+ * Pauses the target.
+ * All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed.
+ * If the target is not present, nothing happens.
+ *
+ * @param {cc.Class} target
+ */
+ pauseTarget:function (target) {
+
+ cc.assert(target, cc._LogInfos.Scheduler_pauseTarget);
+
+ //customer selectors
+ var self = this, element = self._hashForTimers[target.__instanceId];
+ if (element) {
+ element.paused = true;
+ }
+
+ //update callback
+ var elementUpdate = self._hashForUpdates[target.__instanceId];
+ if (elementUpdate) {
+ elementUpdate.entry.paused = true;
+ }
+ },
+
+ /**
+ * Resumes the target.
+ * Schedules the 'update' callback_fn for a given target with a given priority.
+ * The 'update' callback_fn will be called every frame.
+ * The lower the priority, the earlier it is called.
+ *
+ * @deprecated since v3.4 please use .scheduleUpdate
+ * @param {cc.Class} target
+ * @param {Number} priority
+ * @param {Boolean} paused
+ * @example
+ * //register this object to scheduler
+ * cc.director.getScheduler().scheduleUpdateForTarget(this, priority, !this._isRunning );
+ */
+ scheduleUpdateForTarget: function(target, priority, paused){
+ //cc.log("scheduleUpdateForTarget is deprecated. Please use scheduleUpdate.");
+ this.scheduleUpdate(target, priority, paused);
+ },
+
+ /**
+ *
+ * Unschedule a callback function for a given target.
+ * If you want to unschedule the "update", use unscheudleUpdateForTarget.
+ *
+ * @deprecated since v3.4 please use .unschedule
+ * @param {cc.Class} target
+ * @param {function} callback callback[Function] or key[String]
+ * @example
+ * //unschedule a callback of target
+ * cc.director.getScheduler().unscheduleCallbackForTarget(function, this);
+ */
+ unscheduleCallbackForTarget:function (target, callback) {
+ //cc.log("unscheduleCallbackForTarget is deprecated. Please use unschedule.");
+ this.unschedule(callback, target);
+ },
+
+ /**
+ * Unschedules the update callback function for a given target
+ * @param {cc.Class} target
+ * @deprecated since v3.4 please use .unschedule
+ * @example
+ * //unschedules the "update" method.
+ * cc.director.getScheduler().unscheduleUpdateForTarget(this);
+ */
+ unscheduleUpdateForTarget:function (target) {
+ //cc.log("unscheduleUpdateForTarget is deprecated. Please use unschedule.");
+ this.unscheduleUpdate(target);
+ },
+
+ /**
+ * Unschedules all function callbacks for a given target. This also includes the "update" callback function.
+ * @deprecated since v3.4 please use .unscheduleAll
+ * @param {cc.Class} target
+ */
+ unscheduleAllCallbacksForTarget: function(target){
+ //cc.log("unscheduleAllCallbacksForTarget is deprecated. Please use unscheduleAll.");
+ this.unschedule(target.__instanceId + "", target);
+ },
+
+ /**
+ *
+ * Unschedules all function callbacks from all targets.
+ * You should NEVER call this method, unless you know what you are doing.
+ *
+ * @deprecated since v3.4 please use .unscheduleAllWithMinPriority
+ */
+ unscheduleAllCallbacks: function(){
+ //cc.log("unscheduleAllCallbacks is deprecated. Please use unscheduleAll.");
+ this.unscheduleAllWithMinPriority(cc.Scheduler.PRIORITY_SYSTEM);
+ },
+
+ /**
+ *
+ * Unschedules all function callbacks from all targets with a minimum priority.
+ * You should only call this with kCCPriorityNonSystemMin or higher.
+ *
+ * @deprecated since v3.4 please use .unscheduleAllWithMinPriority
+ * @param {Number} minPriority
+ */
+ unscheduleAllCallbacksWithMinPriority:function (minPriority) {
+ //cc.log("unscheduleAllCallbacksWithMinPriority is deprecated. Please use unscheduleAllWithMinPriority.");
+ this.unscheduleAllWithMinPriority(minPriority);
+ }
+});
+
+/**
+ * Priority level reserved for system services.
+ * @constant
+ * @type Number
+ */
+cc.Scheduler.PRIORITY_SYSTEM = (-2147483647 - 1);
+
+/**
+ * Minimum priority level for user scheduling.
+ * @constant
+ * @type Number
+ */
+cc.Scheduler.PRIORITY_NON_SYSTEM = cc.Scheduler.PRIORITY_SYSTEM + 1;
+
+})();
diff --git a/cocos2d/core/base-nodes/BaseNodesPropertyDefine.js b/cocos2d/core/base-nodes/BaseNodesPropertyDefine.js
new file mode 100644
index 0000000000..2b2639cd89
--- /dev/null
+++ b/cocos2d/core/base-nodes/BaseNodesPropertyDefine.js
@@ -0,0 +1,127 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc._tmp.PrototypeCCNode = function () {
+
+ var _p = cc.Node.prototype;
+
+ cc.defineGetterSetter(_p, "x", _p.getPositionX, _p.setPositionX);
+ cc.defineGetterSetter(_p, "y", _p.getPositionY, _p.setPositionY);
+ /** @expose */
+ _p.width;
+ cc.defineGetterSetter(_p, "width", _p._getWidth, _p._setWidth);
+ /** @expose */
+ _p.height;
+ cc.defineGetterSetter(_p, "height", _p._getHeight, _p._setHeight);
+ /** @expose */
+ _p.anchorX;
+ cc.defineGetterSetter(_p, "anchorX", _p._getAnchorX, _p._setAnchorX);
+ /** @expose */
+ _p.anchorY;
+ cc.defineGetterSetter(_p, "anchorY", _p._getAnchorY, _p._setAnchorY);
+ /** @expose */
+ _p.skewX;
+ cc.defineGetterSetter(_p, "skewX", _p.getSkewX, _p.setSkewX);
+ /** @expose */
+ _p.skewY;
+ cc.defineGetterSetter(_p, "skewY", _p.getSkewY, _p.setSkewY);
+ /** @expose */
+ _p.zIndex;
+ cc.defineGetterSetter(_p, "zIndex", _p.getLocalZOrder, _p.setLocalZOrder);
+ /** @expose */
+ _p.vertexZ;
+ cc.defineGetterSetter(_p, "vertexZ", _p.getVertexZ, _p.setVertexZ);
+ /** @expose */
+ _p.rotation;
+ cc.defineGetterSetter(_p, "rotation", _p.getRotation, _p.setRotation);
+ /** @expose */
+ _p.rotationX;
+ cc.defineGetterSetter(_p, "rotationX", _p.getRotationX, _p.setRotationX);
+ /** @expose */
+ _p.rotationY;
+ cc.defineGetterSetter(_p, "rotationY", _p.getRotationY, _p.setRotationY);
+ /** @expose */
+ _p.scale;
+ cc.defineGetterSetter(_p, "scale", _p.getScale, _p.setScale);
+ /** @expose */
+ _p.scaleX;
+ cc.defineGetterSetter(_p, "scaleX", _p.getScaleX, _p.setScaleX);
+ /** @expose */
+ _p.scaleY;
+ cc.defineGetterSetter(_p, "scaleY", _p.getScaleY, _p.setScaleY);
+ /** @expose */
+ _p.children;
+ cc.defineGetterSetter(_p, "children", _p.getChildren);
+ /** @expose */
+ _p.childrenCount;
+ cc.defineGetterSetter(_p, "childrenCount", _p.getChildrenCount);
+ /** @expose */
+ _p.parent;
+ cc.defineGetterSetter(_p, "parent", _p.getParent, _p.setParent);
+ /** @expose */
+ _p.visible;
+ cc.defineGetterSetter(_p, "visible", _p.isVisible, _p.setVisible);
+ /** @expose */
+ _p.running;
+ cc.defineGetterSetter(_p, "running", _p.isRunning);
+ /** @expose */
+ _p.ignoreAnchor;
+ cc.defineGetterSetter(_p, "ignoreAnchor", _p.isIgnoreAnchorPointForPosition, _p.ignoreAnchorPointForPosition);
+ /** @expose */
+ _p.tag;
+ /** @expose */
+ _p.userData;
+ /** @expose */
+ _p.userObject;
+ /** @expose */
+ _p.arrivalOrder;
+ /** @expose */
+ _p.actionManager;
+ cc.defineGetterSetter(_p, "actionManager", _p.getActionManager, _p.setActionManager);
+ /** @expose */
+ _p.scheduler;
+ cc.defineGetterSetter(_p, "scheduler", _p.getScheduler, _p.setScheduler);
+ //cc.defineGetterSetter(_p, "boundingBox", _p.getBoundingBox);
+ /** @expose */
+ _p.shaderProgram;
+ cc.defineGetterSetter(_p, "shaderProgram", _p.getShaderProgram, _p.setShaderProgram);
+
+ /** @expose */
+ _p.opacity;
+ cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
+ /** @expose */
+ _p.opacityModifyRGB;
+ cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB);
+ /** @expose */
+ _p.cascadeOpacity;
+ cc.defineGetterSetter(_p, "cascadeOpacity", _p.isCascadeOpacityEnabled, _p.setCascadeOpacityEnabled);
+ /** @expose */
+ _p.color;
+ cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
+ /** @expose */
+ _p.cascadeColor;
+ cc.defineGetterSetter(_p, "cascadeColor", _p.isCascadeColorEnabled, _p.setCascadeColorEnabled);
+};
\ No newline at end of file
diff --git a/cocos2d/core/base-nodes/CCAtlasNode.js b/cocos2d/core/base-nodes/CCAtlasNode.js
new file mode 100644
index 0000000000..336ab7cc57
--- /dev/null
+++ b/cocos2d/core/base-nodes/CCAtlasNode.js
@@ -0,0 +1,295 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.AtlasNode is a subclass of cc.Node, it knows how to render a TextureAtlas object.
+ *
+ * If you are going to render a TextureAtlas consider subclassing cc.AtlasNode (or a subclass of cc.AtlasNode)
+ *
+ * You can create a cc.AtlasNode with an Atlas file, the width, the height of each item and the quantity of items to render
+ *
+ * @class
+ * @extends cc.Node
+ *
+ * @param {String} tile
+ * @param {Number} tileWidth
+ * @param {Number} tileHeight
+ * @param {Number} itemsToRender
+ * @example
+ * var node = new cc.AtlasNode("pathOfTile", 16, 16, 1);
+ *
+ * @property {cc.Texture2D} texture - Current used texture
+ * @property {cc.TextureAtlas} textureAtlas - Texture atlas for cc.AtlasNode
+ * @property {Number} quadsToDraw - Number of quads to draw
+ */
+cc.AtlasNode = cc.Node.extend(/** @lends cc.AtlasNode# */{
+ textureAtlas: null,
+ quadsToDraw: 0,
+
+ //! chars per row
+ _itemsPerRow: 0,
+ //! chars per column
+ _itemsPerColumn: 0,
+ //! width of each char
+ _itemWidth: 0,
+ //! height of each char
+ _itemHeight: 0,
+
+ // protocol variables
+ _opacityModifyRGB: false,
+ _blendFunc: null,
+
+ // This variable is only used for CCLabelAtlas FPS display. So plz don't modify its value.
+ _ignoreContentScaleFactor: false,
+ _className: "AtlasNode",
+
+ _texture: null,
+ _textureForCanvas: null,
+
+ /**
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {String} tile
+ * @param {Number} tileWidth
+ * @param {Number} tileHeight
+ * @param {Number} itemsToRender
+ */
+ ctor: function (tile, tileWidth, tileHeight, itemsToRender) {
+ cc.Node.prototype.ctor.call(this);
+ this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
+ this._ignoreContentScaleFactor = false;
+ itemsToRender !== undefined && this.initWithTileFile(tile, tileWidth, tileHeight, itemsToRender);
+ },
+
+ _createRenderCmd: function(){
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ this._renderCmd = new cc.AtlasNode.CanvasRenderCmd(this);
+ else
+ this._renderCmd = new cc.AtlasNode.WebGLRenderCmd(this);
+ },
+
+ /**
+ * Updates the Atlas (indexed vertex array).
+ * Empty implementation, shall be overridden in subclasses
+ * @function
+ */
+ updateAtlasValues: function () {
+ cc.log(cc._LogInfos.AtlasNode_updateAtlasValues);
+ },
+
+ /**
+ * Get color value of the atlas node
+ * @function
+ * @return {cc.Color}
+ */
+ getColor: function () {
+ if (this._opacityModifyRGB)
+ return this._renderCmd._colorUnmodified;
+ return cc.Node.prototype.getColor.call(this);
+ },
+
+ /**
+ * Set whether color should be changed with the opacity value,
+ * if true, node color will change while opacity changes.
+ * @function
+ * @param {Boolean} value
+ */
+ setOpacityModifyRGB: function (value) {
+ var oldColor = this.color;
+ this._opacityModifyRGB = value;
+ this.setColor(oldColor);
+ },
+
+ /**
+ * Get whether color should be changed with the opacity value
+ * @function
+ * @return {Boolean}
+ */
+ isOpacityModifyRGB: function () {
+ return this._opacityModifyRGB;
+ },
+
+ /**
+ * Get node's blend function
+ * @function
+ * @return {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ return this._blendFunc;
+ },
+
+ /**
+ * Set node's blend function
+ * This function accept either cc.BlendFunc object or source value and destination value
+ * @function
+ * @param {Number | cc.BlendFunc} src
+ * @param {Number} dst
+ */
+ setBlendFunc: function (src, dst) {
+ if (dst === undefined)
+ this._blendFunc = src;
+ else
+ this._blendFunc = {src: src, dst: dst};
+ },
+
+ /**
+ * Set the atlas texture
+ * @function
+ * @param {cc.TextureAtlas} value The texture
+ */
+ setTextureAtlas: function (value) {
+ this.textureAtlas = value;
+ },
+
+ /**
+ * Get the atlas texture
+ * @function
+ * @return {cc.TextureAtlas}
+ */
+ getTextureAtlas: function () {
+ return this.textureAtlas;
+ },
+
+ /**
+ * Get the number of quads to be rendered
+ * @function
+ * @return {Number}
+ */
+ getQuadsToDraw: function () {
+ return this.quadsToDraw;
+ },
+
+ /**
+ * Set the number of quads to be rendered
+ * @function
+ * @param {Number} quadsToDraw
+ */
+ setQuadsToDraw: function (quadsToDraw) {
+ this.quadsToDraw = quadsToDraw;
+ },
+
+ /**
+ * Initializes an cc.AtlasNode object with an atlas texture file name, the width, the height of each tile and the quantity of tiles to render
+ * @function
+ * @param {String} tile The atlas texture file name
+ * @param {Number} tileWidth The width of each tile
+ * @param {Number} tileHeight The height of each tile
+ * @param {Number} itemsToRender The quantity of tiles to be rendered
+ * @return {Boolean}
+ */
+ initWithTileFile: function (tile, tileWidth, tileHeight, itemsToRender) {
+ if (!tile)
+ throw new Error("cc.AtlasNode.initWithTileFile(): title should not be null");
+ var texture = cc.textureCache.addImage(tile);
+ return this.initWithTexture(texture, tileWidth, tileHeight, itemsToRender);
+ },
+
+ /**
+ * Initializes an CCAtlasNode with an atlas texture, the width, the height of each tile and the quantity of tiles to render
+ * @function
+ * @param {cc.Texture2D} texture The atlas texture
+ * @param {Number} tileWidth The width of each tile
+ * @param {Number} tileHeight The height of each tile
+ * @param {Number} itemsToRender The quantity of tiles to be rendered
+ * @return {Boolean}
+ */
+ initWithTexture: function(texture, tileWidth, tileHeight, itemsToRender){
+ return this._renderCmd.initWithTexture(texture, tileWidth, tileHeight, itemsToRender);
+ },
+
+ /**
+ * Set node's color
+ * @function
+ * @param {cc.Color} color Color object created with cc.color(r, g, b).
+ */
+ setColor: function(color){
+ this._renderCmd.setColor(color);
+ },
+
+ /**
+ * Set node's opacity
+ * @function
+ * @param {Number} opacity The opacity value
+ */
+ setOpacity: function (opacity) {
+ this._renderCmd.setOpacity(opacity);
+ },
+
+ /**
+ * Get the current texture
+ * @function
+ * @return {cc.Texture2D}
+ */
+ getTexture: function(){
+ return this._texture;
+ },
+
+ /**
+ * Replace the current texture with a new one
+ * @function
+ * @param {cc.Texture2D} texture The new texture
+ */
+ setTexture: function(texture){
+ this._texture = texture;
+ },
+
+ _setIgnoreContentScaleFactor: function (ignoreContentScaleFactor) {
+ this._ignoreContentScaleFactor = ignoreContentScaleFactor;
+ }
+});
+
+
+var _p = cc.AtlasNode.prototype;
+// Override properties
+cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
+cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
+
+// Extended properties
+/** @expose */
+_p.texture;
+cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
+/** @expose */
+_p.textureAtlas;
+/** @expose */
+_p.quadsToDraw;
+
+cc.EventHelper.prototype.apply(_p);
+
+/**
+ * Creates a cc.AtlasNode with an Atlas file the width and height of each item and the quantity of items to render
+ * @deprecated since v3.0, please use new construction instead
+ * @function
+ * @static
+ * @param {String} tile
+ * @param {Number} tileWidth
+ * @param {Number} tileHeight
+ * @param {Number} itemsToRender
+ * @return {cc.AtlasNode}
+ */
+cc.AtlasNode.create = function (tile, tileWidth, tileHeight, itemsToRender) {
+ return new cc.AtlasNode(tile, tileWidth, tileHeight, itemsToRender);
+};
\ No newline at end of file
diff --git a/cocos2d/core/base-nodes/CCAtlasNodeCanvasRenderCmd.js b/cocos2d/core/base-nodes/CCAtlasNodeCanvasRenderCmd.js
new file mode 100644
index 0000000000..4fb324f4a9
--- /dev/null
+++ b/cocos2d/core/base-nodes/CCAtlasNodeCanvasRenderCmd.js
@@ -0,0 +1,91 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.AtlasNode's rendering objects of Canvas
+ */
+(function () {
+ cc.AtlasNode.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = false;
+ this._colorUnmodified = cc.color.WHITE;
+ this._textureToRender = null;
+ };
+
+ var proto = cc.AtlasNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.AtlasNode.CanvasRenderCmd;
+
+ proto.initWithTexture = function (texture, tileWidth, tileHeight, itemsToRender) {
+ var node = this._node;
+ node._itemWidth = tileWidth;
+ node._itemHeight = tileHeight;
+
+ node._opacityModifyRGB = true;
+ node._texture = texture;
+ if (!node._texture) {
+ cc.log(cc._LogInfos.AtlasNode__initWithTexture);
+ return false;
+ }
+ this._textureToRender = texture;
+ this._calculateMaxItems();
+
+ node.quadsToDraw = itemsToRender;
+ return true;
+ };
+
+ proto.setColor = function (color3) {
+ var node = this._node;
+ var locRealColor = node._realColor;
+ if ((locRealColor.r === color3.r) && (locRealColor.g === color3.g) && (locRealColor.b === color3.b))
+ return;
+ this._colorUnmodified = color3;
+ this._changeTextureColor();
+ };
+
+ proto._changeTextureColor = function () {
+ var node = this._node;
+ var texture = node._texture,
+ color = this._colorUnmodified,
+ element = texture.getHtmlElementObj();
+ var textureRect = cc.rect(0, 0, element.width, element.height);
+ if (texture === this._textureToRender)
+ this._textureToRender = texture._generateColorTexture(color.r, color.g, color.b, textureRect);
+ else
+ texture._generateColorTexture(color.r, color.g, color.b, textureRect, this._textureToRender.getHtmlElementObj());
+ };
+
+ proto.setOpacity = function (opacity) {
+ var node = this._node;
+ cc.Node.prototype.setOpacity.call(node, opacity);
+ };
+
+ proto._calculateMaxItems = function () {
+ var node = this._node;
+ var selTexture = node._texture;
+ var size = selTexture.getContentSize();
+
+ node._itemsPerColumn = 0 | (size.height / node._itemHeight);
+ node._itemsPerRow = 0 | (size.width / node._itemWidth);
+ };
+})();
diff --git a/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js
new file mode 100644
index 0000000000..5810d00794
--- /dev/null
+++ b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js
@@ -0,0 +1,159 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.AtlasNode's rendering objects of WebGL
+ */
+(function () {
+ cc.AtlasNode.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._textureAtlas = null;
+ this._colorUnmodified = cc.color.WHITE;
+ this._colorF32Array = null;
+ this._uniformColor = null;
+
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+
+ //shader stuff
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR);
+ this._uniformColor = cc._renderContext.getUniformLocation(this._shaderProgram.getProgram(), "u_color");
+ };
+
+ var proto = cc.AtlasNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.AtlasNode.WebGLRenderCmd;
+
+ proto._updateBlendFunc = function () {
+ var node = this._node;
+ if (!this._textureAtlas.texture.hasPremultipliedAlpha()) {
+ node._blendFunc.src = cc.SRC_ALPHA;
+ node._blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
+ }
+ };
+
+ proto._updateOpacityModifyRGB = function () {
+ this._node._opacityModifyRGB = this._textureAtlas.texture.hasPremultipliedAlpha();
+ };
+
+ proto.rendering = function (ctx) {
+ var context = ctx || cc._renderContext, node = this._node;
+
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ this._glProgramState.apply(this._matrix);
+
+ cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
+ if (this._uniformColor && this._colorF32Array) {
+ context.uniform4fv(this._uniformColor, this._colorF32Array);
+ this._textureAtlas.drawNumberOfQuads(node.quadsToDraw, 0);
+ }
+ };
+
+ proto.initWithTexture = function (texture, tileWidth, tileHeight, itemsToRender) {
+ var node = this._node;
+ node._itemWidth = tileWidth;
+ node._itemHeight = tileHeight;
+ this._colorUnmodified = cc.color.WHITE;
+ node._opacityModifyRGB = true;
+
+ node._blendFunc.src = cc.BLEND_SRC;
+ node._blendFunc.dst = cc.BLEND_DST;
+
+ var locRealColor = node._realColor;
+ this._colorF32Array = new Float32Array([locRealColor.r / 255.0, locRealColor.g / 255.0, locRealColor.b / 255.0, node._realOpacity / 255.0]);
+ this._textureAtlas = new cc.TextureAtlas();
+ this._textureAtlas.initWithTexture(texture, itemsToRender);
+
+ if (!this._textureAtlas) {
+ cc.log(cc._LogInfos.AtlasNode__initWithTexture);
+ return false;
+ }
+
+ this._updateBlendFunc();
+ this._updateOpacityModifyRGB();
+ this._calculateMaxItems();
+ node.quadsToDraw = itemsToRender;
+
+ return true;
+ };
+
+ proto.setColor = function (color3) {
+ var temp = cc.color(color3.r, color3.g, color3.b), node = this._node;
+ this._colorUnmodified = color3;
+ var locDisplayedOpacity = this._displayedOpacity;
+ if (node._opacityModifyRGB) {
+ temp.r = temp.r * locDisplayedOpacity / 255;
+ temp.g = temp.g * locDisplayedOpacity / 255;
+ temp.b = temp.b * locDisplayedOpacity / 255;
+ }
+ cc.Node.prototype.setColor.call(node, temp);
+ };
+
+ proto.setOpacity = function (opacity) {
+ var node = this._node;
+ cc.Node.prototype.setOpacity.call(node, opacity);
+ // special opacity for premultiplied textures
+ if (node._opacityModifyRGB) {
+ node.color = this._colorUnmodified;
+ }
+ };
+
+ proto._updateColor = function () {
+ if (this._colorF32Array) {
+ var locDisplayedColor = this._displayedColor;
+ this._colorF32Array[0] = locDisplayedColor.r / 255.0;
+ this._colorF32Array[1] = locDisplayedColor.g / 255.0;
+ this._colorF32Array[2] = locDisplayedColor.b / 255.0;
+ this._colorF32Array[3] = this._displayedOpacity / 255.0;
+ }
+ };
+
+ proto.getTexture = function () {
+ return this._textureAtlas.texture;
+ };
+
+ proto.setTexture = function (texture) {
+ this._textureAtlas.texture = texture;
+ this._updateBlendFunc();
+ this._updateOpacityModifyRGB();
+ };
+
+ proto._calculateMaxItems = function () {
+ var node = this._node;
+ var selTexture = this._textureAtlas.texture;
+ var size = selTexture.getContentSize();
+ if (node._ignoreContentScaleFactor)
+ size = selTexture.getContentSizeInPixels();
+
+ node._itemsPerColumn = 0 | (size.height / node._itemHeight);
+ node._itemsPerRow = 0 | (size.width / node._itemWidth);
+ };
+})();
diff --git a/cocos2d/core/base-nodes/CCNode.js b/cocos2d/core/base-nodes/CCNode.js
new file mode 100644
index 0000000000..9d3e6f15e5
--- /dev/null
+++ b/cocos2d/core/base-nodes/CCNode.js
@@ -0,0 +1,2604 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * Default Node tag
+ * @constant
+ * @type Number
+ */
+cc.NODE_TAG_INVALID = -1;
+
+/**
+ * XXX: Yes, nodes might have a sort problem once every 15 days if the game runs at 60 FPS and each frame sprites are reordered.
+ */
+cc.s_globalOrderOfArrival = 1;
+
+/**
+ * cc.Node is the root class of all node. Anything that gets drawn or contains things that get drawn is a cc.Node.
+ * The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu.
+ *
+ * Some cc.Node nodes provide extra functionality for them or their children.
+ *
+ * Properties configuration function
+ * All properties in attrs will be set to the node,
+ * when the setter of the node is available,
+ * the property will be set via setter function.
+ *
+ * @function
+ * @param {Object} attrs Properties to be set to node
+ */
+ attr: function (attrs) {
+ for (var key in attrs) {
+ this[key] = attrs[key];
+ }
+ },
+
+ /**
+ * Returns the skew degrees in X
+ * The X skew angle of the node in degrees.
+ * This angle describes the shear distortion in the X direction.
+ * Thus, it is the angle between the Y axis and the left edge of the shape
+ * The default skewX angle is 0. Positive values distort the node in a CW direction.
+ *
+ * @function
+ * @return {Number} The X skew angle of the node in degrees.
+ */
+ getSkewX: function () {
+ return this._skewX;
+ },
+
+ /**
+ *
+ * Changes the X skew angle of the node in degrees.
+ *
+ * This angle describes the shear distortion in the X direction.
+ * Thus, it is the angle between the Y axis and the left edge of the shape
+ * The default skewX angle is 0. Positive values distort the node in a CW direction.
+ *
+ * @function
+ * @param {Number} newSkewX The X skew angle of the node in degrees.
+ */
+ setSkewX: function (newSkewX) {
+ this._skewX = newSkewX;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the skew degrees in Y
+ * The Y skew angle of the node in degrees.
+ * This angle describes the shear distortion in the Y direction.
+ * Thus, it is the angle between the X axis and the bottom edge of the shape
+ * The default skewY angle is 0. Positive values distort the node in a CCW direction.
+ *
+ * @function
+ * @return {Number} The Y skew angle of the node in degrees.
+ */
+ getSkewY: function () {
+ return this._skewY;
+ },
+
+ /**
+ *
+ * Changes the Y skew angle of the node in degrees.
+ *
+ * This angle describes the shear distortion in the Y direction.
+ * Thus, it is the angle between the X axis and the bottom edge of the shape
+ * The default skewY angle is 0. Positive values distort the node in a CCW direction.
+ *
+ * @function
+ * @param {Number} newSkewY The Y skew angle of the node in degrees.
+ */
+ setSkewY: function (newSkewY) {
+ this._skewY = newSkewY;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * LocalZOrder is the 'key' used to sort the node relative to its siblings.
+ *
+ * The Node's parent will sort all its children based ont the LocalZOrder value.
+ * If two nodes have the same LocalZOrder, then the node that was added first to the children's array
+ * will be in front of the other node in the array.
+ *
+ * Also, the Scene Graph is traversed using the "In-Order" tree traversal algorithm ( http://en.wikipedia.org/wiki/Tree_traversal#In-order )
+ *
+ * And Nodes that have LocalZOder values < 0 are the "left" subtree
+ * While Nodes with LocalZOder >=0 are the "right" subtree.
+ * @function
+ * @param {Number} localZOrder
+ */
+ setLocalZOrder: function (localZOrder) {
+ if (localZOrder === this._localZOrder)
+ return;
+ if (this._parent)
+ this._parent.reorderChild(this, localZOrder);
+ else
+ this._localZOrder = localZOrder;
+ cc.eventManager._setDirtyForNode(this);
+ },
+
+ //Helper function used by `setLocalZOrder`. Don't use it unless you know what you are doing.
+ _setLocalZOrder: function (localZOrder) {
+ this._localZOrder = localZOrder;
+ },
+
+ /**
+ * Returns the local Z order of this node.
+ * @function
+ * @returns {Number} The local (relative to its siblings) Z order.
+ */
+ getLocalZOrder: function () {
+ return this._localZOrder;
+ },
+
+ /**
+ * Returns z order of this node
+ * @function
+ * @return {Number}
+ * @deprecated since 3.0, please use getLocalZOrder instead
+ */
+ getZOrder: function () {
+ cc.log(cc._LogInfos.Node_getZOrder);
+ return this.getLocalZOrder();
+ },
+
+ /**
+ *
+ * Sets the Z order which stands for the drawing order, and reorder this node in its parent's children array.
+ *
+ * The Z order of node is relative to its "brothers": children of the same parent.
+ * It's nothing to do with OpenGL's z vertex. This one only affects the draw order of nodes in cocos2d.
+ * The larger number it is, the later this node will be drawn in each message loop.
+ * Please refer to setVertexZ(float) for the difference.
+ *
+ * @function
+ * @param {Number} z Z order of this node.
+ * @deprecated since 3.0, please use setLocalZOrder instead
+ */
+ setZOrder: function (z) {
+ cc.log(cc._LogInfos.Node_setZOrder);
+ this.setLocalZOrder(z);
+ },
+
+ /**
+ * Defines the oder in which the nodes are renderer.
+ * Nodes that have a Global Z Order lower, are renderer first.
+ *
+ * In case two or more nodes have the same Global Z Order, the oder is not guaranteed.
+ * The only exception if the Nodes have a Global Z Order == 0. In that case, the Scene Graph order is used.
+ *
+ * By default, all nodes have a Global Z Order = 0. That means that by default, the Scene Graph order is used to render the nodes.
+ *
+ * Global Z Order is useful when you need to render nodes in an order different than the Scene Graph order.
+ *
+ * Limitations: Global Z Order can't be used used by Nodes that have SpriteBatchNode as one of their ancestors.
+ * And if ClippingNode is one of the ancestors, then "global Z order" will be relative to the ClippingNode.
+ * @function
+ * @param {Number} globalZOrder
+ */
+ setGlobalZOrder: function (globalZOrder) {
+ if (this._globalZOrder !== globalZOrder) {
+ this._globalZOrder = globalZOrder;
+ cc.eventManager._setDirtyForNode(this);
+ }
+ },
+
+ /**
+ * Return the Node's Global Z Order.
+ * @function
+ * @returns {number} The node's global Z order
+ */
+ getGlobalZOrder: function () {
+ return this._globalZOrder;
+ },
+
+ /**
+ * Returns WebGL Z vertex of this node.
+ * @function
+ * @return {Number} WebGL Z vertex of this node
+ */
+ getVertexZ: function () {
+ return this._vertexZ;
+ },
+
+ /**
+ *
+ * Sets the real WebGL Z vertex.
+ *
+ * Differences between openGL Z vertex and cocos2d Z order:
+ * - WebGL Z modifies the Z vertex, and not the Z order in the relation between parent-children
+ * - WebGL Z might require to set 2D projection
+ * - cocos2d Z order works OK if all the nodes uses the same WebGL Z vertex. eg: vertexZ = 0
+ *
+ * @warning Use it at your own risk since it might break the cocos2d parent-children z order
+ *
+ * @function
+ * @param {Number} Var
+ */
+ setVertexZ: function (Var) {
+ this._customZ = this._vertexZ = Var;
+ },
+
+ /**
+ * Returns the rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node clockwise.
+ * @function
+ * @return {Number} The rotation of the node in degrees.
+ */
+ getRotation: function () {
+ if (this._rotationX !== this._rotationY)
+ cc.log(cc._LogInfos.Node_getRotation);
+ return this._rotationX;
+ },
+
+ /**
+ *
+ * Sets the rotation (angle) of the node in degrees.
+ *
+ * 0 is the default rotation angle.
+ * Positive values rotate node clockwise, and negative values for anti-clockwise.
+ *
+ * @function
+ * @param {Number} newRotation The rotation of the node in degrees.
+ */
+ setRotation: function (newRotation) {
+ this._rotationX = this._rotationY = newRotation;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the X axis rotation (angle) which represent a horizontal rotational skew of the node in degrees.
+ * 0 is the default rotation angle. Positive values rotate node clockwise
+ * (support only in WebGL rendering mode)
+ * @function
+ * @return {Number} The X rotation in degrees.
+ */
+ getRotationX: function () {
+ return this._rotationX;
+ },
+
+ /**
+ *
+ * Sets the X rotation (angle) of the node in degrees which performs a horizontal rotational skew.
+ * (support only in WebGL rendering mode)
+ * 0 is the default rotation angle.
+ * Positive values rotate node clockwise, and negative values for anti-clockwise.
+ *
+ * @param {Number} rotationX The X rotation in degrees which performs a horizontal rotational skew.
+ */
+ setRotationX: function (rotationX) {
+ this._rotationX = rotationX;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the Y axis rotation (angle) which represent a vertical rotational skew of the node in degrees.
+ * 0 is the default rotation angle. Positive values rotate node clockwise
+ * (support only in WebGL rendering mode)
+ * @function
+ * @return {Number} The Y rotation in degrees.
+ */
+ getRotationY: function () {
+ return this._rotationY;
+ },
+
+ /**
+ *
+ * Sets the Y rotation (angle) of the node in degrees which performs a vertical rotational skew.
+ * (support only in WebGL rendering mode)
+ * 0 is the default rotation angle.
+ * Positive values rotate node clockwise, and negative values for anti-clockwise.
+ *
+ * @param rotationY The Y rotation in degrees.
+ */
+ setRotationY: function (rotationY) {
+ this._rotationY = rotationY;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the scale factor of the node.
+ * @warning: Assertion will fail when _scaleX != _scaleY.
+ * @function
+ * @return {Number} The scale factor
+ */
+ getScale: function () {
+ if (this._scaleX !== this._scaleY)
+ cc.log(cc._LogInfos.Node_getScale);
+ return this._scaleX;
+ },
+
+ /**
+ * Sets the scale factor of the node. 1.0 is the default scale factor. This function can modify the X and Y scale at the same time.
+ * @function
+ * @param {Number} scale or scaleX value
+ * @param {Number} [scaleY=]
+ */
+ setScale: function (scale, scaleY) {
+ this._scaleX = scale;
+ this._scaleY = (scaleY || scaleY === 0) ? scaleY : scale;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the scale factor on X axis of this node
+ * @function
+ * @return {Number} The scale factor on X axis.
+ */
+ getScaleX: function () {
+ return this._scaleX;
+ },
+
+ /**
+ *
+ * Changes the scale factor on X axis of this node
+ * The default value is 1.0 if you haven't changed it before
+ *
+ * @function
+ * @param {Number} newScaleX The scale factor on X axis.
+ */
+ setScaleX: function (newScaleX) {
+ this._scaleX = newScaleX;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the scale factor on Y axis of this node
+ * @function
+ * @return {Number} The scale factor on Y axis.
+ */
+ getScaleY: function () {
+ return this._scaleY;
+ },
+
+ /**
+ *
+ * Changes the scale factor on Y axis of this node
+ * The Default value is 1.0 if you haven't changed it before.
+ *
+ * @function
+ * @param {Number} newScaleY The scale factor on Y axis.
+ */
+ setScaleY: function (newScaleY) {
+ this._scaleY = newScaleY;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ *
+ * Changes the position (x,y) of the node in cocos2d coordinates.
+ * The original point (0,0) is at the left-bottom corner of screen.
+ * Usually we use cc.p(x,y) to compose CCPoint object.
+ * and Passing two numbers (x,y) is more efficient than passing CCPoint object.
+ *
+ * @function
+ * @param {cc.Point|Number} newPosOrxValue The position (x,y) of the node in coordinates or the X coordinate for position
+ * @param {Number} [yValue] Y coordinate for position
+ * @example
+ * var size = cc.winSize;
+ * node.setPosition(size.width/2, size.height/2);
+ */
+ setPosition: function (newPosOrxValue, yValue) {
+ var locPosition = this._position;
+ if (yValue === undefined) {
+ if (locPosition.x === newPosOrxValue.x && locPosition.y === newPosOrxValue.y)
+ return;
+ locPosition.x = newPosOrxValue.x;
+ locPosition.y = newPosOrxValue.y;
+ } else {
+ if (locPosition.x === newPosOrxValue && locPosition.y === yValue)
+ return;
+ locPosition.x = newPosOrxValue;
+ locPosition.y = yValue;
+ }
+ this._usingNormalizedPosition = false;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ *
+ * Sets the position (x,y) using values between 0 and 1.
+ * The positions in pixels is calculated like the following:
+ * _position = _normalizedPosition * parent.getContentSize()
+ *
+ * @param {cc.Point|Number} posOrX
+ * @param {Number} [y]
+ */
+ setNormalizedPosition: function(posOrX, y){
+ var locPosition = this._normalizedPosition;
+ if (y === undefined) {
+ locPosition.x = posOrX.x;
+ locPosition.y = posOrX.y;
+ } else {
+ locPosition.x = posOrX;
+ locPosition.y = y;
+ }
+ this._normalizedPositionDirty = this._usingNormalizedPosition = true;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns a copy of the position (x,y) of the node in cocos2d coordinates. (0,0) is the left-bottom corner.
+ * @function
+ * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates
+ */
+ getPosition: function () {
+ return cc.p(this._position);
+ },
+
+ /**
+ * returns the normalized position
+ * @returns {cc.Point}
+ */
+ getNormalizedPosition: function(){
+ return cc.p(this._normalizedPosition);
+ },
+
+ /**
+ * Returns the x axis position of the node in cocos2d coordinates.
+ * @function
+ * @return {Number}
+ */
+ getPositionX: function () {
+ return this._position.x;
+ },
+
+ /**
+ * Sets the x axis position of the node in cocos2d coordinates.
+ * @function
+ * @param {Number} x The new position in x axis
+ */
+ setPositionX: function (x) {
+ this._position.x = x;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the y axis position of the node in cocos2d coordinates.
+ * @function
+ * @return {Number}
+ */
+ getPositionY: function () {
+ return this._position.y;
+ },
+
+ /**
+ * Sets the y axis position of the node in cocos2d coordinates.
+ * @function
+ * @param {Number} y The new position in y axis
+ */
+ setPositionY: function (y) {
+ this._position.y = y;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the amount of children.
+ * @function
+ * @return {Number} The amount of children.
+ */
+ getChildrenCount: function () {
+ return this._children.length;
+ },
+
+ /**
+ * Returns an array of all children
+ * Composing a "tree" structure is a very important feature of CCNode
+ * @function
+ * @return {Array} An array of children
+ * @example
+ * //This sample code traverses all children nodes, and set their position to (0,0)
+ * var allChildren = parent.getChildren();
+ * for(var i = 0; i< allChildren.length; i++) {
+ * allChildren[i].setPosition(0,0);
+ * }
+ */
+ getChildren: function () {
+ return this._children;
+ },
+
+ /**
+ * Returns if the node is visible
+ * @function
+ * @see cc.Node#setVisible
+ * @return {Boolean} true if the node is visible, false if the node is hidden.
+ */
+ isVisible: function () {
+ return this._visible;
+ },
+
+ /**
+ * Sets whether the node is visible
+ * The default value is true
+ * @function
+ * @param {Boolean} visible Pass true to make the node visible, false to hide the node.
+ */
+ setVisible: function (visible) {
+ if (this._visible !== visible) {
+ this._visible = visible;
+ //if(visible)
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ cc.renderer.childrenOrderDirty = true;
+ }
+ },
+
+ /**
+ * Returns a copy of the anchor point.
+ * Anchor point is the point around which all transformations and positioning manipulations take place.
+ * It's like a pin in the node where it is "attached" to its parent.
+ * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
+ * But you can use values higher than (1,1) and lower than (0,0) too.
+ * The default anchor point is (0.5,0.5), so it starts at the center of the node.
+ * @function
+ * @return {cc.Point} The anchor point of node.
+ */
+ getAnchorPoint: function () {
+ return cc.p(this._anchorPoint);
+ },
+
+ /**
+ *
+ * Sets the anchor point in percent.
+ *
+ * anchor point is the point around which all transformations and positioning manipulations take place.
+ * It's like a pin in the node where it is "attached" to its parent.
+ * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
+ * But you can use values higher than (1,1) and lower than (0,0) too.
+ * The default anchor point is (0.5,0.5), so it starts at the center of the node.
+ *
+ * @function
+ * @param {cc.Point|Number} point The anchor point of node or The x axis anchor of node.
+ * @param {Number} [y] The y axis anchor of node.
+ */
+ setAnchorPoint: function (point, y) {
+ var locAnchorPoint = this._anchorPoint;
+ if (y === undefined) {
+ if ((point.x === locAnchorPoint.x) && (point.y === locAnchorPoint.y))
+ return;
+ locAnchorPoint.x = point.x;
+ locAnchorPoint.y = point.y;
+ } else {
+ if ((point === locAnchorPoint.x) && (y === locAnchorPoint.y))
+ return;
+ locAnchorPoint.x = point;
+ locAnchorPoint.y = y;
+ }
+ this._renderCmd._updateAnchorPointInPoint();
+ },
+
+ _getAnchorX: function () {
+ return this._anchorPoint.x;
+ },
+ _setAnchorX: function (x) {
+ if (this._anchorPoint.x === x) return;
+ this._anchorPoint.x = x;
+ this._renderCmd._updateAnchorPointInPoint();
+ },
+ _getAnchorY: function () {
+ return this._anchorPoint.y;
+ },
+ _setAnchorY: function (y) {
+ if (this._anchorPoint.y === y) return;
+ this._anchorPoint.y = y;
+ this._renderCmd._updateAnchorPointInPoint();
+ },
+
+ /**
+ * Returns a copy of the anchor point in absolute pixels.
+ * you can only read it. If you wish to modify it, use setAnchorPoint
+ * @see cc.Node#getAnchorPoint
+ * @function
+ * @return {cc.Point} The anchor point in absolute pixels.
+ */
+ getAnchorPointInPoints: function () {
+ return this._renderCmd.getAnchorPointInPoints();
+ },
+
+ _getWidth: function () {
+ return this._contentSize.width;
+ },
+ _setWidth: function (width) {
+ this._contentSize.width = width;
+ this._renderCmd._updateAnchorPointInPoint();
+ },
+ _getHeight: function () {
+ return this._contentSize.height;
+ },
+ _setHeight: function (height) {
+ this._contentSize.height = height;
+ this._renderCmd._updateAnchorPointInPoint();
+ },
+
+ /**
+ * Returns a copy the untransformed size of the node.
+ * The contentSize remains the same no matter the node is scaled or rotated.
+ * All nodes has a size. Layer and Scene has the same size of the screen by default.
+ * @function
+ * @return {cc.Size} The untransformed size of the node.
+ */
+ getContentSize: function () {
+ return cc.size(this._contentSize);
+ },
+
+ /**
+ *
+ * Sets the untransformed size of the node.
+ *
+ * The contentSize remains the same no matter the node is scaled or rotated.
+ * All nodes has a size. Layer and Scene has the same size of the screen.
+ *
+ * @function
+ * @param {cc.Size|Number} size The untransformed size of the node or The untransformed size's width of the node.
+ * @param {Number} [height] The untransformed size's height of the node.
+ */
+ setContentSize: function (size, height) {
+ var locContentSize = this._contentSize;
+ if (height === undefined) {
+ if ((size.width === locContentSize.width) && (size.height === locContentSize.height))
+ return;
+ locContentSize.width = size.width;
+ locContentSize.height = size.height;
+ } else {
+ if ((size === locContentSize.width) && (height === locContentSize.height))
+ return;
+ locContentSize.width = size;
+ locContentSize.height = height;
+ }
+ this._renderCmd._updateAnchorPointInPoint();
+ },
+
+ /**
+ *
+ * Returns whether or not the node accepts event callbacks.
+ * Running means the node accept event callbacks like onEnter(), onExit(), update()
+ *
+ * @function
+ * @return {Boolean} Whether or not the node is running.
+ */
+ isRunning: function () {
+ return this._running;
+ },
+
+ /**
+ * Returns a reference to the parent node
+ * @function
+ * @return {cc.Node} A reference to the parent node
+ */
+ getParent: function () {
+ return this._parent;
+ },
+
+ /**
+ * Sets the parent node
+ * @param {cc.Node} parent A reference to the parent node
+ */
+ setParent: function (parent) {
+ this._parent = parent;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns whether the anchor point will be ignored when you position this node.
+ * When anchor point ignored, position will be calculated based on the origin point (0, 0) in parent's coordinates.
+ * @function
+ * @see cc.Node#ignoreAnchorPointForPosition
+ * @return {Boolean} true if the anchor point will be ignored when you position this node.
+ */
+ isIgnoreAnchorPointForPosition: function () {
+ return this._ignoreAnchorPointForPosition;
+ },
+
+ /**
+ *
+ * Sets whether the anchor point will be ignored when you position this node.
+ * When anchor point ignored, position will be calculated based on the origin point (0, 0) in parent's coordinates.
+ * This is an internal method, only used by CCLayer and CCScene. Don't call it outside framework.
+ * The default value is false, while in CCLayer and CCScene are true
+ *
+ * @function
+ * @param {Boolean} newValue true if anchor point will be ignored when you position this node
+ */
+ ignoreAnchorPointForPosition: function (newValue) {
+ if (newValue !== this._ignoreAnchorPointForPosition) {
+ this._ignoreAnchorPointForPosition = newValue;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ }
+ },
+
+ /**
+ * Returns a tag that is used to identify the node easily.
+ * @function
+ * @return {Number} An integer that identifies the node.
+ * @example
+ * //You can set tags to node then identify them easily.
+ * // set tags
+ * node1.setTag(TAG_PLAYER);
+ * node2.setTag(TAG_MONSTER);
+ * node3.setTag(TAG_BOSS);
+ * parent.addChild(node1);
+ * parent.addChild(node2);
+ * parent.addChild(node3);
+ * // identify by tags
+ * var allChildren = parent.getChildren();
+ * for(var i = 0; i < allChildren.length; i++){
+ * switch(node.getTag()) {
+ * case TAG_PLAYER:
+ * break;
+ * case TAG_MONSTER:
+ * break;
+ * case TAG_BOSS:
+ * break;
+ * }
+ * }
+ */
+ getTag: function () {
+ return this.tag;
+ },
+
+ /**
+ * Changes the tag that is used to identify the node easily.
+ * Please refer to getTag for the sample code.
+ * @function
+ * @see cc.Node#getTag
+ * @param {Number} tag A integer that identifies the node.
+ */
+ setTag: function (tag) {
+ this.tag = tag;
+ },
+
+ /**
+ * Changes the name that is used to identify the node easily.
+ * @function
+ * @param {String} name
+ */
+ setName: function (name) {
+ this._name = name;
+ },
+
+ /**
+ * Returns a string that is used to identify the node.
+ * @function
+ * @returns {string} A string that identifies the node.
+ */
+ getName: function () {
+ return this._name;
+ },
+
+ /**
+ *
+ * Returns a custom user data pointer
+ * You can set everything in UserData pointer, a data block, a structure or an object.
+ *
+ * @function
+ * @return {object} A custom user data pointer
+ */
+ getUserData: function () {
+ return this.userData;
+ },
+
+ /**
+ *
+ * Sets a custom user data reference
+ * You can set everything in UserData reference, a data block, a structure or an object, etc.
+ *
+ * @function
+ * @warning Don't forget to release the memory manually in JSB, especially before you change this data pointer, and before this node is autoreleased.
+ * @param {object} Var A custom user data
+ */
+ setUserData: function (Var) {
+ this.userData = Var;
+ },
+
+ /**
+ * Returns a user assigned cocos2d object.
+ * Similar to userData, but instead of holding all kinds of data it can only hold a cocos2d object
+ * @function
+ * @return {object} A user assigned CCObject
+ */
+ getUserObject: function () {
+ return this.userObject;
+ },
+
+ /**
+ *
+ * Sets a user assigned cocos2d object
+ * Similar to UserData, but instead of holding all kinds of data it can only hold a cocos2d object
+ * In JSB, the UserObject will be retained once in this method, and the previous UserObject (if existed) will be release.
+ * The UserObject will be released in CCNode's destruction.
+ *
+ * @param {object} newValue A user cocos2d object
+ */
+ setUserObject: function (newValue) {
+ if (this.userObject !== newValue)
+ this.userObject = newValue;
+ },
+
+
+ /**
+ * Returns the arrival order, indicates which children should be added previously.
+ * @function
+ * @return {Number} The arrival order.
+ */
+ getOrderOfArrival: function () {
+ return this.arrivalOrder;
+ },
+
+ /**
+ *
+ * Sets the arrival order when this node has a same ZOrder with other children.
+ *
+ * A node which called addChild subsequently will take a larger arrival order,
+ * If two children have the same Z order, the child with larger arrival order will be drawn later.
+ *
+ * @function
+ * @warning This method is used internally for zOrder sorting, don't change this manually
+ * @param {Number} Var The arrival order.
+ */
+ setOrderOfArrival: function (Var) {
+ this.arrivalOrder = Var;
+ },
+
+ /**
+ * Returns the CCActionManager object that is used by all actions.
+ * (IMPORTANT: If you set a new cc.ActionManager, then previously created actions are going to be removed.)
+ * @function
+ * @see cc.Node#setActionManager
+ * @return {cc.ActionManager} A CCActionManager object.
+ */
+ getActionManager: function () {
+ return this._actionManager || cc.director.getActionManager();
+ },
+
+ /**
+ * Sets the cc.ActionManager object that is used by all actions.
+ * @function
+ * @warning If you set a new CCActionManager, then previously created actions will be removed.
+ * @param {cc.ActionManager} actionManager A CCActionManager object that is used by all actions.
+ */
+ setActionManager: function (actionManager) {
+ if (this._actionManager !== actionManager) {
+ this.stopAllActions();
+ this._actionManager = actionManager;
+ }
+ },
+
+ /**
+ *
+ * Returns the cc.Scheduler object used to schedule all "updates" and timers.
+ *
+ * @function
+ * @return {cc.Scheduler} A CCScheduler object.
+ */
+ getScheduler: function () {
+ return this._scheduler || cc.director.getScheduler();
+ },
+
+ /**
+ *
+ * Sets a CCScheduler object that is used to schedule all "updates" and timers.
+ * IMPORTANT: If you set a new cc.Scheduler, then previously created timers/update are going to be removed.
+ *
+ * @function
+ * @warning If you set a new CCScheduler, then previously created timers/update are going to be removed.
+ * @param scheduler A cc.Scheduler object that is used to schedule all "update" and timers.
+ */
+ setScheduler: function (scheduler) {
+ if (this._scheduler !== scheduler) {
+ this.unscheduleAllCallbacks();
+ this._scheduler = scheduler;
+ }
+ },
+
+ /**
+ * Returns a "local" axis aligned bounding box of the node.
+ * @deprecated since v3.0, please use getBoundingBox instead
+ * @return {cc.Rect}
+ */
+ boundingBox: function () {
+ cc.log(cc._LogInfos.Node_boundingBox);
+ return this.getBoundingBox();
+ },
+
+ /**
+ * Returns a "local" axis aligned bounding box of the node.
+ * The returned box is relative only to its parent.
+ * @function
+ * @return {cc.Rect} The calculated bounding box of the node
+ */
+ getBoundingBox: function () {
+ var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
+ return cc._rectApplyAffineTransformIn(rect, this.getNodeToParentTransform());
+ },
+
+ /**
+ * Stops all running actions and schedulers
+ * @function
+ */
+ cleanup: function () {
+ // actions
+ this.stopAllActions();
+ this.unscheduleAllCallbacks();
+
+ // event
+ cc.eventManager.removeListeners(this);
+ },
+
+ // composition: GET
+ /**
+ * Returns a child from the container given its tag
+ * @function
+ * @param {Number} aTag An identifier to find the child node.
+ * @return {cc.Node} a CCNode object whose tag equals to the input parameter
+ */
+ getChildByTag: function (aTag) {
+ var __children = this._children;
+ if (__children !== null) {
+ for (var i = 0; i < __children.length; i++) {
+ var node = __children[i];
+ if (node && node.tag === aTag)
+ return node;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Returns a child from the container given its name
+ * @function
+ * @param {String} name A name to find the child node.
+ * @return {cc.Node} a CCNode object whose name equals to the input parameter
+ */
+ getChildByName: function (name) {
+ if (!name) {
+ cc.log("Invalid name");
+ return null;
+ }
+
+ var locChildren = this._children;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ if (locChildren[i]._name === name)
+ return locChildren[i];
+ }
+ return null;
+ },
+
+ // composition: ADD
+
+ /** "add" logic MUST only be in this method
+ *
+ * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.
+ * @function
+ * @param {cc.Node} child A child node
+ * @param {Number} [localZOrder=] Z order for drawing priority. Please refer to setZOrder(int)
+ * @param {Number|String} [tag=] An integer or a name to identify the node easily. Please refer to setTag(int) and setName(string)
+ */
+ addChild: function (child, localZOrder, tag) {
+ localZOrder = localZOrder === undefined ? child._localZOrder : localZOrder;
+ var name, setTag = false;
+ if (tag === undefined) {
+ name = child._name;
+ } else if (typeof tag === 'string') {
+ name = tag;
+ tag = undefined;
+ } else if (typeof tag === 'number') {
+ setTag = true;
+ name = "";
+ }
+
+ cc.assert(child, cc._LogInfos.Node_addChild_3);
+ cc.assert(child._parent === null, "child already added. It can't be added again");
+
+ this._addChildHelper(child, localZOrder, tag, name, setTag);
+ },
+
+ _addChildHelper: function (child, localZOrder, tag, name, setTag) {
+ if (!this._children)
+ this._children = [];
+
+ this._insertChild(child, localZOrder);
+ if (setTag)
+ child.setTag(tag);
+ else
+ child.setName(name);
+
+ child.setParent(this);
+ child.setOrderOfArrival(cc.s_globalOrderOfArrival++);
+
+ if (this._running) {
+ child._performRecursive(cc.Node._stateCallbackType.onEnter);
+ // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter
+ if (this._isTransitionFinished)
+ child._performRecursive(cc.Node._stateCallbackType.onEnterTransitionDidFinish);
+ }
+ child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ if (this._cascadeColorEnabled)
+ child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ if (this._cascadeOpacityEnabled)
+ child._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
+ },
+
+ // composition: REMOVE
+ /**
+ * Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks.
+ * If the cleanup parameter is not passed, it will force a cleanup.
+ * If the node orphan, then nothing happens.
+ * @function
+ * @param {Boolean} [cleanup=true] true if all actions and callbacks on this node should be removed, false otherwise.
+ * @see cc.Node#removeFromParentAndCleanup
+ */
+ removeFromParent: function (cleanup) {
+ if (this._parent) {
+ if (cleanup === undefined)
+ cleanup = true;
+ this._parent.removeChild(this, cleanup);
+ }
+ },
+
+ /**
+ * Removes this node itself from its parent node.
+ * If the node orphan, then nothing happens.
+ * @deprecated since v3.0, please use removeFromParent() instead
+ * @param {Boolean} [cleanup=true] true if all actions and callbacks on this node should be removed, false otherwise.
+ */
+ removeFromParentAndCleanup: function (cleanup) {
+ cc.log(cc._LogInfos.Node_removeFromParentAndCleanup);
+ this.removeFromParent(cleanup);
+ },
+
+ /** Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter.
+ * If the cleanup parameter is not passed, it will force a cleanup.
+ * "remove" logic MUST only be on this method
+ * If a class wants to extend the 'removeChild' behavior it only needs
+ * to override this method
+ * @function
+ * @param {cc.Node} child The child node which will be removed.
+ * @param {Boolean} [cleanup=true] true if all running actions and callbacks on the child node will be cleanup, false otherwise.
+ */
+ removeChild: function (child, cleanup) {
+ // explicit nil handling
+ if (this._children.length === 0)
+ return;
+
+ if (cleanup === undefined)
+ cleanup = true;
+ if (this._children.indexOf(child) > -1)
+ this._detachChild(child, cleanup);
+
+ //this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.visibleDirty);
+ cc.renderer.childrenOrderDirty = true;
+ },
+
+ /**
+ * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter.
+ * If the cleanup parameter is not passed, it will force a cleanup.
+ * @function
+ * @param {Number} tag An integer number that identifies a child node
+ * @param {Boolean} [cleanup=true] true if all running actions and callbacks on the child node will be cleanup, false otherwise.
+ * @see cc.Node#removeChildByTag
+ */
+ removeChildByTag: function (tag, cleanup) {
+ if (tag === cc.NODE_TAG_INVALID)
+ cc.log(cc._LogInfos.Node_removeChildByTag);
+
+ var child = this.getChildByTag(tag);
+ if (!child)
+ cc.log(cc._LogInfos.Node_removeChildByTag_2, tag);
+ else
+ this.removeChild(child, cleanup);
+ },
+
+ /**
+ * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
+ * @param {Boolean} [cleanup=true]
+ */
+ removeAllChildrenWithCleanup: function (cleanup) {
+ this.removeAllChildren(cleanup);
+ },
+
+ /**
+ * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
+ * If the cleanup parameter is not passed, it will force a cleanup.
+ * @function
+ * @param {Boolean} [cleanup=true] true if all running actions on all children nodes should be cleanup, false otherwise.
+ */
+ removeAllChildren: function (cleanup) {
+ // not using detachChild improves speed here
+ var __children = this._children;
+ if (__children !== null) {
+ if (cleanup === undefined)
+ cleanup = true;
+ for (var i = 0; i < __children.length; i++) {
+ var node = __children[i];
+ if (node) {
+ if (this._running) {
+ node._performRecursive(cc.Node._stateCallbackType.onExitTransitionDidStart);
+ node._performRecursive(cc.Node._stateCallbackType.onExit);
+ }
+
+ // If you don't do cleanup, the node's actions will not get removed and the
+ if (cleanup)
+ node._performRecursive(cc.Node._stateCallbackType.cleanup);
+
+ // set parent nil at the end
+ node.parent = null;
+ node._renderCmd.detachFromParent();
+ }
+ }
+ this._children.length = 0;
+ cc.renderer.childrenOrderDirty = true;
+ }
+ },
+
+ _detachChild: function (child, doCleanup) {
+ // IMPORTANT:
+ // -1st do onExit
+ // -2nd cleanup
+ if (this._running) {
+ child._performRecursive(cc.Node._stateCallbackType.onExitTransitionDidStart);
+ child._performRecursive(cc.Node._stateCallbackType.onExit);
+ }
+
+ // If you don't do cleanup, the child's actions will not get removed and the
+ if (doCleanup)
+ child._performRecursive(cc.Node._stateCallbackType.cleanup);
+
+ // set parent nil at the end
+ child.parent = null;
+ child._renderCmd.detachFromParent();
+ cc.arrayRemoveObject(this._children, child);
+ },
+
+ _insertChild: function (child, z) {
+ cc.renderer.childrenOrderDirty = this._reorderChildDirty = true;
+ this._children.push(child);
+ child._setLocalZOrder(z);
+ },
+
+ setNodeDirty: function () {
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /** Reorders a child according to a new z value.
+ * The child MUST be already added.
+ * @function
+ * @param {cc.Node} child An already added child node. It MUST be already added.
+ * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int)
+ */
+ reorderChild: function (child, zOrder) {
+ cc.assert(child, cc._LogInfos.Node_reorderChild);
+ if (this._children.indexOf(child) === -1) {
+ cc.log(cc._LogInfos.Node_reorderChild_2);
+ return;
+ }
+ cc.renderer.childrenOrderDirty = this._reorderChildDirty = true;
+ child.arrivalOrder = cc.s_globalOrderOfArrival;
+ cc.s_globalOrderOfArrival++;
+ child._setLocalZOrder(zOrder);
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.orderDirty);
+ },
+
+ /**
+ *
+ * Sorts the children array once before drawing, instead of every time when a child is added or reordered.
+ * This approach can improves the performance massively.
+ *
+ * @function
+ * @note Don't call this manually unless a child added needs to be removed in the same frame
+ */
+ sortAllChildren: function () {
+ if (this._reorderChildDirty) {
+ var _children = this._children;
+
+ // insertion sort
+ var len = _children.length, i, j, tmp;
+ for (i = 1; i < len; i++) {
+ tmp = _children[i];
+ j = i - 1;
+
+ //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
+ while (j >= 0) {
+ if (tmp._localZOrder < _children[j]._localZOrder) {
+ _children[j + 1] = _children[j];
+ } else if (tmp._localZOrder === _children[j]._localZOrder && tmp.arrivalOrder < _children[j].arrivalOrder) {
+ _children[j + 1] = _children[j];
+ } else {
+ break;
+ }
+ j--;
+ }
+ _children[j + 1] = tmp;
+ }
+
+ //don't need to check children recursively, that's done in visit of each child
+ this._reorderChildDirty = false;
+ }
+ },
+
+ /**
+ * Render function using the canvas 2d context or WebGL context, internal usage only, please do not call this function
+ * @function
+ * @param {CanvasRenderingContext2D | WebGLRenderingContext} ctx The render context
+ */
+ draw: function (ctx) {
+ // override me
+ // Only use- this function to draw your staff.
+ // DON'T draw your stuff outside this method
+ },
+
+ // Internal use only, do not call it by yourself,
+ transformAncestors: function () {
+ if (this._parent !== null) {
+ this._parent.transformAncestors();
+ this._parent.transform();
+ }
+ },
+
+ //scene management
+ /**
+ *
+ * Event callback that is invoked every time when CCNode enters the 'stage'.
+ * If the CCNode enters the 'stage' with a transition, this event is called when the transition starts.
+ * During onEnter you can't access a "sister/brother" node.
+ * If you override onEnter, you must call its parent's onEnter function with this._super().
+ *
+ * @function
+ */
+ onEnter: function () {
+ this._isTransitionFinished = false;
+ this._running = true;//should be running before resumeSchedule
+ this.resume();
+ },
+
+ _performRecursive: function (callbackType) {
+ var nodeCallbackType = cc.Node._stateCallbackType;
+ if (callbackType >= nodeCallbackType.max) {
+ return;
+ }
+
+ var index = 0;
+ var children, child, curr, i, len;
+ var stack = cc.Node._performStacks[cc.Node._performing];
+ if (!stack) {
+ stack = [];
+ cc.Node._performStacks.push(stack);
+ }
+ stack.length = 0;
+ cc.Node._performing++;
+ curr = stack[0] = this;
+ while (curr) {
+ // Walk through children
+ children = curr._children;
+ if (children && children.length > 0) {
+ for (i = 0, len = children.length; i < len; ++i) {
+ child = children[i];
+ stack.push(child);
+ }
+ }
+ children = curr._protectedChildren;
+ if (children && children.length > 0) {
+ for (i = 0, len = children.length; i < len; ++i) {
+ child = children[i];
+ stack.push(child);
+ }
+ }
+
+ index++;
+ curr = stack[index];
+ }
+ for (i = stack.length - 1; i >= 0; --i) {
+ curr = stack[i];
+ stack[i] = null;
+ if (!curr) continue;
+
+ // Perform actual action
+ switch (callbackType) {
+ case nodeCallbackType.onEnter:
+ curr.onEnter();
+ break;
+ case nodeCallbackType.onExit:
+ curr.onExit();
+ break;
+ case nodeCallbackType.onEnterTransitionDidFinish:
+ curr.onEnterTransitionDidFinish();
+ break;
+ case nodeCallbackType.cleanup:
+ curr.cleanup();
+ break;
+ case nodeCallbackType.onExitTransitionDidStart:
+ curr.onExitTransitionDidStart();
+ break;
+ }
+ }
+ cc.Node._performing--;
+ },
+
+ /**
+ *
+ * Event callback that is invoked when the CCNode enters in the 'stage'.
+ * If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes.
+ * If you override onEnterTransitionDidFinish, you shall call its parent's onEnterTransitionDidFinish with this._super()
+ *
+ * @function
+ */
+ onEnterTransitionDidFinish: function () {
+ this._isTransitionFinished = true;
+ },
+
+ /**
+ * callback that is called every time the cc.Node leaves the 'stage'.
+ * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts.
+ * If you override onExitTransitionDidStart, you shall call its parent's onExitTransitionDidStart with this._super()
+ * @function
+ */
+ onExitTransitionDidStart: function () {
+ },
+
+ /**
+ *
+ * callback that is called every time the cc.Node leaves the 'stage'.
+ * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes.
+ * During onExit you can't access a sibling node.
+ * If you override onExit, you shall call its parent's onExit with this._super().
+ *
+ * @function
+ */
+ onExit: function () {
+ this._running = false;
+ this.pause();
+ this.removeAllComponents();
+ },
+
+ // actions
+ /**
+ * Executes an action, and returns the action that is executed.
+ * The node becomes the action's target. Refer to cc.Action's getTarget()
+ * @function
+ * @warning Starting from v0.8 actions don't retain their target anymore.
+ * @param {cc.Action} action
+ * @return {cc.Action} An Action pointer
+ */
+ runAction: function (action) {
+ cc.assert(action, cc._LogInfos.Node_runAction);
+
+ this.actionManager.addAction(action, this, !this._running);
+ return action;
+ },
+
+ /**
+ * Stops and removes all actions from the running action list .
+ * @function
+ */
+ stopAllActions: function () {
+ this.actionManager && this.actionManager.removeAllActionsFromTarget(this);
+ },
+
+ /**
+ * Stops and removes an action from the running action list.
+ * @function
+ * @param {cc.Action} action An action object to be removed.
+ */
+ stopAction: function (action) {
+ this.actionManager.removeAction(action);
+ },
+
+ /**
+ * Removes an action from the running action list by its tag.
+ * @function
+ * @param {Number} tag A tag that indicates the action to be removed.
+ */
+ stopActionByTag: function (tag) {
+ if (tag === cc.ACTION_TAG_INVALID) {
+ cc.log(cc._LogInfos.Node_stopActionByTag);
+ return;
+ }
+ this.actionManager.removeActionByTag(tag, this);
+ },
+
+ /**
+ * Returns an action from the running action list by its tag.
+ * @function
+ * @see cc.Node#getTag and cc.Node#setTag
+ * @param {Number} tag
+ * @return {cc.Action} The action object with the given tag.
+ */
+ getActionByTag: function (tag) {
+ if (tag === cc.ACTION_TAG_INVALID) {
+ cc.log(cc._LogInfos.Node_getActionByTag);
+ return null;
+ }
+ return this.actionManager.getActionByTag(tag, this);
+ },
+
+ /** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).
+ * Composable actions are counted as 1 action. Example:
+ * If you are running 1 Sequence of 7 actions, it will return 1.
+ * If you are running 7 Sequences of 2 actions, it will return 7.
+ * @function
+ * @return {Number} The number of actions that are running plus the ones that are schedule to run
+ */
+ getNumberOfRunningActions: function () {
+ return this.actionManager.numberOfRunningActionsInTarget(this);
+ },
+
+ // cc.Node - Callbacks
+ // timers
+ /**
+ * schedules the "update" method.
+ * It will use the order number 0. This method will be called every frame.
+ * Scheduled methods with a lower order value will be called before the ones that have a higher order value.
+ * Only one "update" method could be scheduled per node.
+ * @function
+ */
+ scheduleUpdate: function () {
+ this.scheduleUpdateWithPriority(0);
+ },
+
+ /**
+ *
+ * schedules the "update" callback function with a custom priority.
+ * This callback function will be called every frame.
+ * Scheduled callback functions with a lower priority will be called before the ones that have a higher value.
+ * Only one "update" callback function could be scheduled per node (You can't have 2 'update' callback functions).
+ *
+ * @function
+ * @param {Number} priority
+ */
+ scheduleUpdateWithPriority: function (priority) {
+ this.scheduler.scheduleUpdate(this, priority, !this._running);
+ },
+
+ /**
+ * Unschedules the "update" method.
+ * @function
+ * @see cc.Node#scheduleUpdate
+ */
+ unscheduleUpdate: function () {
+ this.scheduler.unscheduleUpdate(this);
+ },
+
+ /**
+ * Schedules a custom selector.
+ * If the selector is already scheduled, then the interval parameter will be updated without scheduling it again.
+ * @function
+ * @param {function} callback A function wrapped as a selector
+ * @param {Number} interval Tick interval in seconds. 0 means tick every frame. If interval = 0, it's recommended to use scheduleUpdate() instead.
+ * @param {Number} repeat The selector will be executed (repeat + 1) times, you can use kCCRepeatForever for tick infinitely.
+ * @param {Number} delay The amount of time that the first tick will wait before execution.
+ * @param {String} key The only string identifying the callback
+ */
+ schedule: function (callback, interval, repeat, delay, key) {
+ var len = arguments.length;
+ if (typeof callback === "function") {
+ //callback, interval, repeat, delay, key
+ if (len === 1) {
+ //callback
+ interval = 0;
+ repeat = cc.REPEAT_FOREVER;
+ delay = 0;
+ key = this.__instanceId;
+ } else if (len === 2) {
+ if (typeof interval === "number") {
+ //callback, interval
+ repeat = cc.REPEAT_FOREVER;
+ delay = 0;
+ key = this.__instanceId;
+ } else {
+ //callback, key
+ key = interval;
+ interval = 0;
+ repeat = cc.REPEAT_FOREVER;
+ delay = 0;
+ }
+ } else if (len === 3) {
+ if (typeof repeat === "string") {
+ //callback, interval, key
+ key = repeat;
+ repeat = cc.REPEAT_FOREVER;
+ } else {
+ //callback, interval, repeat
+ key = this.__instanceId;
+ }
+ delay = 0;
+ } else if (len === 4) {
+ key = this.__instanceId;
+ }
+ } else {
+ //selector
+ //selector, interval
+ //selector, interval, repeat, delay
+ if (len === 1) {
+ interval = 0;
+ repeat = cc.REPEAT_FOREVER;
+ delay = 0;
+ } else if (len === 2) {
+ repeat = cc.REPEAT_FOREVER;
+ delay = 0;
+ }
+ }
+
+ cc.assert(callback, cc._LogInfos.Node_schedule);
+ cc.assert(interval >= 0, cc._LogInfos.Node_schedule_2);
+
+ interval = interval || 0;
+ repeat = isNaN(repeat) ? cc.REPEAT_FOREVER : repeat;
+ delay = delay || 0;
+
+ this.scheduler.schedule(callback, this, interval, repeat, delay, !this._running, key);
+ },
+
+ /**
+ * Schedules a callback function that runs only once, with a delay of 0 or larger
+ * @function
+ * @see cc.Node#schedule
+ * @param {function} callback A function wrapped as a selector
+ * @param {Number} delay The amount of time that the first tick will wait before execution.
+ * @param {String} key The only string identifying the callback
+ */
+ scheduleOnce: function (callback, delay, key) {
+ //selector, delay
+ //callback, delay, key
+ if (key === undefined)
+ key = this.__instanceId;
+ this.schedule(callback, 0, 0, delay, key);
+ },
+
+ /**
+ * unschedules a custom callback function.
+ * @function
+ * @see cc.Node#schedule
+ * @param {function} callback_fn A function wrapped as a selector
+ */
+ unschedule: function (callback_fn) {
+ //key
+ //selector
+ if (!callback_fn)
+ return;
+
+ this.scheduler.unschedule(callback_fn, this);
+ },
+
+ /**
+ * unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.
+ * Actions are not affected by this method.
+ * @function
+ */
+ unscheduleAllCallbacks: function () {
+ this.scheduler.unscheduleAllForTarget(this);
+ },
+
+ /**
+ * Resumes all scheduled selectors and actions.
+ * This method is called internally by onEnter
+ * @function
+ * @deprecated since v3.0, please use resume() instead
+ */
+ resumeSchedulerAndActions: function () {
+ cc.log(cc._LogInfos.Node_resumeSchedulerAndActions);
+ this.resume();
+ },
+
+ /**
+ * Resumes all scheduled selectors and actions.
+ * This method is called internally by onEnter
+ */
+ resume: function () {
+ this.scheduler.resumeTarget(this);
+ this.actionManager && this.actionManager.resumeTarget(this);
+ cc.eventManager.resumeTarget(this);
+ },
+
+ /**
+ * Pauses all scheduled selectors and actions.
+ * This method is called internally by onExit
+ * @deprecated since v3.0, please use pause instead
+ * @function
+ */
+ pauseSchedulerAndActions: function () {
+ cc.log(cc._LogInfos.Node_pauseSchedulerAndActions);
+ this.pause();
+ },
+
+ /**
+ * Pauses all scheduled selectors and actions.
+ * This method is called internally by onExit
+ * @function
+ */
+ pause: function () {
+ this.scheduler.pauseTarget(this);
+ this.actionManager && this.actionManager.pauseTarget(this);
+ cc.eventManager.pauseTarget(this);
+ },
+
+ /**
+ *Sets the additional transform.
+ * The additional transform will be concatenated at the end of getNodeToParentTransform.
+ * It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't).
+ *
+ * @function
+ * @param {cc.AffineTransform} additionalTransform The additional transform
+ * @example
+ * // create a batchNode
+ * var batch = new cc.SpriteBatchNode("Icon-114.png");
+ * this.addChild(batch);
+ *
+ * // create two sprites, spriteA will be added to batchNode, they are using different textures.
+ * var spriteA = new cc.Sprite(batch->getTexture());
+ * var spriteB = new cc.Sprite("Icon-72.png");
+ *
+ * batch.addChild(spriteA);
+ *
+ * // We can't make spriteB as spriteA's child since they use different textures. So just add it to layer.
+ * // But we want to simulate `parent-child` relationship for these two node.
+ * this.addChild(spriteB);
+ *
+ * //position
+ * spriteA.setPosition(ccp(200, 200));
+ *
+ * // Gets the spriteA's transform.
+ * var t = spriteA.getNodeToParentTransform();
+ *
+ * // Sets the additional transform to spriteB, spriteB's position will based on its pseudo parent i.e. spriteA.
+ * spriteB.setAdditionalTransform(t);
+ *
+ * //scale
+ * spriteA.setScale(2);
+ *
+ * // Gets the spriteA's transform.
+ * t = spriteA.getNodeToParentTransform();
+ *
+ * // Sets the additional transform to spriteB, spriteB's scale will based on its pseudo parent i.e. spriteA.
+ * spriteB.setAdditionalTransform(t);
+ *
+ * //rotation
+ * spriteA.setRotation(20);
+ *
+ * // Gets the spriteA's transform.
+ * t = spriteA.getNodeToParentTransform();
+ *
+ * // Sets the additional transform to spriteB, spriteB's rotation will based on its pseudo parent i.e. spriteA.
+ * spriteB.setAdditionalTransform(t);
+ */
+ setAdditionalTransform: function (additionalTransform) {
+ if(additionalTransform === undefined)
+ return this._additionalTransformDirty = false;
+ this._additionalTransform = additionalTransform;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ this._additionalTransformDirty = true;
+ },
+
+ /**
+ * Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.
+ * The matrix is in Pixels.
+ * @function
+ * @return {cc.AffineTransform}
+ */
+ getParentToNodeTransform: function () {
+ return this._renderCmd.getParentToNodeTransform();
+ },
+
+ /**
+ * @function
+ * @deprecated since v3.0, please use getParentToNodeTransform instead
+ */
+ parentToNodeTransform: function () {
+ return this.getParentToNodeTransform();
+ },
+
+ /**
+ * Returns the world affine transform matrix. The matrix is in Pixels.
+ * @function
+ * @return {cc.AffineTransform}
+ */
+ getNodeToWorldTransform: function () {
+ var t = this.getNodeToParentTransform();
+ for (var p = this._parent; p !== null; p = p.parent)
+ t = cc.affineTransformConcat(t, p.getNodeToParentTransform());
+ return t;
+ },
+
+ /**
+ * @function
+ * @deprecated since v3.0, please use getNodeToWorldTransform instead
+ */
+ nodeToWorldTransform: function () {
+ return this.getNodeToWorldTransform();
+ },
+
+ /**
+ * Returns the inverse world affine transform matrix. The matrix is in Pixels.
+ * @function
+ * @return {cc.AffineTransform}
+ */
+ getWorldToNodeTransform: function () {
+ return cc.affineTransformInvert(this.getNodeToWorldTransform());
+ },
+
+ /**
+ * @function
+ * @deprecated since v3.0, please use getWorldToNodeTransform instead
+ */
+ worldToNodeTransform: function () {
+ return this.getWorldToNodeTransform();
+ },
+
+ /**
+ * Converts a Point to node (local) space coordinates. The result is in Points.
+ * @function
+ * @param {cc.Point} worldPoint
+ * @return {cc.Point}
+ */
+ convertToNodeSpace: function (worldPoint) {
+ return cc.pointApplyAffineTransform(worldPoint, this.getWorldToNodeTransform());
+ },
+
+ /**
+ * Converts a Point to world space coordinates. The result is in Points.
+ * @function
+ * @param {cc.Point} nodePoint
+ * @return {cc.Point}
+ */
+ convertToWorldSpace: function (nodePoint) {
+ nodePoint = nodePoint || cc.p(0, 0);
+ return cc.pointApplyAffineTransform(nodePoint, this.getNodeToWorldTransform());
+ },
+
+ /**
+ * Converts a Point to node (local) space coordinates. The result is in Points.
+ * treating the returned/received node point as anchor relative.
+ * @function
+ * @param {cc.Point} worldPoint
+ * @return {cc.Point}
+ */
+ convertToNodeSpaceAR: function (worldPoint) {
+ return cc.pSub(this.convertToNodeSpace(worldPoint), this._renderCmd.getAnchorPointInPoints());
+ },
+
+ /**
+ * Converts a local Point to world space coordinates.The result is in Points.
+ * treating the returned/received node point as anchor relative.
+ * @function
+ * @param {cc.Point} nodePoint
+ * @return {cc.Point}
+ */
+ convertToWorldSpaceAR: function (nodePoint) {
+ nodePoint = nodePoint || cc.p(0, 0);
+ var pt = cc.pAdd(nodePoint, this._renderCmd.getAnchorPointInPoints());
+ return this.convertToWorldSpace(pt);
+ },
+
+ _convertToWindowSpace: function (nodePoint) {
+ var worldPoint = this.convertToWorldSpace(nodePoint);
+ return cc.director.convertToUI(worldPoint);
+ },
+
+ /** convenience methods which take a cc.Touch instead of cc.Point
+ * @function
+ * @param {cc.Touch} touch The touch object
+ * @return {cc.Point}
+ */
+ convertTouchToNodeSpace: function (touch) {
+ var point = touch.getLocation();
+ return this.convertToNodeSpace(point);
+ },
+
+ /**
+ * converts a cc.Touch (world coordinates) into a local coordinate. This method is AR (Anchor Relative).
+ * @function
+ * @param {cc.Touch} touch The touch object
+ * @return {cc.Point}
+ */
+ convertTouchToNodeSpaceAR: function (touch) {
+ var point = cc.director.convertToGL(touch.getLocation());
+ return this.convertToNodeSpaceAR(point);
+ },
+
+ /**
+ * Update will be called automatically every frame if "scheduleUpdate" is called when the node is "live".
+ * The default behavior is to invoke the visit function of node's componentContainer.
+ * Override me to implement your own update logic.
+ * @function
+ * @param {Number} dt Delta time since last update
+ */
+ update: function (dt) {
+ if (this._componentContainer && !this._componentContainer.isEmpty())
+ this._componentContainer.visit(dt);
+ },
+
+ /**
+ *
+ * Calls children's updateTransform() method recursively.
+ *
+ * This method is moved from CCSprite, so it's no longer specific to CCSprite.
+ * As the result, you apply CCSpriteBatchNode's optimization on your customed CCNode.
+ * e.g., batchNode->addChild(myCustomNode), while you can only addChild(sprite) before.
+ *
+ * @function
+ */
+ updateTransform: function () {
+ var children = this._children, node;
+ for (var i = 0; i < children.length; i++) {
+ node = children[i];
+ if (node)
+ node.updateTransform();
+ }
+ },
+
+ /**
+ * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
+ * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
+ * This is a hack, and should be removed once JSB fixes the retain/release bug
+ * You will need to retain an object if you created an engine object and haven't added it into the scene graph during the same frame.
+ * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,
+ * when you want to use it later, a "Invalid Native Object" error will be raised.
+ * The retain function can increase a reference count for the native object to avoid it being released,
+ * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.
+ * retain and release function call should be paired in developer's game code.
+ * @function
+ * @see cc.Node#release
+ */
+ retain: function () {
+ },
+ /**
+ * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
+ * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
+ * This is a hack, and should be removed once JSB fixes the retain/release bug
+ * You will need to retain an object if you created an engine object and haven't added it into the scene graph during the same frame.
+ * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,
+ * when you want to use it later, a "Invalid Native Object" error will be raised.
+ * The retain function can increase a reference count for the native object to avoid it being released,
+ * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.
+ * retain and release function call should be paired in developer's game code.
+ * @function
+ * @see cc.Node#retain
+ */
+ release: function () {
+ },
+
+ /**
+ * Returns a component identified by the name given.
+ * @function
+ * @param {String} name The name to search for
+ * @return {cc.Component} The component found
+ */
+ getComponent: function (name) {
+ if(this._componentContainer)
+ return this._componentContainer.getComponent(name);
+ return null;
+ },
+
+ /**
+ * Adds a component to the node's component container.
+ * @function
+ * @param {cc.Component} component
+ */
+ addComponent: function (component) {
+ if(this._componentContainer)
+ this._componentContainer.add(component);
+ },
+
+ /**
+ * Removes a component identified by the given name or removes the component object given
+ * @function
+ * @param {String|cc.Component} component
+ */
+ removeComponent: function (component) {
+ if(this._componentContainer)
+ return this._componentContainer.remove(component);
+ return false;
+ },
+
+ /**
+ * Removes all components of cc.Node, it called when cc.Node is exiting from stage.
+ * @function
+ */
+ removeAllComponents: function () {
+ if(this._componentContainer)
+ this._componentContainer.removeAll();
+ },
+
+ grid: null,
+
+ /**
+ * Recursive method that visit its children and draw them
+ * @function
+ * @param {cc.Node} parent
+ */
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ var renderer = cc.renderer;
+ cmd.visit(parentCmd);
+
+ var i, children = this._children, len = children.length, child;
+ if (len > 0) {
+ if (this._reorderChildDirty) {
+ this.sortAllChildren();
+ }
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0) {
+ child.visit(this);
+ }
+ else {
+ break;
+ }
+ }
+
+ renderer.pushRenderCommand(cmd);
+ for (; i < len; i++) {
+ children[i].visit(this);
+ }
+ } else {
+ renderer.pushRenderCommand(cmd);
+ }
+ cmd._dirtyFlag = 0;
+ },
+
+ /**
+ * Performs view-matrix transformation based on position, scale, rotation and other attributes.
+ * @function
+ * @param {cc.Node.RenderCmd} parentCmd parent's render command
+ * @param {boolean} recursive whether call its children's transform
+ */
+ transform: function (parentCmd, recursive) {
+ this._renderCmd.transform(parentCmd, recursive);
+ },
+
+ /**
+ * Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.
+ * The matrix is in Pixels.
+ * @function
+ * @return {cc.AffineTransform}
+ * @deprecated since v3.0, please use getNodeToParentTransform instead
+ */
+ nodeToParentTransform: function () {
+ return this.getNodeToParentTransform();
+ },
+
+ /**
+ * Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.
+ * The matrix is in Pixels.
+ * @function
+ * @return {cc.AffineTransform} The affine transform object
+ */
+ getNodeToParentTransform: function (ancestor) {
+ var t = this._renderCmd.getNodeToParentTransform();
+ if (ancestor) {
+ var T = {a: t.a, b: t.b, c: t.c, d: t.d, tx: t.tx, ty: t.ty};
+ for (var p = this._parent; p != null && p != ancestor; p = p.getParent()) {
+ cc.affineTransformConcatIn(T, p.getNodeToParentTransform());
+ }
+ return T;
+ } else {
+ return t;
+ }
+ },
+
+ getNodeToParentAffineTransform: function (ancestor) {
+ return this.getNodeToParentTransform(ancestor);
+ },
+
+ /**
+ * Returns null
+ * @function
+ * @return {null}
+ * @deprecated since v3.0, no alternative function
+ */
+ getCamera: function () {
+ return null;
+ },
+
+ /**
+ * Returns a grid object that is used when applying effects.
+ * This function have been deprecated, please use cc.NodeGrid to run grid actions
+ * @function
+ * @return {cc.GridBase} A CCGrid object that is used when applying effects
+ * @deprecated since v3.0, no alternative function
+ */
+ getGrid: function () {
+ return this.grid;
+ },
+
+ /**
+ * Changes a grid object that is used when applying effects
+ * This function have been deprecated, please use cc.NodeGrid to run grid actions
+ * @function
+ * @param {cc.GridBase} grid A CCGrid object that is used when applying effects
+ * @deprecated since v3.0, no alternative function
+ */
+ setGrid: function (grid) {
+ this.grid = grid;
+ },
+
+ /**
+ * Return the shader program currently used for this node
+ * @function
+ * @return {cc.GLProgram} The shader program currently used for this node
+ */
+ getShaderProgram: function () {
+ return this._renderCmd.getShaderProgram();
+ },
+
+ /**
+ *
+ * Sets the shader program for this node
+ *
+ * Since v2.0, each rendering node must set its shader program.
+ * It should be set in initialize phase.
+ *
+ * @function
+ * @param {cc.GLProgram} newShaderProgram The shader program which fetches from CCShaderCache.
+ * @example
+ * node.setGLProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
+ */
+ setShaderProgram: function (newShaderProgram) {
+ this._renderCmd.setShaderProgram(newShaderProgram);
+ },
+
+ setGLProgramState: function (glProgramState) {
+ this._renderCmd.setGLProgramState(glProgramState);
+ },
+
+ getGLProgramState: function () {
+ return this._renderCmd.getGLProgramState();
+ },
+
+ /**
+ * Returns the state of OpenGL server side.
+ * @function
+ * @return {Number} The state of OpenGL server side.
+ * @deprecated since v3.0, no need anymore
+ */
+ getGLServerState: function () {
+ return 0;
+ },
+
+ /**
+ * Sets the state of OpenGL server side.
+ * @function
+ * @param {Number} state The state of OpenGL server side.
+ * @deprecated since v3.0, no need anymore
+ */
+ setGLServerState: function (state) {
+ },
+
+ /**
+ * Returns a "world" axis aligned bounding box of the node.
+ * @function
+ * @return {cc.Rect}
+ */
+ getBoundingBoxToWorld: function () {
+ var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
+ var trans = this.getNodeToWorldTransform();
+ rect = cc.rectApplyAffineTransform(rect, trans);
+
+ //query child's BoundingBox
+ if (!this._children)
+ return rect;
+
+ var locChildren = this._children;
+ for (var i = 0; i < locChildren.length; i++) {
+ var child = locChildren[i];
+ if (child && child._visible) {
+ var childRect = child._getBoundingBoxToCurrentNode(trans);
+ if (childRect)
+ rect = cc.rectUnion(rect, childRect);
+ }
+ }
+ return rect;
+ },
+
+ _getBoundingBoxToCurrentNode: function (parentTransform) {
+ var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
+ var trans = (parentTransform === undefined) ? this.getNodeToParentTransform() : cc.affineTransformConcat(this.getNodeToParentTransform(), parentTransform);
+ rect = cc.rectApplyAffineTransform(rect, trans);
+
+ //query child's BoundingBox
+ if (!this._children)
+ return rect;
+
+ var locChildren = this._children;
+ for (var i = 0; i < locChildren.length; i++) {
+ var child = locChildren[i];
+ if (child && child._visible) {
+ var childRect = child._getBoundingBoxToCurrentNode(trans);
+ if (childRect)
+ rect = cc.rectUnion(rect, childRect);
+ }
+ }
+ return rect;
+ },
+
+ /**
+ * Returns the opacity of Node
+ * @function
+ * @returns {number} opacity
+ */
+ getOpacity: function () {
+ return this._realOpacity;
+ },
+
+ /**
+ * Returns the displayed opacity of Node,
+ * the difference between displayed opacity and opacity is that displayed opacity is calculated based on opacity and parent node's opacity when cascade opacity enabled.
+ * @function
+ * @returns {number} displayed opacity
+ */
+ getDisplayedOpacity: function () {
+ return this._renderCmd.getDisplayedOpacity();
+ },
+
+ /**
+ * Sets the opacity of Node
+ * @function
+ * @param {Number} opacity
+ */
+ setOpacity: function (opacity) {
+ this._realOpacity = opacity;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
+ },
+
+ /**
+ * Update displayed opacity
+ * @function
+ * @param {Number} parentOpacity
+ */
+ updateDisplayedOpacity: function (parentOpacity) {
+ //TODO this API shouldn't be public.
+ this._renderCmd._updateDisplayOpacity(parentOpacity);
+ },
+
+ /**
+ * Returns whether node's opacity value affect its child nodes.
+ * @function
+ * @returns {boolean}
+ */
+ isCascadeOpacityEnabled: function () {
+ return this._cascadeOpacityEnabled;
+ },
+
+ /**
+ * Enable or disable cascade opacity, if cascade enabled, child nodes' opacity will be the multiplication of parent opacity and its own opacity.
+ * @function
+ * @param {boolean} cascadeOpacityEnabled
+ */
+ setCascadeOpacityEnabled: function (cascadeOpacityEnabled) {
+ if (this._cascadeOpacityEnabled === cascadeOpacityEnabled)
+ return;
+ this._cascadeOpacityEnabled = cascadeOpacityEnabled;
+ this._renderCmd.setCascadeOpacityEnabledDirty();
+ },
+
+ /**
+ * Returns the color of Node
+ * @function
+ * @returns {cc.Color}
+ */
+ getColor: function () {
+ var locRealColor = this._realColor;
+ return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
+ },
+
+ /**
+ * Returns the displayed color of Node,
+ * the difference between displayed color and color is that displayed color is calculated based on color and parent node's color when cascade color enabled.
+ * @function
+ * @returns {cc.Color}
+ */
+ getDisplayedColor: function () {
+ return this._renderCmd.getDisplayedColor();
+ },
+
+ /**
+ * Sets the color of Node.
+ * When color doesn't include opacity value like cc.color(128,128,128), this function only change the color.
+ * When color include opacity like cc.color(128,128,128,100), then this function will change the color and the opacity.
+ * @function
+ * @param {cc.Color} color The new color given
+ */
+ setColor: function (color) {
+ var locRealColor = this._realColor;
+ locRealColor.r = color.r;
+ locRealColor.g = color.g;
+ locRealColor.b = color.b;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ },
+
+ /**
+ * Update the displayed color of Node
+ * @function
+ * @param {cc.Color} parentColor
+ */
+ updateDisplayedColor: function (parentColor) {
+ //TODO this API shouldn't be public.
+ this._renderCmd._updateDisplayColor(parentColor);
+ },
+
+ /**
+ * Returns whether node's color value affect its child nodes.
+ * @function
+ * @returns {boolean}
+ */
+ isCascadeColorEnabled: function () {
+ return this._cascadeColorEnabled;
+ },
+
+ /**
+ * Enable or disable cascade color, if cascade enabled, child nodes' opacity will be the cascade value of parent color and its own color.
+ * @param {boolean} cascadeColorEnabled
+ */
+ setCascadeColorEnabled: function (cascadeColorEnabled) {
+ if (this._cascadeColorEnabled === cascadeColorEnabled)
+ return;
+ this._cascadeColorEnabled = cascadeColorEnabled;
+ this._renderCmd.setCascadeColorEnabledDirty();
+ },
+
+ /**
+ * Set whether color should be changed with the opacity value,
+ * useless in cc.Node, but this function is override in some class to have such behavior.
+ * @function
+ * @param {Boolean} opacityValue
+ */
+ setOpacityModifyRGB: function (opacityValue) {
+ },
+
+ /**
+ * Get whether color should be changed with the opacity value
+ * @function
+ * @return {Boolean}
+ */
+ isOpacityModifyRGB: function () {
+ return false;
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.Node.CanvasRenderCmd(this);
+ else
+ return new cc.Node.WebGLRenderCmd(this);
+ },
+
+ /** Search the children of the receiving node to perform processing for nodes which share a name.
+ *
+ * @param name The name to search for, supports c++11 regular expression.
+ * Search syntax options:
+ * `//`: Can only be placed at the begin of the search string. This indicates that it will search recursively.
+ * `..`: The search should move up to the node's parent. Can only be placed at the end of string.
+ * `/` : When placed anywhere but the start of the search string, this indicates that the search should move to the node's children.
+ *
+ * @code
+ * enumerateChildren("//MyName", ...): This searches the children recursively and matches any node with the name `MyName`.
+ * enumerateChildren("[[:alnum:]]+", ...): This search string matches every node of its children.
+ * enumerateChildren("A[[:digit:]]", ...): This searches the node's children and returns any child named `A0`, `A1`, ..., `A9`.
+ * enumerateChildren("Abby/Normal", ...): This searches the node's grandchildren and returns any node whose name is `Normal`
+ * and whose parent is named `Abby`.
+ * enumerateChildren("//Abby/Normal", ...): This searches recursively and returns any node whose name is `Normal` and whose
+ * parent is named `Abby`.
+ * @endcode
+ *
+ * @warning Only support alpha or number for name, and not support unicode.
+ *
+ * @param callback A callback function to execute on nodes that match the `name` parameter. The function takes the following arguments:
+ * `node`
+ * A node that matches the name
+ * And returns a boolean result. Your callback can return `true` to terminate the enumeration.
+ *
+ */
+ enumerateChildren: function (name, callback) {
+ cc.assert(name && name.length != 0, "Invalid name");
+ cc.assert(callback != null, "Invalid callback function");
+
+ var length = name.length;
+ var subStrStartPos = 0;
+ var subStrlength = length;
+
+ // Starts with '//'?
+ var searchRecursively = false;
+ if (length > 2 && name[0] === "/" && name[1] === "/") {
+ searchRecursively = true;
+ subStrStartPos = 2;
+ subStrlength -= 2;
+ }
+
+ var searchFromParent = false;
+ if (length > 3 && name[length - 3] === "/" && name[length - 2] === "." && name[length - 1] === ".") {
+ searchFromParent = true;
+ subStrlength -= 3;
+ }
+
+ var newName = name.substr(subStrStartPos, subStrlength);
+
+ if (searchFromParent)
+ newName = "[[:alnum:]]+/" + newName;
+
+ if (searchRecursively)
+ this.doEnumerateRecursive(this, newName, callback);
+ else
+ this.doEnumerate(newName, callback);
+ },
+
+ doEnumerateRecursive: function (node, name, callback) {
+ var ret = false;
+ if (node.doEnumerate(name, callback)) {
+ ret = true;
+ } else {
+ var child,
+ children = node.getChildren(),
+ length = children.length;
+ // search its children
+ for (var i = 0; i < length; i++) {
+ child = children[i];
+ if (this.doEnumerateRecursive(child, name, callback)) {
+ ret = true;
+ break;
+ }
+ }
+ }
+ return ret;
+ },
+
+ doEnumerate: function (name, callback) {
+ // name may be xxx/yyy, should find its parent
+ var pos = name.indexOf('/');
+ var searchName = name;
+ var needRecursive = false;
+ if (pos !== -1) {
+ searchName = name.substr(0, pos);
+ //name.erase(0, pos+1);
+ needRecursive = true;
+ }
+
+ var ret = false;
+ var child,
+ children = this._children,
+ length = children.length;
+ for (var i = 0; i < length; i++) {
+ child = children[i];
+ if (child._name.indexOf(searchName) !== -1) {
+ if (!needRecursive) {
+ // terminate enumeration if callback return true
+ if (callback(child)) {
+ ret = true;
+ break;
+ }
+ } else {
+ ret = child.doEnumerate(name, callback);
+ if (ret)
+ break;
+ }
+ }
+ }
+
+ return ret;
+ }
+});
+
+/**
+ * Allocates and initializes a node.
+ * @deprecated since v3.0, please use new construction instead.
+ * @see cc.Node
+ * @return {cc.Node}
+ */
+cc.Node.create = function () {
+ return new cc.Node();
+};
+
+cc.Node._stateCallbackType = {
+ onEnter: 1,
+ onExit: 2,
+ cleanup: 3,
+ onEnterTransitionDidFinish: 4,
+ onExitTransitionDidStart: 5,
+ max: 6
+};
+cc.Node._performStacks = [[]];
+cc.Node._performing = 0;
+
+cc.assert(cc.isFunction(cc._tmp.PrototypeCCNode), cc._LogInfos.MissingFile, "BaseNodesPropertyDefine.js");
+cc._tmp.PrototypeCCNode();
+delete cc._tmp.PrototypeCCNode;
diff --git a/cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js b/cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js
new file mode 100644
index 0000000000..43c46d0f7f
--- /dev/null
+++ b/cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js
@@ -0,0 +1,657 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//---------------------- Customer render cmd --------------------
+cc.CustomRenderCmd = function (target, func) {
+ this._needDraw = true;
+ this._target = target;
+ this._callback = func;
+};
+cc.CustomRenderCmd.prototype.rendering = function (ctx, scaleX, scaleY) {
+ if (!this._callback)
+ return;
+ this._callback.call(this._target, ctx, scaleX, scaleY);
+};
+cc.CustomRenderCmd.prototype.needDraw = function () {
+ return this._needDraw;
+};
+
+var dirtyFlags = cc.Node._dirtyFlags = {
+ transformDirty: 1 << 0, visibleDirty: 1 << 1, colorDirty: 1 << 2, opacityDirty: 1 << 3, cacheDirty: 1 << 4,
+ orderDirty: 1 << 5, textDirty: 1 << 6, gradientDirty: 1 << 7, textureDirty: 1 << 8,
+ contentDirty: 1 << 9,
+ COUNT: 10,
+ all: (1 << 10) - 1
+};
+
+var ONE_DEGREE = Math.PI / 180;
+
+function transformChildTree(root) {
+ var index = 1;
+ var children, child, curr, parentCmd, i, len;
+ var stack = cc.Node._performStacks[cc.Node._performing];
+ if (!stack) {
+ stack = [];
+ cc.Node._performStacks.push(stack);
+ }
+ stack.length = 0;
+ cc.Node._performing++;
+ stack[0] = root;
+ while (index) {
+ index--;
+ curr = stack[index];
+ // Avoid memory leak
+ stack[index] = null;
+ if (!curr) continue;
+ children = curr._children;
+ if (children && children.length > 0) {
+ parentCmd = curr._renderCmd;
+ for (i = 0, len = children.length; i < len; ++i) {
+ child = children[i];
+ stack[index] = child;
+ index++;
+ child._renderCmd.transform(parentCmd);
+ }
+ }
+ var pChildren = curr._protectedChildren;
+ if (pChildren && pChildren.length > 0) {
+ parentCmd = curr._renderCmd;
+ for (i = 0, len = pChildren.length; i < len; ++i) {
+ child = pChildren[i];
+ stack[index] = child;
+ index++;
+ child._renderCmd.transform(parentCmd);
+ }
+ }
+ }
+ cc.Node._performing--;
+}
+
+//-------------------------Base -------------------------
+cc.Node.RenderCmd = function (renderable) {
+ this._node = renderable;
+ this._anchorPointInPoints = {x: 0, y: 0};
+ this._displayedColor = cc.color(255, 255, 255, 255);
+};
+
+cc.Node.RenderCmd.prototype = {
+ constructor: cc.Node.RenderCmd,
+
+ _needDraw: false,
+ _dirtyFlag: 1,
+ _curLevel: -1,
+
+ _displayedOpacity: 255,
+ _cascadeColorEnabledDirty: false,
+ _cascadeOpacityEnabledDirty: false,
+
+ _transform: null,
+ _worldTransform: null,
+ _inverse: null,
+
+ needDraw: function () {
+ return this._needDraw;
+ },
+
+ getAnchorPointInPoints: function () {
+ return cc.p(this._anchorPointInPoints);
+ },
+
+ getDisplayedColor: function () {
+ var tmpColor = this._displayedColor;
+ return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
+ },
+
+ getDisplayedOpacity: function () {
+ return this._displayedOpacity;
+ },
+
+ setCascadeColorEnabledDirty: function () {
+ this._cascadeColorEnabledDirty = true;
+ this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ },
+
+ setCascadeOpacityEnabledDirty: function () {
+ this._cascadeOpacityEnabledDirty = true;
+ this.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
+ },
+
+ getParentToNodeTransform: function () {
+ if (!this._inverse) {
+ this._inverse = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ }
+ if (this._dirtyFlag & cc.Node._dirtyFlags.transformDirty) {
+ cc.affineTransformInvertOut(this.getNodeToParentTransform(), this._inverse);
+ }
+ return this._inverse;
+ },
+
+ detachFromParent: function () {
+ },
+
+ _updateAnchorPointInPoint: function () {
+ var locAPP = this._anchorPointInPoints, locSize = this._node._contentSize, locAnchorPoint = this._node._anchorPoint;
+ locAPP.x = locSize.width * locAnchorPoint.x;
+ locAPP.y = locSize.height * locAnchorPoint.y;
+ this.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ setDirtyFlag: function (dirtyFlag) {
+ if (this._dirtyFlag === 0 && dirtyFlag !== 0)
+ cc.renderer.pushDirtyNode(this);
+ this._dirtyFlag |= dirtyFlag;
+ },
+
+ getParentRenderCmd: function () {
+ if (this._node && this._node._parent && this._node._parent._renderCmd)
+ return this._node._parent._renderCmd;
+ return null;
+ },
+
+ transform: function (parentCmd, recursive) {
+ if (!this._transform) {
+ this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ }
+
+ var node = this._node,
+ pt = parentCmd ? parentCmd._worldTransform : null,
+ t = this._transform,
+ wt = this._worldTransform; //get the world transform
+
+ if (node._usingNormalizedPosition && node._parent) {
+ var conSize = node._parent._contentSize;
+ node._position.x = node._normalizedPosition.x * conSize.width;
+ node._position.y = node._normalizedPosition.y * conSize.height;
+ node._normalizedPositionDirty = false;
+ }
+
+ var hasRotation = node._rotationX || node._rotationY;
+ var hasSkew = node._skewX || node._skewY;
+ var sx = node._scaleX, sy = node._scaleY;
+ var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y;
+ var a = 1, b = 0, c = 0, d = 1;
+ if (hasRotation || hasSkew) {
+ // position
+ t.tx = node._position.x;
+ t.ty = node._position.y;
+
+ // rotation
+ if (hasRotation) {
+ var rotationRadiansX = node._rotationX * ONE_DEGREE;
+ c = Math.sin(rotationRadiansX);
+ d = Math.cos(rotationRadiansX);
+ if (node._rotationY === node._rotationX) {
+ a = d;
+ b = -c;
+ }
+ else {
+ var rotationRadiansY = node._rotationY * ONE_DEGREE;
+ a = Math.cos(rotationRadiansY);
+ b = -Math.sin(rotationRadiansY);
+ }
+ }
+
+ // scale
+ t.a = a *= sx;
+ t.b = b *= sx;
+ t.c = c *= sy;
+ t.d = d *= sy;
+
+ // skew
+ if (hasSkew) {
+ var skx = Math.tan(node._skewX * ONE_DEGREE);
+ var sky = Math.tan(node._skewY * ONE_DEGREE);
+ if (skx === Infinity)
+ skx = 99999999;
+ if (sky === Infinity)
+ sky = 99999999;
+ t.a = a + c * sky;
+ t.b = b + d * sky;
+ t.c = c + a * skx;
+ t.d = d + b * skx;
+ }
+
+ if (appX || appY) {
+ t.tx -= t.a * appX + t.c * appY;
+ t.ty -= t.b * appX + t.d * appY;
+ // adjust anchorPoint
+ if (node._ignoreAnchorPointForPosition) {
+ t.tx += appX;
+ t.ty += appY;
+ }
+ }
+
+ if (node._additionalTransformDirty) {
+ cc.affineTransformConcatIn(t, node._additionalTransform);
+ }
+
+ if (pt) {
+ // cc.AffineTransformConcat is incorrect at get world transform
+ wt.a = t.a * pt.a + t.b * pt.c; //a
+ wt.b = t.a * pt.b + t.b * pt.d; //b
+ wt.c = t.c * pt.a + t.d * pt.c; //c
+ wt.d = t.c * pt.b + t.d * pt.d; //d
+ wt.tx = pt.a * t.tx + pt.c * t.ty + pt.tx;
+ wt.ty = pt.d * t.ty + pt.ty + pt.b * t.tx;
+ } else {
+ wt.a = t.a;
+ wt.b = t.b;
+ wt.c = t.c;
+ wt.d = t.d;
+ wt.tx = t.tx;
+ wt.ty = t.ty;
+ }
+ }
+ else {
+ t.a = sx;
+ t.b = 0;
+ t.c = 0;
+ t.d = sy;
+ t.tx = node._position.x;
+ t.ty = node._position.y;
+
+ if (appX || appY) {
+ t.tx -= t.a * appX;
+ t.ty -= t.d * appY;
+ // adjust anchorPoint
+ if (node._ignoreAnchorPointForPosition) {
+ t.tx += appX;
+ t.ty += appY;
+ }
+ }
+
+ if (node._additionalTransformDirty) {
+ cc.affineTransformConcatIn(t, node._additionalTransform);
+ }
+
+ if (pt) {
+ wt.a = t.a * pt.a + t.b * pt.c;
+ wt.b = t.a * pt.b + t.b * pt.d;
+ wt.c = t.c * pt.a + t.d * pt.c;
+ wt.d = t.c * pt.b + t.d * pt.d;
+ wt.tx = t.tx * pt.a + t.ty * pt.c + pt.tx;
+ wt.ty = t.tx * pt.b + t.ty * pt.d + pt.ty;
+ } else {
+ wt.a = t.a;
+ wt.b = t.b;
+ wt.c = t.c;
+ wt.d = t.d;
+ wt.tx = t.tx;
+ wt.ty = t.ty;
+ }
+ }
+
+ if (this._updateCurrentRegions) {
+ this._updateCurrentRegions();
+ this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble);
+ }
+
+ if (recursive) {
+ transformChildTree(node);
+ }
+
+ this._cacheDirty = true;
+ },
+
+ getNodeToParentTransform: function () {
+ if (!this._transform || this._dirtyFlag & cc.Node._dirtyFlags.transformDirty) {
+ this.transform();
+ }
+ return this._transform;
+ },
+
+ visit: function (parentCmd) {
+ var node = this._node, renderer = cc.renderer;
+
+ parentCmd = parentCmd || this.getParentRenderCmd();
+ if (parentCmd)
+ this._curLevel = parentCmd._curLevel + 1;
+
+ if (isNaN(node._customZ)) {
+ node._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+
+ this._syncStatus(parentCmd);
+ },
+
+ _updateDisplayColor: function (parentColor) {
+ var node = this._node;
+ var locDispColor = this._displayedColor, locRealColor = node._realColor;
+ var i, len, selChildren, item;
+ this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
+ if (this._cascadeColorEnabledDirty && !node._cascadeColorEnabled) {
+ locDispColor.r = locRealColor.r;
+ locDispColor.g = locRealColor.g;
+ locDispColor.b = locRealColor.b;
+ var whiteColor = new cc.Color(255, 255, 255, 255);
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd)
+ item._renderCmd._updateDisplayColor(whiteColor);
+ }
+ this._cascadeColorEnabledDirty = false;
+ } else {
+ if (parentColor === undefined) {
+ var locParent = node._parent;
+ if (locParent && locParent._cascadeColorEnabled)
+ parentColor = locParent.getDisplayedColor();
+ else
+ parentColor = cc.color.WHITE;
+ }
+ locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
+ locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
+ locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
+ if (node._cascadeColorEnabled) {
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd) {
+ item._renderCmd._updateDisplayColor(locDispColor);
+ item._renderCmd._updateColor();
+ }
+ }
+ }
+ }
+ this._dirtyFlag &= ~dirtyFlags.colorDirty;
+ },
+
+ _updateDisplayOpacity: function (parentOpacity) {
+ var node = this._node;
+ var i, len, selChildren, item;
+ this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
+ if (this._cascadeOpacityEnabledDirty && !node._cascadeOpacityEnabled) {
+ this._displayedOpacity = node._realOpacity;
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd)
+ item._renderCmd._updateDisplayOpacity(255);
+ }
+ this._cascadeOpacityEnabledDirty = false;
+ } else {
+ if (parentOpacity === undefined) {
+ var locParent = node._parent;
+ parentOpacity = 255;
+ if (locParent && locParent._cascadeOpacityEnabled)
+ parentOpacity = locParent.getDisplayedOpacity();
+ }
+ this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
+ if (node._cascadeOpacityEnabled) {
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd) {
+ item._renderCmd._updateDisplayOpacity(this._displayedOpacity);
+ item._renderCmd._updateColor();
+ }
+ }
+ }
+ }
+ this._dirtyFlag &= ~dirtyFlags.opacityDirty;
+ },
+
+ _syncDisplayColor: function (parentColor) {
+ var node = this._node, locDispColor = this._displayedColor, locRealColor = node._realColor;
+ if (parentColor === undefined) {
+ var locParent = node._parent;
+ if (locParent && locParent._cascadeColorEnabled)
+ parentColor = locParent.getDisplayedColor();
+ else
+ parentColor = cc.color.WHITE;
+ }
+ locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
+ locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
+ locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
+ },
+
+ _syncDisplayOpacity: function (parentOpacity) {
+ var node = this._node;
+ if (parentOpacity === undefined) {
+ var locParent = node._parent;
+ parentOpacity = 255;
+ if (locParent && locParent._cascadeOpacityEnabled)
+ parentOpacity = locParent.getDisplayedOpacity();
+ }
+ this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
+ },
+
+ _updateColor: function () {
+ },
+
+ _propagateFlagsDown: function (parentCmd) {
+ var locFlag = this._dirtyFlag;
+ var parentNode = parentCmd ? parentCmd._node : null;
+
+ if(parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & dirtyFlags.colorDirty))
+ locFlag |= dirtyFlags.colorDirty;
+
+ if(parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & dirtyFlags.opacityDirty))
+ locFlag |= dirtyFlags.opacityDirty;
+
+ if(parentCmd && (parentCmd._dirtyFlag & dirtyFlags.transformDirty))
+ locFlag |= dirtyFlags.transformDirty;
+
+ this._dirtyFlag = locFlag;
+ },
+
+ updateStatus: function () {
+ var locFlag = this._dirtyFlag;
+ var colorDirty = locFlag & dirtyFlags.colorDirty,
+ opacityDirty = locFlag & dirtyFlags.opacityDirty;
+
+ if (locFlag & dirtyFlags.contentDirty) {
+ this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
+ this._dirtyFlag &= ~dirtyFlags.contentDirty;
+ }
+
+ if (colorDirty)
+ this._updateDisplayColor();
+
+ if (opacityDirty)
+ this._updateDisplayOpacity();
+
+ if (colorDirty || opacityDirty)
+ this._updateColor();
+
+ if (locFlag & dirtyFlags.transformDirty) {
+ //update the transform
+ this.transform(this.getParentRenderCmd(), true);
+ this._dirtyFlag &= ~dirtyFlags.transformDirty;
+ }
+
+ if (locFlag & dirtyFlags.orderDirty)
+ this._dirtyFlag &= ~dirtyFlags.orderDirty;
+ },
+
+ _syncStatus: function (parentCmd) {
+ // In the visit logic does not restore the _dirtyFlag
+ // Because child elements need parent's _dirtyFlag to change himself
+ var locFlag = this._dirtyFlag, parentNode = parentCmd ? parentCmd._node : null;
+
+ // There is a possibility:
+ // The parent element changed color, child element not change
+ // This will cause the parent element changed color
+ // But while the child element does not enter the circulation
+ // Here will be reset state in last
+ // In order the child elements get the parent state
+ if (parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & dirtyFlags.colorDirty))
+ locFlag |= dirtyFlags.colorDirty;
+
+ if (parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & dirtyFlags.opacityDirty))
+ locFlag |= dirtyFlags.opacityDirty;
+
+ if (parentCmd && (parentCmd._dirtyFlag & dirtyFlags.transformDirty))
+ locFlag |= dirtyFlags.transformDirty;
+
+ this._dirtyFlag = locFlag;
+
+ var colorDirty = locFlag & dirtyFlags.colorDirty,
+ opacityDirty = locFlag & dirtyFlags.opacityDirty;
+
+ if (colorDirty)
+ //update the color
+ this._syncDisplayColor();
+
+ if (opacityDirty)
+ //update the opacity
+ this._syncDisplayOpacity();
+
+ if (colorDirty || opacityDirty)
+ this._updateColor();
+
+ if (locFlag & dirtyFlags.transformDirty)
+ //update the transform
+ this.transform(parentCmd);
+
+ if (locFlag & dirtyFlags.orderDirty)
+ this._dirtyFlag &= ~dirtyFlags.orderDirty;
+ },
+
+ setShaderProgram: function (shaderProgram) {
+ //do nothing.
+ },
+
+ getShaderProgram: function () {
+ return null;
+ },
+
+ getGLProgramState: function () {
+ return null;
+ },
+
+ setGLProgramState: function (glProgramState) {
+ // do nothing
+ },
+};
+
+cc.Node.RenderCmd.prototype.originTransform = cc.Node.RenderCmd.prototype.transform;
+cc.Node.RenderCmd.prototype.originUpdateStatus = cc.Node.RenderCmd.prototype.updateStatus;
+cc.Node.RenderCmd.prototype._originSyncStatus = cc.Node.RenderCmd.prototype._syncStatus;
+
+//-----------------------Canvas ---------------------------
+
+(function () {
+//The cc.Node's render command for Canvas
+ cc.Node.CanvasRenderCmd = function (renderable) {
+ this._node = renderable;
+ this._anchorPointInPoints = {x: 0, y: 0};
+ this._displayedColor = cc.color(255, 255, 255, 255);
+ this._cachedParent = null;
+ this._cacheDirty = false;
+ this._currentRegion = new cc.Region();
+ this._oldRegion = new cc.Region();
+ this._regionFlag = 0;
+ this._canUseDirtyRegion = false;
+ };
+
+ cc.Node.CanvasRenderCmd.RegionStatus = {
+ NotDirty: 0, //the region is not dirty
+ Dirty: 1, //the region is dirty, because of color, opacity or context
+ DirtyDouble: 2 //the region is moved, the old and the new one need considered when rendering
+ };
+
+ var proto = cc.Node.CanvasRenderCmd.prototype = Object.create(cc.Node.RenderCmd.prototype);
+ proto.constructor = cc.Node.CanvasRenderCmd;
+ proto._rootCtor = cc.Node.CanvasRenderCmd;
+
+ proto._notifyRegionStatus = function (status) {
+ if (this._needDraw && this._regionFlag < status) {
+ this._regionFlag = status;
+ }
+ };
+
+ var localBB = new cc.Rect();
+ proto.getLocalBB = function () {
+ var node = this._node;
+ localBB.x = localBB.y = 0;
+ localBB.width = node._contentSize.width;
+ localBB.height = node._contentSize.height;
+ return localBB;
+ };
+
+ proto._updateCurrentRegions = function () {
+ var temp = this._currentRegion;
+ this._currentRegion = this._oldRegion;
+ this._oldRegion = temp;
+ //hittest will call the transform, and set region flag to DirtyDouble, and the changes need to be considered for rendering
+ if (cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble === this._regionFlag && (!this._currentRegion.isEmpty())) {
+ this._oldRegion.union(this._currentRegion);
+ }
+ this._currentRegion.updateRegion(this.getLocalBB(), this._worldTransform);
+ };
+
+ proto.setDirtyFlag = function (dirtyFlag, child) {
+ cc.Node.RenderCmd.prototype.setDirtyFlag.call(this, dirtyFlag, child);
+ this._setCacheDirty(child); //TODO it should remove from here.
+ if (this._cachedParent)
+ this._cachedParent.setDirtyFlag(dirtyFlag, true);
+ };
+
+ proto._setCacheDirty = function () {
+ if (this._cacheDirty === false) {
+ this._cacheDirty = true;
+ var cachedP = this._cachedParent;
+ cachedP && cachedP !== this && cachedP._setNodeDirtyForCache && cachedP._setNodeDirtyForCache();
+ }
+ };
+
+ proto._setCachedParent = function (cachedParent) {
+ if (this._cachedParent === cachedParent)
+ return;
+
+ this._cachedParent = cachedParent;
+ var children = this._node._children;
+ for (var i = 0, len = children.length; i < len; i++)
+ children[i]._renderCmd._setCachedParent(cachedParent);
+ };
+
+ proto.detachFromParent = function () {
+ this._cachedParent = null;
+ var selChildren = this._node._children, item;
+ for (var i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd)
+ item._renderCmd.detachFromParent();
+ }
+ };
+
+ //util functions
+ cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc = function (blendFunc) {
+ if (!blendFunc)
+ return "source-over";
+ else {
+ if (( blendFunc.src === cc.SRC_ALPHA && blendFunc.dst === cc.ONE) || (blendFunc.src === cc.ONE && blendFunc.dst === cc.ONE))
+ return "lighter";
+ else if (blendFunc.src === cc.ZERO && blendFunc.dst === cc.SRC_ALPHA)
+ return "destination-in";
+ else if (blendFunc.src === cc.ZERO && blendFunc.dst === cc.ONE_MINUS_SRC_ALPHA)
+ return "destination-out";
+ else
+ return "source-over";
+ }
+ };
+})();
diff --git a/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js
new file mode 100644
index 0000000000..7680017273
--- /dev/null
+++ b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js
@@ -0,0 +1,65 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+// ------------------------------ The cc.Node's render command for WebGL ----------------------------------
+(function () {
+ cc.Node.WebGLRenderCmd = function (renderable) {
+ this._node = renderable;
+ this._anchorPointInPoints = {x: 0, y: 0};
+ this._displayedColor = cc.color(255, 255, 255, 255);
+ this._glProgramState = null;
+ };
+
+ var proto = cc.Node.WebGLRenderCmd.prototype = Object.create(cc.Node.RenderCmd.prototype);
+ proto.constructor = cc.Node.WebGLRenderCmd;
+ proto._rootCtor = cc.Node.WebGLRenderCmd;
+
+ proto._updateColor = function () {
+ };
+
+ proto.setShaderProgram = function (shaderProgram) {
+ this._glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(shaderProgram);
+ };
+
+ proto.getShaderProgram = function () {
+ return this._glProgramState ? this._glProgramState.getGLProgram() : null;
+ };
+
+ proto.getGLProgramState = function () {
+ return this._glProgramState;
+ };
+
+ proto.setGLProgramState = function (glProgramState) {
+ this._glProgramState = glProgramState;
+ };
+
+ // Use a property getter/setter for backwards compatability, and
+ // to ease the transition from using glPrograms directly, to
+ // using glProgramStates.
+ Object.defineProperty(proto, '_shaderProgram', {
+ set: function (value) { this.setShaderProgram(value); },
+ get: function () { return this.getShaderProgram(); }
+ });
+ /** @expose */
+ proto._shaderProgram;
+})();
diff --git a/cocos2d/core/cocoa/CCAffineTransform.js b/cocos2d/core/cocoa/CCAffineTransform.js
new file mode 100644
index 0000000000..8ff0957dfb
--- /dev/null
+++ b/cocos2d/core/cocoa/CCAffineTransform.js
@@ -0,0 +1,305 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.AffineTransform class represent an affine transform matrix. It's composed basically by translation, rotation, scale transformations.
+ * Please do not use its constructor directly, use cc.affineTransformMake alias function instead.
+ *
+ * @class cc.AffineTransform
+ * @param {Number} a
+ * @param {Number} b
+ * @param {Number} c
+ * @param {Number} d
+ * @param {Number} tx
+ * @param {Number} ty
+ * @see cc.affineTransformMake
+ */
+cc.AffineTransform = function (a, b, c, d, tx, ty) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.d = d;
+ this.tx = tx;
+ this.ty = ty;
+};
+
+/**
+ * Create a cc.AffineTransform object with all contents in the matrix
+ * @function
+ *
+ * @param {Number} a
+ * @param {Number} b
+ * @param {Number} c
+ * @param {Number} d
+ * @param {Number} tx
+ * @param {Number} ty
+ * @return {cc.AffineTransform}
+ */
+cc.affineTransformMake = function (a, b, c, d, tx, ty) {
+ return {a: a, b: b, c: c, d: d, tx: tx, ty: ty};
+};
+
+/**
+ * Apply the affine transformation on a point.
+ * @function
+ *
+ * @param {cc.Point|Number} point or x
+ * @param {cc.AffineTransform|Number} transOrY transform matrix or y
+ * @param {cc.AffineTransform} t transform matrix or y
+ * @return {cc.Point}
+ */
+cc.pointApplyAffineTransform = function (point, transOrY, t) {
+ var x, y;
+ if (t === undefined) {
+ t = transOrY;
+ x = point.x;
+ y = point.y;
+ } else {
+ x = point;
+ y = transOrY;
+ }
+ return {x: t.a * x + t.c * y + t.tx, y: t.b * x + t.d * y + t.ty};
+};
+
+cc._pointApplyAffineTransform = function (x, y, t) { //it will remove.
+ return cc.pointApplyAffineTransform(x, y, t);
+};
+
+/**
+ * Apply the affine transformation on a size.
+ * @function
+ *
+ * @param {cc.Size} size
+ * @param {cc.AffineTransform} t
+ * @return {cc.Size}
+ */
+cc.sizeApplyAffineTransform = function (size, t) {
+ return {width: t.a * size.width + t.c * size.height, height: t.b * size.width + t.d * size.height};
+};
+
+/**
+ * Create a identity transformation matrix:
+ * [ 1, 0, 0,
+ * 0, 1, 0 ]
+ * @function
+ *
+ * @return {cc.AffineTransform}
+ */
+cc.affineTransformMakeIdentity = function () {
+ return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
+};
+
+/**
+ * Create a identity transformation matrix:
+ * [ 1, 0, 0,
+ * 0, 1, 0 ]
+ * @function
+ *
+ * @return {cc.AffineTransform}
+ * @deprecated since v3.0, please use cc.affineTransformMakeIdentity() instead
+ * @see cc.affineTransformMakeIdentity
+ */
+cc.affineTransformIdentity = function () {
+ return {a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0};
+};
+
+/**
+ * Apply the affine transformation on a rect.
+ * @function
+ *
+ * @param {cc.Rect} rect
+ * @param {cc.AffineTransform} anAffineTransform
+ * @return {cc.Rect}
+ */
+cc.rectApplyAffineTransform = function (rect, anAffineTransform) {
+ var top = cc.rectGetMinY(rect);
+ var left = cc.rectGetMinX(rect);
+ var right = cc.rectGetMaxX(rect);
+ var bottom = cc.rectGetMaxY(rect);
+
+ var topLeft = cc.pointApplyAffineTransform(left, top, anAffineTransform);
+ var topRight = cc.pointApplyAffineTransform(right, top, anAffineTransform);
+ var bottomLeft = cc.pointApplyAffineTransform(left, bottom, anAffineTransform);
+ var bottomRight = cc.pointApplyAffineTransform(right, bottom, anAffineTransform);
+
+ var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
+ var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
+ var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
+ var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
+
+ return cc.rect(minX, minY, (maxX - minX), (maxY - minY));
+};
+
+cc._rectApplyAffineTransformIn = function (rect, anAffineTransform) {
+ var top = cc.rectGetMinY(rect);
+ var left = cc.rectGetMinX(rect);
+ var right = cc.rectGetMaxX(rect);
+ var bottom = cc.rectGetMaxY(rect);
+
+ var topLeft = cc.pointApplyAffineTransform(left, top, anAffineTransform);
+ var topRight = cc.pointApplyAffineTransform(right, top, anAffineTransform);
+ var bottomLeft = cc.pointApplyAffineTransform(left, bottom, anAffineTransform);
+ var bottomRight = cc.pointApplyAffineTransform(right, bottom, anAffineTransform);
+
+ var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
+ var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x);
+ var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
+ var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y);
+
+ rect.x = minX;
+ rect.y = minY;
+ rect.width = maxX - minX;
+ rect.height = maxY - minY;
+ return rect;
+};
+
+/**
+ * Create a new affine transformation with a base transformation matrix and a translation based on it.
+ * @function
+ *
+ * @param {cc.AffineTransform} t The base affine transform object
+ * @param {Number} tx The translation on x axis
+ * @param {Number} ty The translation on y axis
+ * @return {cc.AffineTransform}
+ */
+cc.affineTransformTranslate = function (t, tx, ty) {
+ return {
+ a: t.a,
+ b: t.b,
+ c: t.c,
+ d: t.d,
+ tx: t.tx + t.a * tx + t.c * ty,
+ ty: t.ty + t.b * tx + t.d * ty
+ };
+};
+
+/**
+ * Create a new affine transformation with a base transformation matrix and a scale based on it.
+ * @function
+ * @param {cc.AffineTransform} t The base affine transform object
+ * @param {Number} sx The scale on x axis
+ * @param {Number} sy The scale on y axis
+ * @return {cc.AffineTransform}
+ */
+cc.affineTransformScale = function (t, sx, sy) {
+ return {a: t.a * sx, b: t.b * sx, c: t.c * sy, d: t.d * sy, tx: t.tx, ty: t.ty};
+};
+
+/**
+ * Create a new affine transformation with a base transformation matrix and a rotation based on it.
+ * @function
+ * @param {cc.AffineTransform} aTransform The base affine transform object
+ * @param {Number} anAngle The angle to rotate
+ * @return {cc.AffineTransform}
+ */
+cc.affineTransformRotate = function (aTransform, anAngle) {
+ var fSin = Math.sin(anAngle);
+ var fCos = Math.cos(anAngle);
+
+ return {
+ a: aTransform.a * fCos + aTransform.c * fSin,
+ b: aTransform.b * fCos + aTransform.d * fSin,
+ c: aTransform.c * fCos - aTransform.a * fSin,
+ d: aTransform.d * fCos - aTransform.b * fSin,
+ tx: aTransform.tx,
+ ty: aTransform.ty
+ };
+};
+
+/**
+ * Concatenate a transform matrix to another and return the result:
+ * t' = t1 * t2
+ * @function
+ * @param {cc.AffineTransform} t1 The first transform object
+ * @param {cc.AffineTransform} t2 The transform object to concatenate
+ * @return {cc.AffineTransform} The result of concatenation
+ */
+cc.affineTransformConcat = function (t1, t2) {
+ return {
+ a: t1.a * t2.a + t1.b * t2.c, //a
+ b: t1.a * t2.b + t1.b * t2.d, //b
+ c: t1.c * t2.a + t1.d * t2.c, //c
+ d: t1.c * t2.b + t1.d * t2.d, //d
+ tx: t1.tx * t2.a + t1.ty * t2.c + t2.tx, //tx
+ ty: t1.tx * t2.b + t1.ty * t2.d + t2.ty
+ }; //ty
+};
+
+/**
+ * Concatenate a transform matrix to another
+ * The results are reflected in the first matrix.
+ * t' = t1 * t2
+ * @function
+ * @param {cc.AffineTransform} t1 The first transform object
+ * @param {cc.AffineTransform} t2 The transform object to concatenate
+ * @return {cc.AffineTransform} The result of concatenation
+ */
+cc.affineTransformConcatIn = function (t1, t2) {
+ var a = t1.a, b = t1.b, c = t1.c, d = t1.d, tx = t1.tx, ty = t1.ty;
+ t1.a = a * t2.a + b * t2.c;
+ t1.b = a * t2.b + b * t2.d;
+ t1.c = c * t2.a + d * t2.c;
+ t1.d = c * t2.b + d * t2.d;
+ t1.tx = tx * t2.a + ty * t2.c + t2.tx;
+ t1.ty = tx * t2.b + ty * t2.d + t2.ty;
+ return t1;
+};
+
+/**
+ * Return true if an affine transform equals to another, false otherwise.
+ * @function
+ * @param {cc.AffineTransform} t1
+ * @param {cc.AffineTransform} t2
+ * @return {Boolean}
+ */
+cc.affineTransformEqualToTransform = function (t1, t2) {
+ return ((t1.a === t2.a) && (t1.b === t2.b) && (t1.c === t2.c) && (t1.d === t2.d) && (t1.tx === t2.tx) && (t1.ty === t2.ty));
+};
+
+/**
+ * Get the invert transform of an AffineTransform object
+ * @function
+ * @param {cc.AffineTransform} t
+ * @return {cc.AffineTransform} The inverted transform object
+ */
+cc.affineTransformInvert = function (t) {
+ var determinant = 1 / (t.a * t.d - t.b * t.c);
+ return {
+ a: determinant * t.d, b: -determinant * t.b, c: -determinant * t.c, d: determinant * t.a,
+ tx: determinant * (t.c * t.ty - t.d * t.tx), ty: determinant * (t.b * t.tx - t.a * t.ty)
+ };
+};
+
+cc.affineTransformInvertOut = function (t, out) {
+ var a = t.a, b = t.b, c = t.c, d = t.d;
+ var determinant = 1 / (a * d - b * c);
+ out.a = determinant * d;
+ out.b = -determinant * b;
+ out.c = -determinant * c;
+ out.d = determinant * a;
+ out.tx = determinant * (c * t.ty - d * t.tx);
+ out.ty = determinant * (b * t.tx - a * t.ty);
+};
diff --git a/cocos2d/core/cocoa/CCGeometry.js b/cocos2d/core/cocoa/CCGeometry.js
new file mode 100644
index 0000000000..a3690f21c1
--- /dev/null
+++ b/cocos2d/core/cocoa/CCGeometry.js
@@ -0,0 +1,338 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.Point is the class for point object, please do not use its constructor to create points, use cc.p() alias function instead.
+ * @class cc.Point
+ * @param {Number} x
+ * @param {Number} y
+ *
+ * @property x {Number}
+ * @property y {Number}
+ * @see cc.p
+ */
+cc.Point = function (x, y) {
+ this.x = x || 0;
+ this.y = y || 0;
+};
+
+/**
+ * Helper function that creates a cc.Point.
+ * @function
+ * @param {Number|cc.Point} x a Number or a size object
+ * @param {Number} y
+ * @return {cc.Point}
+ * @example
+ * var point1 = cc.p();
+ * var point2 = cc.p(100, 100);
+ * var point3 = cc.p(point2);
+ * var point4 = cc.p({x: 100, y: 100});
+ */
+cc.p = function (x, y) {
+ // This can actually make use of "hidden classes" in JITs and thus decrease
+ // memory usage and overall performance drastically
+ // return cc.p(x, y);
+ // but this one will instead flood the heap with newly allocated hash maps
+ // giving little room for optimization by the JIT,
+ // note: we have tested this item on Chrome and firefox, it is faster than cc.p(x, y)
+ if (x === undefined)
+ return {x: 0, y: 0};
+ if (y === undefined)
+ return {x: x.x, y: x.y};
+ return {x: x, y: y};
+};
+
+/**
+ * Check whether a point's value equals to another
+ * @function
+ * @param {cc.Point} point1
+ * @param {cc.Point} point2
+ * @return {Boolean}
+ */
+cc.pointEqualToPoint = function (point1, point2) {
+ return point1 && point2 && (point1.x === point2.x) && (point1.y === point2.y);
+};
+
+
+/**
+ * cc.Size is the class for size object, please do not use its constructor to create sizes, use cc.size() alias function instead.
+ * @class cc.Size
+ * @param {Number} width
+ * @param {Number} height
+ * @property {Number} width
+ * @property {Number} height
+ * @see cc.size
+ */
+cc.Size = function (width, height) {
+ this.width = width || 0;
+ this.height = height || 0;
+};
+
+/**
+ * Helper function that creates a cc.Size.
+ * @function
+ * @param {Number|cc.Size} w width or a size object
+ * @param {Number} h height
+ * @return {cc.Size}
+ * @example
+ * var size1 = cc.size();
+ * var size2 = cc.size(100,100);
+ * var size3 = cc.size(size2);
+ * var size4 = cc.size({width: 100, height: 100});
+ */
+cc.size = function (w, h) {
+ // This can actually make use of "hidden classes" in JITs and thus decrease
+ // memory usage and overall performance drastically
+ //return cc.size(w, h);
+ // but this one will instead flood the heap with newly allocated hash maps
+ // giving little room for optimization by the JIT
+ // note: we have tested this item on Chrome and firefox, it is faster than cc.size(w, h)
+ if (w === undefined)
+ return {width: 0, height: 0};
+ if (h === undefined)
+ return {width: w.width, height: w.height};
+ return {width: w, height: h};
+};
+
+/**
+ * Check whether a point's value equals to another
+ * @function
+ * @param {cc.Size} size1
+ * @param {cc.Size} size2
+ * @return {Boolean}
+ */
+cc.sizeEqualToSize = function (size1, size2) {
+ return (size1 && size2 && (size1.width === size2.width) && (size1.height === size2.height));
+};
+
+
+/**
+ * cc.Rect is the class for rect object, please do not use its constructor to create rects, use cc.rect() alias function instead.
+ * @class cc.Rect
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} width
+ * @param {Number} height
+ *
+ * @property {Number} x
+ * @property {Number} y
+ * @property {Number} width
+ * @property {Number} height
+ *
+ * @see cc.rect
+ */
+cc.Rect = function (x, y, width, height) {
+ this.x = x||0;
+ this.y = y||0;
+ this.width = width||0;
+ this.height = height||0;
+};
+
+/**
+ * Helper function that creates a cc.Rect.
+ * @function
+ * @param {Number|cc.Rect} x a number or a rect object
+ * @param {Number} y
+ * @param {Number} w
+ * @param {Number} h
+ * @returns {cc.Rect}
+ * @example
+ * var rect1 = cc.rect();
+ * var rect2 = cc.rect(100,100,100,100);
+ * var rect3 = cc.rect(rect2);
+ * var rect4 = cc.rect({x: 100, y: 100, width: 100, height: 100});
+ */
+cc.rect = function (x, y, w, h) {
+ if (x === undefined)
+ return {x: 0, y: 0, width: 0, height: 0};
+ if (y === undefined)
+ return {x: x.x, y: x.y, width: x.width, height: x.height};
+ return {x: x, y: y, width: w, height: h };
+};
+
+/**
+ * Check whether a rect's value equals to another
+ * @function
+ * @param {cc.Rect} rect1
+ * @param {cc.Rect} rect2
+ * @return {Boolean}
+ */
+cc.rectEqualToRect = function (rect1, rect2) {
+ return rect1 && rect2 && (rect1.x === rect2.x) && (rect1.y === rect2.y) && (rect1.width === rect2.width) && (rect1.height === rect2.height);
+};
+
+cc._rectEqualToZero = function(rect){
+ return rect && (rect.x === 0) && (rect.y === 0) && (rect.width === 0) && (rect.height === 0);
+};
+
+/**
+ * Check whether the rect1 contains rect2
+ * @function
+ * @param {cc.Rect} rect1
+ * @param {cc.Rect} rect2
+ * @return {Boolean}
+ */
+cc.rectContainsRect = function (rect1, rect2) {
+ if (!rect1 || !rect2)
+ return false;
+ return !((rect1.x >= rect2.x) || (rect1.y >= rect2.y) ||
+ ( rect1.x + rect1.width <= rect2.x + rect2.width) ||
+ ( rect1.y + rect1.height <= rect2.y + rect2.height));
+};
+
+/**
+ * Returns the rightmost x-value of a rect
+ * @function
+ * @param {cc.Rect} rect
+ * @return {Number} The rightmost x value
+ */
+cc.rectGetMaxX = function (rect) {
+ return (rect.x + rect.width);
+};
+
+/**
+ * Return the midpoint x-value of a rect
+ * @function
+ * @param {cc.Rect} rect
+ * @return {Number} The midpoint x value
+ */
+cc.rectGetMidX = function (rect) {
+ return (rect.x + rect.width / 2.0);
+};
+/**
+ * Returns the leftmost x-value of a rect
+ * @function
+ * @param {cc.Rect} rect
+ * @return {Number} The leftmost x value
+ */
+cc.rectGetMinX = function (rect) {
+ return rect.x;
+};
+
+/**
+ * Return the topmost y-value of a rect
+ * @function
+ * @param {cc.Rect} rect
+ * @return {Number} The topmost y value
+ */
+cc.rectGetMaxY = function (rect) {
+ return(rect.y + rect.height);
+};
+
+/**
+ * Return the midpoint y-value of `rect'
+ * @function
+ * @param {cc.Rect} rect
+ * @return {Number} The midpoint y value
+ */
+cc.rectGetMidY = function (rect) {
+ return rect.y + rect.height / 2.0;
+};
+
+/**
+ * Return the bottommost y-value of a rect
+ * @function
+ * @param {cc.Rect} rect
+ * @return {Number} The bottommost y value
+ */
+cc.rectGetMinY = function (rect) {
+ return rect.y;
+};
+
+/**
+ * Check whether a rect contains a point
+ * @function
+ * @param {cc.Rect} rect
+ * @param {cc.Point} point
+ * @return {Boolean}
+ */
+cc.rectContainsPoint = function (rect, point) {
+ return (point.x >= cc.rectGetMinX(rect) && point.x <= cc.rectGetMaxX(rect) &&
+ point.y >= cc.rectGetMinY(rect) && point.y <= cc.rectGetMaxY(rect)) ;
+};
+
+/**
+ * Check whether a rect intersect with another
+ * @function
+ * @param {cc.Rect} rectA
+ * @param {cc.Rect} rectB
+ * @return {Boolean}
+ */
+cc.rectIntersectsRect = function (ra, rb) {
+ var maxax = ra.x + ra.width,
+ maxay = ra.y + ra.height,
+ maxbx = rb.x + rb.width,
+ maxby = rb.y + rb.height;
+ return !(maxax < rb.x || maxbx < ra.x || maxay < rb.y || maxby < ra.y);
+};
+
+/**
+ * Check whether a rect overlaps another
+ * @function
+ * @param {cc.Rect} rectA
+ * @param {cc.Rect} rectB
+ * @return {Boolean}
+ */
+cc.rectOverlapsRect = function (rectA, rectB) {
+ return !((rectA.x + rectA.width < rectB.x) ||
+ (rectB.x + rectB.width < rectA.x) ||
+ (rectA.y + rectA.height < rectB.y) ||
+ (rectB.y + rectB.height < rectA.y));
+};
+
+/**
+ * Returns the smallest rectangle that contains the two source rectangles.
+ * @function
+ * @param {cc.Rect} rectA
+ * @param {cc.Rect} rectB
+ * @return {cc.Rect}
+ */
+cc.rectUnion = function (rectA, rectB) {
+ var rect = cc.rect(0, 0, 0, 0);
+ rect.x = Math.min(rectA.x, rectB.x);
+ rect.y = Math.min(rectA.y, rectB.y);
+ rect.width = Math.max(rectA.x + rectA.width, rectB.x + rectB.width) - rect.x;
+ rect.height = Math.max(rectA.y + rectA.height, rectB.y + rectB.height) - rect.y;
+ return rect;
+};
+
+/**
+ * Returns the overlapping portion of 2 rectangles
+ * @function
+ * @param {cc.Rect} rectA
+ * @param {cc.Rect} rectB
+ * @return {cc.Rect}
+ */
+cc.rectIntersection = function (rectA, rectB) {
+ var intersection = cc.rect(
+ Math.max(cc.rectGetMinX(rectA), cc.rectGetMinX(rectB)),
+ Math.max(cc.rectGetMinY(rectA), cc.rectGetMinY(rectB)),
+ 0, 0);
+
+ intersection.width = Math.min(cc.rectGetMaxX(rectA), cc.rectGetMaxX(rectB)) - cc.rectGetMinX(intersection);
+ intersection.height = Math.min(cc.rectGetMaxY(rectA), cc.rectGetMaxY(rectB)) - cc.rectGetMinY(intersection);
+ return intersection;
+};
diff --git a/cocos2d/cocos2d_externs.js b/cocos2d/core/cocos2d_externs.js
similarity index 56%
rename from cocos2d/cocos2d_externs.js
rename to cocos2d/core/cocos2d_externs.js
index 69338757af..97c83972eb 100644
--- a/cocos2d/cocos2d_externs.js
+++ b/cocos2d/core/cocos2d_externs.js
@@ -15,7 +15,7 @@
CSSProperties.prototype._super;
/**
- * cocos2d-html5-only. We need this becuase the cc.Class.extend's new
+ * cocos2d-html5-only. We need this because the cc.Class.extend's new
* infrastructure requires it.
* @type {string}
*/
@@ -44,3 +44,23 @@ CSSProperties.prototype.accelerationIncludingGravity;
CSSProperties.prototype.gamma;
CSSProperties.prototype.beta;
CSSProperties.prototype.alpha;
+
+
+var gl = gl || {};
+CSSProperties.prototype.gl;
+
+CSSProperties.prototype.AudioContext;
+CSSProperties.prototype.webkitAudioContext;
+CSSProperties.prototype.mozAudioContext;
+CSSProperties.prototype.createBufferSource;
+CSSProperties.prototype.createGain;
+CSSProperties.prototype.createGainNode;
+CSSProperties.prototype.destination;
+CSSProperties.prototype.decodeAudioData;
+CSSProperties.prototype.gain;
+CSSProperties.prototype.connect;
+CSSProperties.prototype.playbackState;
+CSSProperties.prototype.noteGrainOn;
+CSSProperties.prototype.noteOn;
+
+
diff --git a/cocos2d/core/event-manager/CCEvent.js b/cocos2d/core/event-manager/CCEvent.js
new file mode 100644
index 0000000000..fa5c47f5a1
--- /dev/null
+++ b/cocos2d/core/event-manager/CCEvent.js
@@ -0,0 +1,449 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * Base class of all kinds of events.
+ * @class
+ * @extends cc.Class
+ */
+cc.Event = cc.Class.extend(/** @lends cc.Event# */{
+ _type: 0, // Event type
+ _isStopped: false, //< whether the event has been stopped.
+ _currentTarget: null, //< Current target
+
+ _setCurrentTarget: function (target) {
+ this._currentTarget = target;
+ },
+
+ ctor: function (type) {
+ this._type = type;
+ },
+
+ /**
+ * Gets the event type
+ * @function
+ * @returns {Number}
+ */
+ getType: function () {
+ return this._type;
+ },
+
+ /**
+ * Stops propagation for current event
+ * @function
+ */
+ stopPropagation: function () {
+ this._isStopped = true;
+ },
+
+ /**
+ * Checks whether the event has been stopped
+ * @function
+ * @returns {boolean}
+ */
+ isStopped: function () {
+ return this._isStopped;
+ },
+
+ /**
+ *
+ * Gets current target of the event
+ * note: It only be available when the event listener is associated with node.
+ * It returns 0 when the listener is associated with fixed priority.
+ *
+ * @function
+ * @returns {cc.Node} The target with which the event associates.
+ */
+ getCurrentTarget: function () {
+ return this._currentTarget;
+ }
+});
+
+//event type
+/**
+ * The type code of Touch event.
+ * @constant
+ * @type {number}
+ */
+cc.Event.TOUCH = 0;
+/**
+ * The type code of Keyboard event.
+ * @constant
+ * @type {number}
+ */
+cc.Event.KEYBOARD = 1;
+/**
+ * The type code of Acceleration event.
+ * @constant
+ * @type {number}
+ */
+cc.Event.ACCELERATION = 2;
+/**
+ * The type code of Mouse event.
+ * @constant
+ * @type {number}
+ */
+cc.Event.MOUSE = 3;
+/**
+ * The type code of UI focus event.
+ * @constant
+ * @type {number}
+ */
+cc.Event.FOCUS = 4;
+/**
+ * The type code of Custom event.
+ * @constant
+ * @type {number}
+ */
+cc.Event.CUSTOM = 6;
+
+/**
+ * The Custom event
+ * @class
+ * @extends cc.Event
+ */
+cc.EventCustom = cc.Event.extend(/** @lends cc.EventCustom# */{
+ _eventName: null,
+ _userData: null, // User data
+
+ ctor: function (eventName) {
+ cc.Event.prototype.ctor.call(this, cc.Event.CUSTOM);
+ this._eventName = eventName;
+ },
+
+ /**
+ * Sets user data
+ * @param {*} data
+ */
+ setUserData: function (data) {
+ this._userData = data;
+ },
+
+ /**
+ * Gets user data
+ * @returns {*}
+ */
+ getUserData: function () {
+ return this._userData;
+ },
+
+ /**
+ * Gets event name
+ * @returns {String}
+ */
+ getEventName: function () {
+ return this._eventName;
+ }
+});
+
+/**
+ * The mouse event
+ * @class
+ * @extends cc.Event
+ */
+cc.EventMouse = cc.Event.extend(/** @lends cc.EventMouse# */{
+ _eventType: 0,
+ _button: 0,
+ _x: 0,
+ _y: 0,
+ _prevX: 0,
+ _prevY: 0,
+ _scrollX: 0,
+ _scrollY: 0,
+
+ ctor: function (eventType) {
+ cc.Event.prototype.ctor.call(this, cc.Event.MOUSE);
+ this._eventType = eventType;
+ },
+
+ /**
+ * Sets scroll data
+ * @param {number} scrollX
+ * @param {number} scrollY
+ */
+ setScrollData: function (scrollX, scrollY) {
+ this._scrollX = scrollX;
+ this._scrollY = scrollY;
+ },
+
+ /**
+ * Returns the x axis scroll value
+ * @returns {number}
+ */
+ getScrollX: function () {
+ return this._scrollX;
+ },
+
+ /**
+ * Returns the y axis scroll value
+ * @returns {number}
+ */
+ getScrollY: function () {
+ return this._scrollY;
+ },
+
+ /**
+ * Sets cursor location
+ * @param {number} x
+ * @param {number} y
+ */
+ setLocation: function (x, y) {
+ this._x = x;
+ this._y = y;
+ },
+
+ /**
+ * Returns cursor location
+ * @return {cc.Point} location
+ */
+ getLocation: function () {
+ return {x: this._x, y: this._y};
+ },
+
+ /**
+ * Returns the current cursor location in screen coordinates
+ * @return {cc.Point}
+ */
+ getLocationInView: function() {
+ return {x: this._x, y: cc.view._designResolutionSize.height - this._y};
+ },
+
+ _setPrevCursor: function (x, y) {
+ this._prevX = x;
+ this._prevY = y;
+ },
+
+ /**
+ * Returns the delta distance from the previous location to current location
+ * @return {cc.Point}
+ */
+ getDelta: function () {
+ return {x: this._x - this._prevX, y: this._y - this._prevY};
+ },
+
+ /**
+ * Returns the X axis delta distance from the previous location to current location
+ * @return {Number}
+ */
+ getDeltaX: function () {
+ return this._x - this._prevX;
+ },
+
+ /**
+ * Returns the Y axis delta distance from the previous location to current location
+ * @return {Number}
+ */
+ getDeltaY: function () {
+ return this._y - this._prevY;
+ },
+
+ /**
+ * Sets mouse button
+ * @param {number} button
+ */
+ setButton: function (button) {
+ this._button = button;
+ },
+
+ /**
+ * Returns mouse button
+ * @returns {number}
+ */
+ getButton: function () {
+ return this._button;
+ },
+
+ /**
+ * Returns location X axis data
+ * @returns {number}
+ */
+ getLocationX: function () {
+ return this._x;
+ },
+
+ /**
+ * Returns location Y axis data
+ * @returns {number}
+ */
+ getLocationY: function () {
+ return this._y;
+ }
+});
+
+//Different types of MouseEvent
+/**
+ * The none event code of mouse event.
+ * @constant
+ * @type {number}
+ */
+cc.EventMouse.NONE = 0;
+/**
+ * The event type code of mouse down event.
+ * @constant
+ * @type {number}
+ */
+cc.EventMouse.DOWN = 1;
+/**
+ * The event type code of mouse up event.
+ * @constant
+ * @type {number}
+ */
+cc.EventMouse.UP = 2;
+/**
+ * The event type code of mouse move event.
+ * @constant
+ * @type {number}
+ */
+cc.EventMouse.MOVE = 3;
+/**
+ * The event type code of mouse scroll event.
+ * @constant
+ * @type {number}
+ */
+cc.EventMouse.SCROLL = 4;
+
+/**
+ * The tag of Mouse left button
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_LEFT = 0;
+
+/**
+ * The tag of Mouse right button (The right button number is 2 on browser)
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_RIGHT = 2;
+
+/**
+ * The tag of Mouse middle button (The right button number is 1 on browser)
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_MIDDLE = 1;
+
+/**
+ * The tag of Mouse button 4
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_4 = 3;
+
+/**
+ * The tag of Mouse button 5
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_5 = 4;
+
+/**
+ * The tag of Mouse button 6
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_6 = 5;
+
+/**
+ * The tag of Mouse button 7
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_7 = 6;
+
+/**
+ * The tag of Mouse button 8
+ * @constant
+ * @type {Number}
+ */
+cc.EventMouse.BUTTON_8 = 7;
+
+/**
+ * The touch event
+ * @class
+ * @extends cc.Event
+ */
+cc.EventTouch = cc.Event.extend(/** @lends cc.EventTouch# */{
+ _eventCode: 0,
+ _touches: null,
+
+ ctor: function (arr) {
+ cc.Event.prototype.ctor.call(this, cc.Event.TOUCH);
+ this._touches = arr || [];
+ },
+
+ /**
+ * Returns event code
+ * @returns {number}
+ */
+ getEventCode: function () {
+ return this._eventCode;
+ },
+
+ /**
+ * Returns touches of event
+ * @returns {Array}
+ */
+ getTouches: function () {
+ return this._touches;
+ },
+
+ _setEventCode: function (eventCode) {
+ this._eventCode = eventCode;
+ },
+
+ _setTouches: function (touches) {
+ this._touches = touches;
+ }
+});
+
+/**
+ * The maximum touch numbers
+ * @constant
+ * @type {Number}
+ */
+cc.EventTouch.MAX_TOUCHES = 5;
+
+cc.EventTouch.EventCode = {BEGAN: 0, MOVED: 1, ENDED: 2, CANCELLED: 3};
+
+/**
+ * Focus change event for UI widget
+ * @class
+ * @extends cc.Event
+ */
+cc.EventFocus = cc.Event.extend(/** @lends cc.EventTouch# */{
+ _widgetGetFocus: null,
+ _widgetLoseFocus: null,
+ /**
+ * Constructor function.
+ * @param {ccui.Widget} widgetLoseFocus
+ * @param {ccui.Widget} widgetGetFocus
+ */
+ ctor: function(widgetLoseFocus, widgetGetFocus){
+ cc.Event.prototype.ctor.call(this, cc.Event.FOCUS);
+ this._widgetGetFocus = widgetGetFocus;
+ this._widgetLoseFocus = widgetLoseFocus;
+ }
+});
\ No newline at end of file
diff --git a/cocos2d/core/event-manager/CCEventExtension.js b/cocos2d/core/event-manager/CCEventExtension.js
new file mode 100644
index 0000000000..a14968f0f7
--- /dev/null
+++ b/cocos2d/core/event-manager/CCEventExtension.js
@@ -0,0 +1,126 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The acceleration event
+ * @class
+ * @extends cc.Event
+ */
+cc.EventAcceleration = cc.Event.extend(/** @lends cc.EventAcceleration# */{
+ _acc: null,
+ ctor: function (acc) {
+ cc.Event.prototype.ctor.call(this, cc.Event.ACCELERATION);
+ this._acc = acc;
+ }
+});
+
+/**
+ * The keyboard event
+ * @class
+ * @extends cc.Event
+ */
+cc.EventKeyboard = cc.Event.extend(/** @lends cc.EventKeyboard# */{
+ _keyCode: 0,
+ _isPressed: false,
+ ctor: function (keyCode, isPressed) {
+ cc.Event.prototype.ctor.call(this, cc.Event.KEYBOARD);
+ this._keyCode = keyCode;
+ this._isPressed = isPressed;
+ }
+});
+
+
+//Acceleration
+cc._EventListenerAcceleration = cc.EventListener.extend({
+ _onAccelerationEvent: null,
+
+ ctor: function (callback) {
+ this._onAccelerationEvent = callback;
+ var selfPointer = this;
+ var listener = function (event) {
+ selfPointer._onAccelerationEvent(event._acc, event);
+ };
+ cc.EventListener.prototype.ctor.call(this, cc.EventListener.ACCELERATION, cc._EventListenerAcceleration.LISTENER_ID, listener);
+ },
+
+ checkAvailable: function () {
+
+ cc.assert(this._onAccelerationEvent, cc._LogInfos._EventListenerAcceleration_checkAvailable);
+
+ return true;
+ },
+
+ clone: function () {
+ return new cc._EventListenerAcceleration(this._onAccelerationEvent);
+ }
+});
+
+cc._EventListenerAcceleration.LISTENER_ID = "__cc_acceleration";
+
+cc._EventListenerAcceleration.create = function (callback) {
+ return new cc._EventListenerAcceleration(callback);
+};
+
+
+//Keyboard
+cc._EventListenerKeyboard = cc.EventListener.extend({
+ onKeyPressed: null,
+ onKeyReleased: null,
+
+ ctor: function () {
+ var selfPointer = this;
+ var listener = function (event) {
+ if (event._isPressed) {
+ if (selfPointer.onKeyPressed)
+ selfPointer.onKeyPressed(event._keyCode, event);
+ } else {
+ if (selfPointer.onKeyReleased)
+ selfPointer.onKeyReleased(event._keyCode, event);
+ }
+ };
+ cc.EventListener.prototype.ctor.call(this, cc.EventListener.KEYBOARD, cc._EventListenerKeyboard.LISTENER_ID, listener);
+ },
+
+ clone: function () {
+ var eventListener = new cc._EventListenerKeyboard();
+ eventListener.onKeyPressed = this.onKeyPressed;
+ eventListener.onKeyReleased = this.onKeyReleased;
+ return eventListener;
+ },
+
+ checkAvailable: function () {
+ if (this.onKeyPressed === null && this.onKeyReleased === null) {
+ cc.log(cc._LogInfos._EventListenerKeyboard_checkAvailable);
+ return false;
+ }
+ return true;
+ }
+});
+
+cc._EventListenerKeyboard.LISTENER_ID = "__cc_keyboard";
+
+cc._EventListenerKeyboard.create = function () {
+ return new cc._EventListenerKeyboard();
+};
\ No newline at end of file
diff --git a/cocos2d/core/event-manager/CCEventHelper.js b/cocos2d/core/event-manager/CCEventHelper.js
new file mode 100644
index 0000000000..b005e71c59
--- /dev/null
+++ b/cocos2d/core/event-manager/CCEventHelper.js
@@ -0,0 +1,138 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2015 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+// The event helper
+cc.EventHelper = function () {
+};
+
+cc.EventHelper.prototype = {
+ constructor: cc.EventHelper,
+
+ apply: function (object) {
+ object.addEventListener = cc.EventHelper.prototype.addEventListener;
+ object.hasEventListener = cc.EventHelper.prototype.hasEventListener;
+ object.removeEventListener = cc.EventHelper.prototype.removeEventListener;
+ object.dispatchEvent = cc.EventHelper.prototype.dispatchEvent;
+ },
+
+ addEventListener: function (type, listener, target) {
+ //check 'type' status, if the status is ready, dispatch event next frame
+ if (type === "load" && this._textureLoaded) { //only load event checked.
+ setTimeout(function () {
+ listener.call(target);
+ }, 0);
+ return;
+ }
+
+ if (this._listeners === undefined)
+ this._listeners = {};
+
+ var listeners = this._listeners;
+ if (listeners[type] === undefined)
+ listeners[type] = [];
+
+ if (!this.hasEventListener(type, listener, target))
+ listeners[type].push({callback: listener, eventTarget: target});
+ },
+
+ hasEventListener: function (type, listener, target) {
+ if (this._listeners === undefined)
+ return false;
+
+ var listeners = this._listeners;
+ if (listeners[type] !== undefined) {
+ for (var i = 0, len = listeners.length; i < len; i++) {
+ var selListener = listeners[i];
+ if (selListener.callback === listener && selListener.eventTarget === target)
+ return true;
+ }
+ }
+ return false;
+ },
+
+ removeEventListener: function (type, listener, target) {
+ if (this._listeners === undefined)
+ return;
+
+ var listeners = this._listeners;
+ var listenerArray = listeners[type];
+
+ if (listenerArray !== undefined) {
+ for (var i = 0; i < listenerArray.length;) {
+ var selListener = listenerArray[i];
+ if (selListener.eventTarget === target && selListener.callback === listener)
+ listenerArray.splice(i, 1);
+ else
+ i++
+ }
+ }
+ },
+
+ removeEventTarget: function (type, listener, target) {
+ if (this._listeners === undefined)
+ return;
+
+ var listeners = this._listeners;
+ var listenerArray = listeners[type];
+
+ if (listenerArray !== undefined) {
+ for (var i = 0; i < listenerArray.length;) {
+ var selListener = listenerArray[i];
+ if (selListener.eventTarget === target)
+ listenerArray.splice(i, 1);
+ else
+ i++
+ }
+ }
+ },
+
+ dispatchEvent: function (event, clearAfterDispatch) {
+ if (this._listeners === undefined)
+ return;
+
+ if (clearAfterDispatch == null)
+ clearAfterDispatch = true;
+ var listeners = this._listeners;
+ var listenerArray = listeners[event];
+
+ if (listenerArray !== undefined) {
+ var array = [];
+ var length = listenerArray.length;
+
+ for (var i = 0; i < length; i++) {
+ array[i] = listenerArray[i];
+ }
+
+ for (i = 0; i < length; i++) {
+ array[i].callback.call(array[i].eventTarget, this);
+ }
+
+ if (clearAfterDispatch)
+ listenerArray.length = 0;
+ }
+ }
+};
+
+cc.EventHelper.prototype.apply(cc.game);
diff --git a/cocos2d/core/event-manager/CCEventListener.js b/cocos2d/core/event-manager/CCEventListener.js
new file mode 100644
index 0000000000..c970c43fdf
--- /dev/null
+++ b/cocos2d/core/event-manager/CCEventListener.js
@@ -0,0 +1,514 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ *
+ * The base class of event listener.
+ * If you need custom listener which with different callback, you need to inherit this class.
+ * For instance, you could refer to EventListenerAcceleration, EventListenerKeyboard,
+ * EventListenerTouchOneByOne, EventListenerCustom.
+ *
+ * @class
+ * @extends cc.Class
+ */
+cc.EventListener = cc.Class.extend(/** @lends cc.EventListener# */{
+ _onEvent: null, // Event callback function
+ _type: 0, // Event listener type
+ _listenerID: null, // Event listener ID
+ _registered: false, // Whether the listener has been added to dispatcher.
+
+ _fixedPriority: 0, // The higher the number, the higher the priority, 0 is for scene graph base priority.
+ _node: null, // scene graph based priority
+ _paused: true, // Whether the listener is paused
+ _isEnabled: true, // Whether the listener is enabled
+
+ /**
+ * Initializes event with type and callback function
+ * @param {number} type
+ * @param {string} listenerID
+ * @param {function} callback
+ */
+ ctor: function (type, listenerID, callback) {
+ this._onEvent = callback;
+ this._type = type || 0;
+ this._listenerID = listenerID || "";
+ },
+
+ /**
+ *
+ * Sets paused state for the listener
+ * The paused state is only used for scene graph priority listeners.
+ * `EventDispatcher::resumeAllEventListenersForTarget(node)` will set the paused state to `true`,
+ * while `EventDispatcher::pauseAllEventListenersForTarget(node)` will set it to `false`.
+ * @note 1) Fixed priority listeners will never get paused. If a fixed priority doesn't want to receive events,
+ * call `setEnabled(false)` instead.
+ * 2) In `Node`'s onEnter and onExit, the `paused state` of the listeners which associated with that node will be automatically updated.
+ *
+ * @param {boolean} paused
+ * @private
+ */
+ _setPaused: function (paused) {
+ this._paused = paused;
+ },
+
+ /**
+ * Checks whether the listener is paused
+ * @returns {boolean}
+ * @private
+ */
+ _isPaused: function () {
+ return this._paused;
+ },
+
+ /**
+ * Marks the listener was registered by EventDispatcher
+ * @param {boolean} registered
+ * @private
+ */
+ _setRegistered: function (registered) {
+ this._registered = registered;
+ },
+
+ /**
+ * Checks whether the listener was registered by EventDispatcher
+ * @returns {boolean}
+ * @private
+ */
+ _isRegistered: function () {
+ return this._registered;
+ },
+
+ /**
+ * Gets the type of this listener
+ * @note It's different from `EventType`, e.g. TouchEvent has two kinds of event listeners - EventListenerOneByOne, EventListenerAllAtOnce
+ * @returns {number}
+ * @private
+ */
+ _getType: function () {
+ return this._type;
+ },
+
+ /**
+ * Gets the listener ID of this listener
+ * When event is being dispatched, listener ID is used as key for searching listeners according to event type.
+ * @returns {string}
+ * @private
+ */
+ _getListenerID: function () {
+ return this._listenerID;
+ },
+
+ /**
+ * Sets the fixed priority for this listener
+ * @note This method is only used for `fixed priority listeners`, it needs to access a non-zero value. 0 is reserved for scene graph priority listeners
+ * @param {number} fixedPriority
+ * @private
+ */
+ _setFixedPriority: function (fixedPriority) {
+ this._fixedPriority = fixedPriority;
+ },
+
+ /**
+ * Gets the fixed priority of this listener
+ * @returns {number} 0 if it's a scene graph priority listener, non-zero for fixed priority listener
+ * @private
+ */
+ _getFixedPriority: function () {
+ return this._fixedPriority;
+ },
+
+ /**
+ * Sets scene graph priority for this listener
+ * @param {cc.Node} node
+ * @private
+ */
+ _setSceneGraphPriority: function (node) {
+ this._node = node;
+ },
+
+ /**
+ * Gets scene graph priority of this listener
+ * @returns {cc.Node} if it's a fixed priority listener, non-null for scene graph priority listener
+ * @private
+ */
+ _getSceneGraphPriority: function () {
+ return this._node;
+ },
+
+ /**
+ * Checks whether the listener is available.
+ * @returns {boolean}
+ */
+ checkAvailable: function () {
+ return this._onEvent !== null;
+ },
+
+ /**
+ * Clones the listener, its subclasses have to override this method.
+ * @returns {cc.EventListener}
+ */
+ clone: function () {
+ return null;
+ },
+
+ /**
+ * Enables or disables the listener
+ * @note Only listeners with `enabled` state will be able to receive events.
+ * When an listener was initialized, it's enabled by default.
+ * An event listener can receive events when it is enabled and is not paused.
+ * paused state is always false when it is a fixed priority listener.
+ * @param {boolean} enabled
+ */
+ setEnabled: function(enabled){
+ this._isEnabled = enabled;
+ },
+
+ /**
+ * Checks whether the listener is enabled
+ * @returns {boolean}
+ */
+ isEnabled: function(){
+ return this._isEnabled;
+ },
+
+ /**
+ * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
+ * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
+ * This is a hack, and should be removed once JSB fixes the retain/release bug
+ * You will need to retain an object if you created a listener and haven't added it any target node during the same frame.
+ * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,
+ * when you want to use it later, a "Invalid Native Object" error will be raised.
+ * The retain function can increase a reference count for the native object to avoid it being released,
+ * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.
+ * retain and release function call should be paired in developer's game code.
+ * @function
+ * @see cc.EventListener#release
+ */
+ retain:function () {
+ },
+ /**
+ * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
+ * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
+ * This is a hack, and should be removed once JSB fixes the retain/release bug
+ * You will need to retain an object if you created a listener and haven't added it any target node during the same frame.
+ * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,
+ * when you want to use it later, a "Invalid Native Object" error will be raised.
+ * The retain function can increase a reference count for the native object to avoid it being released,
+ * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.
+ * retain and release function call should be paired in developer's game code.
+ * @function
+ * @see cc.EventListener#retain
+ */
+ release:function () {
+ }
+});
+
+// event listener type
+/**
+ * The type code of unknown event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.UNKNOWN = 0;
+/**
+ * The type code of one by one touch event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.TOUCH_ONE_BY_ONE = 1;
+/**
+ * The type code of all at once touch event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.TOUCH_ALL_AT_ONCE = 2;
+/**
+ * The type code of keyboard event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.KEYBOARD = 3;
+/**
+ * The type code of mouse event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.MOUSE = 4;
+/**
+ * The type code of acceleration event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.ACCELERATION = 6;
+/**
+ * The type code of Focus change event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.FOCUS = 7;
+/**
+ * The type code of custom event listener.
+ * @constant
+ * @type {number}
+ */
+cc.EventListener.CUSTOM = 8;
+
+cc._EventListenerCustom = cc.EventListener.extend({
+ _onCustomEvent: null,
+ ctor: function (listenerId, callback, target) {
+ this._onCustomEvent = callback;
+ this._target = target;
+
+ cc.EventListener.prototype.ctor.call(this, cc.EventListener.CUSTOM, listenerId, this._callback);
+ },
+
+ _callback: function (event) {
+ if (this._onCustomEvent !== null)
+ this._onCustomEvent.call(this._target, event);
+ },
+
+ checkAvailable: function () {
+ return (cc.EventListener.prototype.checkAvailable.call(this) && this._onCustomEvent !== null);
+ },
+
+ clone: function () {
+ return new cc._EventListenerCustom(this._listenerID, this._onCustomEvent);
+ }
+});
+
+cc._EventListenerCustom.create = function (eventName, callback) {
+ return new cc._EventListenerCustom(eventName, callback);
+};
+
+cc._EventListenerMouse = cc.EventListener.extend({
+ onMouseDown: null,
+ onMouseUp: null,
+ onMouseMove: null,
+ onMouseScroll: null,
+
+ ctor: function () {
+ cc.EventListener.prototype.ctor.call(this, cc.EventListener.MOUSE, cc._EventListenerMouse.LISTENER_ID, this._callback);
+ },
+
+ _callback: function (event) {
+ var eventType = cc.EventMouse;
+ switch (event._eventType) {
+ case eventType.DOWN:
+ if (this.onMouseDown)
+ this.onMouseDown(event);
+ break;
+ case eventType.UP:
+ if (this.onMouseUp)
+ this.onMouseUp(event);
+ break;
+ case eventType.MOVE:
+ if (this.onMouseMove)
+ this.onMouseMove(event);
+ break;
+ case eventType.SCROLL:
+ if (this.onMouseScroll)
+ this.onMouseScroll(event);
+ break;
+ default:
+ break;
+ }
+ },
+
+ clone: function () {
+ var eventListener = new cc._EventListenerMouse();
+ eventListener.onMouseDown = this.onMouseDown;
+ eventListener.onMouseUp = this.onMouseUp;
+ eventListener.onMouseMove = this.onMouseMove;
+ eventListener.onMouseScroll = this.onMouseScroll;
+ return eventListener;
+ },
+
+ checkAvailable: function () {
+ return true;
+ }
+});
+
+cc._EventListenerMouse.LISTENER_ID = "__cc_mouse";
+
+cc._EventListenerMouse.create = function () {
+ return new cc._EventListenerMouse();
+};
+
+cc._EventListenerTouchOneByOne = cc.EventListener.extend({
+ _claimedTouches: null,
+ swallowTouches: false,
+ onTouchBegan: null,
+ onTouchMoved: null,
+ onTouchEnded: null,
+ onTouchCancelled: null,
+
+ ctor: function () {
+ cc.EventListener.prototype.ctor.call(this, cc.EventListener.TOUCH_ONE_BY_ONE, cc._EventListenerTouchOneByOne.LISTENER_ID, null);
+ this._claimedTouches = [];
+ },
+
+ setSwallowTouches: function (needSwallow) {
+ this.swallowTouches = needSwallow;
+ },
+
+ isSwallowTouches: function(){
+ return this.swallowTouches;
+ },
+
+ clone: function () {
+ var eventListener = new cc._EventListenerTouchOneByOne();
+ eventListener.onTouchBegan = this.onTouchBegan;
+ eventListener.onTouchMoved = this.onTouchMoved;
+ eventListener.onTouchEnded = this.onTouchEnded;
+ eventListener.onTouchCancelled = this.onTouchCancelled;
+ eventListener.swallowTouches = this.swallowTouches;
+ return eventListener;
+ },
+
+ checkAvailable: function () {
+ if(!this.onTouchBegan){
+ cc.log(cc._LogInfos._EventListenerTouchOneByOne_checkAvailable);
+ return false;
+ }
+ return true;
+ }
+});
+
+cc._EventListenerTouchOneByOne.LISTENER_ID = "__cc_touch_one_by_one";
+
+cc._EventListenerTouchOneByOne.create = function () {
+ return new cc._EventListenerTouchOneByOne();
+};
+
+cc._EventListenerTouchAllAtOnce = cc.EventListener.extend({
+ onTouchesBegan: null,
+ onTouchesMoved: null,
+ onTouchesEnded: null,
+ onTouchesCancelled: null,
+
+ ctor: function(){
+ cc.EventListener.prototype.ctor.call(this, cc.EventListener.TOUCH_ALL_AT_ONCE, cc._EventListenerTouchAllAtOnce.LISTENER_ID, null);
+ },
+
+ clone: function(){
+ var eventListener = new cc._EventListenerTouchAllAtOnce();
+ eventListener.onTouchesBegan = this.onTouchesBegan;
+ eventListener.onTouchesMoved = this.onTouchesMoved;
+ eventListener.onTouchesEnded = this.onTouchesEnded;
+ eventListener.onTouchesCancelled = this.onTouchesCancelled;
+ return eventListener;
+ },
+
+ checkAvailable: function(){
+ if (this.onTouchesBegan === null && this.onTouchesMoved === null
+ && this.onTouchesEnded === null && this.onTouchesCancelled === null) {
+ cc.log(cc._LogInfos._EventListenerTouchAllAtOnce_checkAvailable);
+ return false;
+ }
+ return true;
+ }
+});
+
+cc._EventListenerTouchAllAtOnce.LISTENER_ID = "__cc_touch_all_at_once";
+
+cc._EventListenerTouchAllAtOnce.create = function(){
+ return new cc._EventListenerTouchAllAtOnce();
+};
+
+/**
+ * Create a EventListener object by json object
+ * @function
+ * @static
+ * @param {object} argObj a json object
+ * @returns {cc.EventListener}
+ * todo: It should be the direct use new
+ * @example
+ * cc.EventListener.create({
+ * event: cc.EventListener.TOUCH_ONE_BY_ONE,
+ * swallowTouches: true,
+ * onTouchBegan: function (touch, event) {
+ * //do something
+ * return true;
+ * }
+ * });
+ */
+cc.EventListener.create = function(argObj){
+
+ cc.assert(argObj&&argObj.event, cc._LogInfos.EventListener_create);
+
+ var listenerType = argObj.event;
+ delete argObj.event;
+
+ var listener = null;
+ if(listenerType === cc.EventListener.TOUCH_ONE_BY_ONE)
+ listener = new cc._EventListenerTouchOneByOne();
+ else if(listenerType === cc.EventListener.TOUCH_ALL_AT_ONCE)
+ listener = new cc._EventListenerTouchAllAtOnce();
+ else if(listenerType === cc.EventListener.MOUSE)
+ listener = new cc._EventListenerMouse();
+ else if(listenerType === cc.EventListener.CUSTOM){
+ listener = new cc._EventListenerCustom(argObj.eventName, argObj.callback);
+ delete argObj.eventName;
+ delete argObj.callback;
+ } else if(listenerType === cc.EventListener.KEYBOARD)
+ listener = new cc._EventListenerKeyboard();
+ else if(listenerType === cc.EventListener.ACCELERATION){
+ listener = new cc._EventListenerAcceleration(argObj.callback);
+ delete argObj.callback;
+ } else if(listenerType === cc.EventListener.FOCUS)
+ listener = new cc._EventListenerFocus();
+
+ for(var key in argObj) {
+ listener[key] = argObj[key];
+ }
+
+ return listener;
+};
+
+cc._EventListenerFocus = cc.EventListener.extend({
+ clone: function(){
+ var listener = new cc._EventListenerFocus();
+ listener.onFocusChanged = this.onFocusChanged;
+ return listener;
+ },
+ checkAvailable: function(){
+ if(!this.onFocusChanged){
+ cc.log("Invalid EventListenerFocus!");
+ return false;
+ }
+ return true;
+ },
+ onFocusChanged: null,
+ ctor: function(){
+ cc.EventListener.prototype.ctor.call(this, cc.EventListener.FOCUS, cc._EventListenerFocus.LISTENER_ID, this._callback);
+ },
+ _callback: function (event) {
+ if (this.onFocusChanged) {
+ this.onFocusChanged(event._widgetLoseFocus, event._widgetGetFocus);
+ }
+ }
+});
+
+cc._EventListenerFocus.LISTENER_ID = "__cc_focus_event";
\ No newline at end of file
diff --git a/cocos2d/core/event-manager/CCEventManager.js b/cocos2d/core/event-manager/CCEventManager.js
new file mode 100644
index 0000000000..7f54f03939
--- /dev/null
+++ b/cocos2d/core/event-manager/CCEventManager.js
@@ -0,0 +1,1016 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2015 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+
+/**
+ * @ignore
+ */
+cc._EventListenerVector = cc.Class.extend({
+ _fixedListeners: null,
+ _sceneGraphListeners: null,
+ gt0Index: 0,
+
+ ctor: function () {
+ this._fixedListeners = [];
+ this._sceneGraphListeners = [];
+ },
+
+ size: function () {
+ return this._fixedListeners.length + this._sceneGraphListeners.length;
+ },
+
+ empty: function () {
+ return (this._fixedListeners.length === 0) && (this._sceneGraphListeners.length === 0);
+ },
+
+ push: function (listener) {
+ if (listener._getFixedPriority() === 0)
+ this._sceneGraphListeners.push(listener);
+ else
+ this._fixedListeners.push(listener);
+ },
+
+ clearSceneGraphListeners: function () {
+ this._sceneGraphListeners.length = 0;
+ },
+
+ clearFixedListeners: function () {
+ this._fixedListeners.length = 0;
+ },
+
+ clear: function () {
+ this._sceneGraphListeners.length = 0;
+ this._fixedListeners.length = 0;
+ },
+
+ getFixedPriorityListeners: function () {
+ return this._fixedListeners;
+ },
+
+ getSceneGraphPriorityListeners: function () {
+ return this._sceneGraphListeners;
+ }
+});
+
+function __getListenerID (event) {
+ var eventType = cc.Event, getType = event._type;
+ if (getType === eventType.ACCELERATION)
+ return cc._EventListenerAcceleration.LISTENER_ID;
+ if (getType === eventType.CUSTOM)
+ return event._eventName;
+ if (getType === eventType.KEYBOARD)
+ return cc._EventListenerKeyboard.LISTENER_ID;
+ if (getType === eventType.MOUSE)
+ return cc._EventListenerMouse.LISTENER_ID;
+ if (getType === eventType.FOCUS)
+ return cc._EventListenerFocus.LISTENER_ID;
+ if (getType === eventType.TOUCH) {
+ // Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce.
+ // return UNKNOWN instead.
+ cc.log(cc._LogInfos.__getListenerID);
+ }
+ return "";
+}
+
+/**
+ *
+ * cc.eventManager is a singleton object which manages event listener subscriptions and event dispatching.
+ *
+ * The EventListener list is managed in such way so that event listeners can be added and removed
+ * while events are being dispatched.
+ *
+ * @class
+ * @name cc.eventManager
+ */
+cc.eventManager = /** @lends cc.eventManager# */{
+ //Priority dirty flag
+ DIRTY_NONE: 0,
+ DIRTY_FIXED_PRIORITY: 1 << 0,
+ DIRTY_SCENE_GRAPH_PRIORITY: 1 << 1,
+ DIRTY_ALL: 3,
+
+ _listenersMap: {},
+ _priorityDirtyFlagMap: {},
+ _nodeListenersMap: {},
+ _nodePriorityMap: {},
+ _globalZOrderNodeMap: {},
+ _toAddedListeners: [],
+ _toRemovedListeners: [],
+ _dirtyNodes: [],
+ _inDispatch: 0,
+ _isEnabled: false,
+ _nodePriorityIndex: 0,
+
+ _internalCustomListenerIDs: [cc.game.EVENT_HIDE, cc.game.EVENT_SHOW],
+
+ _setDirtyForNode: function (node) {
+ // Mark the node dirty only when there is an event listener associated with it.
+ if (this._nodeListenersMap[node.__instanceId] != null)
+ this._dirtyNodes.push(node);
+ var _children = node.getChildren();
+ for(var i = 0, len = _children.length; i < len; i++)
+ this._setDirtyForNode(_children[i]);
+ },
+
+ /**
+ * Pauses all listeners which are associated the specified target.
+ * @param {cc.Node} node
+ * @param {Boolean} [recursive=false]
+ */
+ pauseTarget: function (node, recursive) {
+ var listeners = this._nodeListenersMap[node.__instanceId], i, len;
+ if (listeners) {
+ for (i = 0, len = listeners.length; i < len; i++)
+ listeners[i]._setPaused(true);
+ }
+ if (recursive === true) {
+ var locChildren = node.getChildren();
+ for (i = 0, len = locChildren.length; i < len; i++)
+ this.pauseTarget(locChildren[i], true);
+ }
+ },
+
+ /**
+ * Resumes all listeners which are associated the specified target.
+ * @param {cc.Node} node
+ * @param {Boolean} [recursive=false]
+ */
+ resumeTarget: function (node, recursive) {
+ var listeners = this._nodeListenersMap[node.__instanceId], i, len;
+ if (listeners) {
+ for (i = 0, len = listeners.length; i < len; i++)
+ listeners[i]._setPaused(false);
+ }
+ this._setDirtyForNode(node);
+ if (recursive === true) {
+ var locChildren = node.getChildren();
+ for (i = 0, len = locChildren.length; i< len; i++)
+ this.resumeTarget(locChildren[i], true);
+ }
+ },
+
+ _addListener: function (listener) {
+ if (this._inDispatch === 0)
+ this._forceAddEventListener(listener);
+ else
+ this._toAddedListeners.push(listener);
+ },
+
+ _forceAddEventListener: function (listener) {
+ var listenerID = listener._getListenerID();
+ var listeners = this._listenersMap[listenerID];
+ if (!listeners) {
+ listeners = new cc._EventListenerVector();
+ this._listenersMap[listenerID] = listeners;
+ }
+ listeners.push(listener);
+
+ if (listener._getFixedPriority() === 0) {
+ this._setDirty(listenerID, this.DIRTY_SCENE_GRAPH_PRIORITY);
+
+ var node = listener._getSceneGraphPriority();
+ if (node === null)
+ cc.log(cc._LogInfos.eventManager__forceAddEventListener);
+
+ this._associateNodeAndEventListener(node, listener);
+ if (node.isRunning())
+ this.resumeTarget(node);
+ } else
+ this._setDirty(listenerID, this.DIRTY_FIXED_PRIORITY);
+ },
+
+ _getListeners: function (listenerID) {
+ return this._listenersMap[listenerID];
+ },
+
+ _updateDirtyFlagForSceneGraph: function () {
+ if (this._dirtyNodes.length === 0)
+ return;
+
+ var locDirtyNodes = this._dirtyNodes, selListeners, selListener, locNodeListenersMap = this._nodeListenersMap;
+ for (var i = 0, len = locDirtyNodes.length; i < len; i++) {
+ selListeners = locNodeListenersMap[locDirtyNodes[i].__instanceId];
+ if (selListeners) {
+ for (var j = 0, listenersLen = selListeners.length; j < listenersLen; j++) {
+ selListener = selListeners[j];
+ if (selListener)
+ this._setDirty(selListener._getListenerID(), this.DIRTY_SCENE_GRAPH_PRIORITY);
+ }
+ }
+ }
+ this._dirtyNodes.length = 0;
+ },
+
+ _removeAllListenersInVector: function (listenerVector) {
+ if (!listenerVector)
+ return;
+ var selListener;
+ for (var i = 0; i < listenerVector.length;) {
+ selListener = listenerVector[i];
+ selListener._setRegistered(false);
+ if (selListener._getSceneGraphPriority() != null) {
+ this._dissociateNodeAndEventListener(selListener._getSceneGraphPriority(), selListener);
+ selListener._setSceneGraphPriority(null); // NULL out the node pointer so we don't have any dangling pointers to destroyed nodes.
+ }
+
+ if (this._inDispatch === 0)
+ cc.arrayRemoveObject(listenerVector, selListener);
+ else
+ ++i;
+ }
+ },
+
+ _removeListenersForListenerID: function (listenerID) {
+ var listeners = this._listenersMap[listenerID], i;
+ if (listeners) {
+ var fixedPriorityListeners = listeners.getFixedPriorityListeners();
+ var sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
+
+ this._removeAllListenersInVector(sceneGraphPriorityListeners);
+ this._removeAllListenersInVector(fixedPriorityListeners);
+
+ // Remove the dirty flag according the 'listenerID'.
+ // No need to check whether the dispatcher is dispatching event.
+ delete this._priorityDirtyFlagMap[listenerID];
+
+ if (!this._inDispatch) {
+ listeners.clear();
+ }
+ delete this._listenersMap[listenerID];
+ }
+
+ var locToAddedListeners = this._toAddedListeners, listener;
+ for (i = 0; i < locToAddedListeners.length;) {
+ listener = locToAddedListeners[i];
+ if (listener && listener._getListenerID() === listenerID)
+ cc.arrayRemoveObject(locToAddedListeners, listener);
+ else
+ ++i;
+ }
+ },
+
+ _sortEventListeners: function (listenerID) {
+ var dirtyFlag = this.DIRTY_NONE, locFlagMap = this._priorityDirtyFlagMap;
+ if (locFlagMap[listenerID])
+ dirtyFlag = locFlagMap[listenerID];
+
+ if (dirtyFlag !== this.DIRTY_NONE) {
+ // Clear the dirty flag first, if `rootNode` is null, then set its dirty flag of scene graph priority
+ locFlagMap[listenerID] = this.DIRTY_NONE;
+
+ if (dirtyFlag & this.DIRTY_FIXED_PRIORITY)
+ this._sortListenersOfFixedPriority(listenerID);
+
+ if (dirtyFlag & this.DIRTY_SCENE_GRAPH_PRIORITY) {
+ var rootNode = cc.director.getRunningScene();
+ if (rootNode)
+ this._sortListenersOfSceneGraphPriority(listenerID, rootNode);
+ else
+ locFlagMap[listenerID] = this.DIRTY_SCENE_GRAPH_PRIORITY;
+ }
+ }
+ },
+
+ _sortListenersOfSceneGraphPriority: function (listenerID, rootNode) {
+ var listeners = this._getListeners(listenerID);
+ if (!listeners)
+ return;
+
+ var sceneGraphListener = listeners.getSceneGraphPriorityListeners();
+ if (!sceneGraphListener || sceneGraphListener.length === 0)
+ return;
+
+ // Reset priority index
+ this._nodePriorityIndex = 0;
+ this._nodePriorityMap = {};
+
+ this._visitTarget(rootNode, true);
+
+ // After sort: priority < 0, > 0
+ listeners.getSceneGraphPriorityListeners().sort(this._sortEventListenersOfSceneGraphPriorityDes);
+ },
+
+ _sortEventListenersOfSceneGraphPriorityDes: function (l1, l2) {
+ var locNodePriorityMap = cc.eventManager._nodePriorityMap, node1 = l1._getSceneGraphPriority(),
+ node2 = l2._getSceneGraphPriority();
+ if (!l2 || !node2 || !locNodePriorityMap[node2.__instanceId])
+ return -1;
+ else if (!l1 || !node1 || !locNodePriorityMap[node1.__instanceId])
+ return 1;
+ return locNodePriorityMap[l2._getSceneGraphPriority().__instanceId] - locNodePriorityMap[l1._getSceneGraphPriority().__instanceId];
+ },
+
+ _sortListenersOfFixedPriority: function (listenerID) {
+ var listeners = this._listenersMap[listenerID];
+ if (!listeners)
+ return;
+
+ var fixedListeners = listeners.getFixedPriorityListeners();
+ if (!fixedListeners || fixedListeners.length === 0)
+ return;
+ // After sort: priority < 0, > 0
+ fixedListeners.sort(this._sortListenersOfFixedPriorityAsc);
+
+ // FIXME: Should use binary search
+ var index = 0;
+ for (var len = fixedListeners.length; index < len;) {
+ if (fixedListeners[index]._getFixedPriority() >= 0)
+ break;
+ ++index;
+ }
+ listeners.gt0Index = index;
+ },
+
+ _sortListenersOfFixedPriorityAsc: function (l1, l2) {
+ return l1._getFixedPriority() - l2._getFixedPriority();
+ },
+
+ _onUpdateListeners: function (listeners) {
+ var fixedPriorityListeners = listeners.getFixedPriorityListeners();
+ var sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
+ var i, selListener, idx, toRemovedListeners = this._toRemovedListeners;
+
+ if (sceneGraphPriorityListeners) {
+ for (i = 0; i < sceneGraphPriorityListeners.length;) {
+ selListener = sceneGraphPriorityListeners[i];
+ if (!selListener._isRegistered()) {
+ cc.arrayRemoveObject(sceneGraphPriorityListeners, selListener);
+ // if item in toRemove list, remove it from the list
+ idx = toRemovedListeners.indexOf(selListener);
+ if(idx !== -1)
+ toRemovedListeners.splice(idx, 1);
+ } else
+ ++i;
+ }
+ }
+
+ if (fixedPriorityListeners) {
+ for (i = 0; i < fixedPriorityListeners.length;) {
+ selListener = fixedPriorityListeners[i];
+ if (!selListener._isRegistered()) {
+ cc.arrayRemoveObject(fixedPriorityListeners, selListener);
+ // if item in toRemove list, remove it from the list
+ idx = toRemovedListeners.indexOf(selListener);
+ if(idx !== -1)
+ toRemovedListeners.splice(idx, 1);
+ } else
+ ++i;
+ }
+ }
+
+ if (sceneGraphPriorityListeners && sceneGraphPriorityListeners.length === 0)
+ listeners.clearSceneGraphListeners();
+
+ if (fixedPriorityListeners && fixedPriorityListeners.length === 0)
+ listeners.clearFixedListeners();
+ },
+
+ frameUpdateListeners: function () {
+ var locListenersMap = this._listenersMap, locPriorityDirtyFlagMap = this._priorityDirtyFlagMap;
+ for (var selKey in locListenersMap) {
+ if (locListenersMap[selKey].empty()) {
+ delete locPriorityDirtyFlagMap[selKey];
+ delete locListenersMap[selKey];
+ }
+ }
+
+ var locToAddedListeners = this._toAddedListeners;
+ if (locToAddedListeners.length !== 0) {
+ for (var i = 0, len = locToAddedListeners.length; i < len; i++)
+ this._forceAddEventListener(locToAddedListeners[i]);
+ locToAddedListeners.length = 0;
+ }
+ if (this._toRemovedListeners.length !== 0) {
+ this._cleanToRemovedListeners();
+ }
+ },
+
+ _updateTouchListeners: function (event) {
+ var locInDispatch = this._inDispatch;
+ cc.assert(locInDispatch > 0, cc._LogInfos.EventManager__updateListeners);
+
+ if (locInDispatch > 1)
+ return;
+
+ var listeners;
+ listeners = this._listenersMap[cc._EventListenerTouchOneByOne.LISTENER_ID];
+ if (listeners) {
+ this._onUpdateListeners(listeners);
+ }
+ listeners = this._listenersMap[cc._EventListenerTouchAllAtOnce.LISTENER_ID];
+ if (listeners) {
+ this._onUpdateListeners(listeners);
+ }
+
+ cc.assert(locInDispatch === 1, cc._LogInfos.EventManager__updateListeners_2);
+
+ var locToAddedListeners = this._toAddedListeners;
+ if (locToAddedListeners.length !== 0) {
+ for (var i = 0, len = locToAddedListeners.length; i < len; i++)
+ this._forceAddEventListener(locToAddedListeners[i]);
+ locToAddedListeners.length = 0;
+ }
+ if (this._toRemovedListeners.length !== 0) {
+ this._cleanToRemovedListeners();
+ }
+ },
+
+ //Remove all listeners in _toRemoveListeners list and cleanup
+ _cleanToRemovedListeners: function () {
+ var toRemovedListeners = this._toRemovedListeners;
+ for (var i = 0; i < toRemovedListeners.length; i++) {
+ var selListener = toRemovedListeners[i];
+ var listeners = this._listenersMap[selListener._getListenerID()];
+ if (!listeners)
+ continue;
+
+ var idx, fixedPriorityListeners = listeners.getFixedPriorityListeners(),
+ sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
+
+ if (sceneGraphPriorityListeners) {
+ idx = sceneGraphPriorityListeners.indexOf(selListener);
+ if (idx !== -1) {
+ sceneGraphPriorityListeners.splice(idx, 1);
+ }
+ }
+ if (fixedPriorityListeners) {
+ idx = fixedPriorityListeners.indexOf(selListener);
+ if (idx !== -1) {
+ fixedPriorityListeners.splice(idx, 1);
+ }
+ }
+ }
+ toRemovedListeners.length = 0;
+ },
+
+ _onTouchEventCallback: function (listener, argsObj) {
+ // Skip if the listener was removed.
+ if (!listener._isRegistered)
+ return false;
+
+ var event = argsObj.event, selTouch = argsObj.selTouch;
+ event._setCurrentTarget(listener._node);
+
+ var isClaimed = false, removedIdx;
+ var getCode = event.getEventCode(), eventCode = cc.EventTouch.EventCode;
+ if (getCode === eventCode.BEGAN) {
+ if (listener.onTouchBegan) {
+ isClaimed = listener.onTouchBegan(selTouch, event);
+ if (isClaimed && listener._registered)
+ listener._claimedTouches.push(selTouch);
+ }
+ } else if (listener._claimedTouches.length > 0
+ && ((removedIdx = listener._claimedTouches.indexOf(selTouch)) !== -1)) {
+ isClaimed = true;
+ if (getCode === eventCode.MOVED && listener.onTouchMoved) {
+ listener.onTouchMoved(selTouch, event);
+ } else if (getCode === eventCode.ENDED) {
+ if (listener.onTouchEnded)
+ listener.onTouchEnded(selTouch, event);
+ if (listener._registered)
+ listener._claimedTouches.splice(removedIdx, 1);
+ } else if (getCode === eventCode.CANCELLED) {
+ if (listener.onTouchCancelled)
+ listener.onTouchCancelled(selTouch, event);
+ if (listener._registered)
+ listener._claimedTouches.splice(removedIdx, 1);
+ }
+ }
+
+ // If the event was stopped, return directly.
+ if (event.isStopped()) {
+ cc.eventManager._updateTouchListeners(event);
+ return true;
+ }
+
+ if (isClaimed && listener._registered && listener.swallowTouches) {
+ if (argsObj.needsMutableSet)
+ argsObj.touches.splice(selTouch, 1);
+ return true;
+ }
+ return false;
+ },
+
+ _dispatchTouchEvent: function (event) {
+ this._sortEventListeners(cc._EventListenerTouchOneByOne.LISTENER_ID);
+ this._sortEventListeners(cc._EventListenerTouchAllAtOnce.LISTENER_ID);
+
+ var oneByOneListeners = this._getListeners(cc._EventListenerTouchOneByOne.LISTENER_ID);
+ var allAtOnceListeners = this._getListeners(cc._EventListenerTouchAllAtOnce.LISTENER_ID);
+
+ // If there aren't any touch listeners, return directly.
+ if (null === oneByOneListeners && null === allAtOnceListeners)
+ return;
+
+ var originalTouches = event.getTouches(), mutableTouches = cc.copyArray(originalTouches);
+ var oneByOneArgsObj = {event: event, needsMutableSet: (oneByOneListeners && allAtOnceListeners), touches: mutableTouches, selTouch: null};
+
+ //
+ // process the target handlers 1st
+ //
+ if (oneByOneListeners) {
+ for (var i = 0; i < originalTouches.length; i++) {
+ oneByOneArgsObj.selTouch = originalTouches[i];
+ this._dispatchEventToListeners(oneByOneListeners, this._onTouchEventCallback, oneByOneArgsObj);
+ if (event.isStopped())
+ return;
+ }
+ }
+
+ //
+ // process standard handlers 2nd
+ //
+ if (allAtOnceListeners && mutableTouches.length > 0) {
+ this._dispatchEventToListeners(allAtOnceListeners, this._onTouchesEventCallback, {event: event, touches: mutableTouches});
+ if (event.isStopped())
+ return;
+ }
+ this._updateTouchListeners(event);
+ },
+
+ _onTouchesEventCallback: function (listener, callbackParams) {
+ // Skip if the listener was removed.
+ if (!listener._registered)
+ return false;
+
+ var eventCode = cc.EventTouch.EventCode, event = callbackParams.event, touches = callbackParams.touches, getCode = event.getEventCode();
+ event._setCurrentTarget(listener._node);
+ if (getCode === eventCode.BEGAN && listener.onTouchesBegan)
+ listener.onTouchesBegan(touches, event);
+ else if (getCode === eventCode.MOVED && listener.onTouchesMoved)
+ listener.onTouchesMoved(touches, event);
+ else if (getCode === eventCode.ENDED && listener.onTouchesEnded)
+ listener.onTouchesEnded(touches, event);
+ else if (getCode === eventCode.CANCELLED && listener.onTouchesCancelled)
+ listener.onTouchesCancelled(touches, event);
+
+ // If the event was stopped, return directly.
+ if (event.isStopped()) {
+ cc.eventManager._updateTouchListeners(event);
+ return true;
+ }
+ return false;
+ },
+
+ _associateNodeAndEventListener: function (node, listener) {
+ var listeners = this._nodeListenersMap[node.__instanceId];
+ if (!listeners) {
+ listeners = [];
+ this._nodeListenersMap[node.__instanceId] = listeners;
+ }
+ listeners.push(listener);
+ },
+
+ _dissociateNodeAndEventListener: function (node, listener) {
+ var listeners = this._nodeListenersMap[node.__instanceId];
+ if (listeners) {
+ cc.arrayRemoveObject(listeners, listener);
+ if (listeners.length === 0)
+ delete this._nodeListenersMap[node.__instanceId];
+ }
+ },
+
+ _dispatchEventToListeners: function (listeners, onEvent, eventOrArgs) {
+ var shouldStopPropagation = false;
+ var fixedPriorityListeners = listeners.getFixedPriorityListeners();
+ var sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
+
+ var i = 0, j, selListener;
+ if (fixedPriorityListeners) { // priority < 0
+ if (fixedPriorityListeners.length !== 0) {
+ for (; i < listeners.gt0Index; ++i) {
+ selListener = fixedPriorityListeners[i];
+ if (selListener.isEnabled() && !selListener._isPaused() && selListener._isRegistered() && onEvent(selListener, eventOrArgs)) {
+ shouldStopPropagation = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (sceneGraphPriorityListeners && !shouldStopPropagation) { // priority == 0, scene graph priority
+ for (j = 0; j < sceneGraphPriorityListeners.length; j++) {
+ selListener = sceneGraphPriorityListeners[j];
+ if (selListener.isEnabled() && !selListener._isPaused() && selListener._isRegistered() && onEvent(selListener, eventOrArgs)) {
+ shouldStopPropagation = true;
+ break;
+ }
+ }
+ }
+
+ if (fixedPriorityListeners && !shouldStopPropagation) { // priority > 0
+ for (; i < fixedPriorityListeners.length; ++i) {
+ selListener = fixedPriorityListeners[i];
+ if (selListener.isEnabled() && !selListener._isPaused() && selListener._isRegistered() && onEvent(selListener, eventOrArgs)) {
+ shouldStopPropagation = true;
+ break;
+ }
+ }
+ }
+ },
+
+ _setDirty: function (listenerID, flag) {
+ var locDirtyFlagMap = this._priorityDirtyFlagMap;
+ if (locDirtyFlagMap[listenerID] == null)
+ locDirtyFlagMap[listenerID] = flag;
+ else
+ locDirtyFlagMap[listenerID] = flag | locDirtyFlagMap[listenerID];
+ },
+
+ _visitTarget: function (node, isRootNode) {
+ var children = node.getChildren(), i = 0;
+ var childrenCount = children.length, locGlobalZOrderNodeMap = this._globalZOrderNodeMap, locNodeListenersMap = this._nodeListenersMap;
+
+ if (childrenCount > 0) {
+ var child;
+ // visit children zOrder < 0
+ for (; i < childrenCount; i++) {
+ child = children[i];
+ if (child && child.getLocalZOrder() < 0)
+ this._visitTarget(child, false);
+ else
+ break;
+ }
+
+ if (locNodeListenersMap[node.__instanceId] != null) {
+ if (!locGlobalZOrderNodeMap[node.getGlobalZOrder()])
+ locGlobalZOrderNodeMap[node.getGlobalZOrder()] = [];
+ locGlobalZOrderNodeMap[node.getGlobalZOrder()].push(node.__instanceId);
+ }
+
+ for (; i < childrenCount; i++) {
+ child = children[i];
+ if (child)
+ this._visitTarget(child, false);
+ }
+ } else {
+ if (locNodeListenersMap[node.__instanceId] != null) {
+ if (!locGlobalZOrderNodeMap[node.getGlobalZOrder()])
+ locGlobalZOrderNodeMap[node.getGlobalZOrder()] = [];
+ locGlobalZOrderNodeMap[node.getGlobalZOrder()].push(node.__instanceId);
+ }
+ }
+
+ if (isRootNode) {
+ var globalZOrders = [];
+ for (var selKey in locGlobalZOrderNodeMap)
+ globalZOrders.push(selKey);
+
+ globalZOrders.sort(this._sortNumberAsc);
+
+ var zOrdersLen = globalZOrders.length, selZOrders, j, locNodePriorityMap = this._nodePriorityMap;
+ for (i = 0; i < zOrdersLen; i++) {
+ selZOrders = locGlobalZOrderNodeMap[globalZOrders[i]];
+ for (j = 0; j < selZOrders.length; j++)
+ locNodePriorityMap[selZOrders[j]] = ++this._nodePriorityIndex;
+ }
+ this._globalZOrderNodeMap = {};
+ }
+ },
+
+ _sortNumberAsc: function (a, b) {
+ return a - b;
+ },
+
+ /**
+ *
+ * Adds a event listener for a specified event.
+ * if the parameter "nodeOrPriority" is a node, it means to add a event listener for a specified event with the priority of scene graph.
+ * if the parameter "nodeOrPriority" is a Number, it means to add a event listener for a specified event with the fixed priority.
+ *
+ * @param {cc.EventListener|Object} listener The listener of a specified event or a object of some event parameters.
+ * @param {cc.Node|Number} nodeOrPriority The priority of the listener is based on the draw order of this node or fixedPriority The fixed priority of the listener.
+ * @note The priority of scene graph will be fixed value 0. So the order of listener item in the vector will be ' <0, scene graph (0 priority), >0'.
+ * A lower priority will be called before the ones that have a higher value. 0 priority is forbidden for fixed priority since it's used for scene graph based priority.
+ * The listener must be a cc.EventListener object when adding a fixed priority listener, because we can't remove a fixed priority listener without the listener handler,
+ * except calls removeAllListeners().
+ * @return {cc.EventListener} Return the listener. Needed in order to remove the event from the dispatcher.
+ */
+ addListener: function (listener, nodeOrPriority) {
+ cc.assert(listener && nodeOrPriority, cc._LogInfos.eventManager_addListener_2);
+ if (!(listener instanceof cc.EventListener)) {
+ cc.assert(!cc.isNumber(nodeOrPriority), cc._LogInfos.eventManager_addListener_3);
+ listener = cc.EventListener.create(listener);
+ } else {
+ if (listener._isRegistered()) {
+ cc.log(cc._LogInfos.eventManager_addListener_4);
+ return;
+ }
+ }
+
+ if (!listener.checkAvailable())
+ return;
+
+ if (cc.isNumber(nodeOrPriority)) {
+ if (nodeOrPriority === 0) {
+ cc.log(cc._LogInfos.eventManager_addListener);
+ return;
+ }
+
+ listener._setSceneGraphPriority(null);
+ listener._setFixedPriority(nodeOrPriority);
+ listener._setRegistered(true);
+ listener._setPaused(false);
+ this._addListener(listener);
+ } else {
+ listener._setSceneGraphPriority(nodeOrPriority);
+ listener._setFixedPriority(0);
+ listener._setRegistered(true);
+ this._addListener(listener);
+ }
+
+ return listener;
+ },
+
+ /**
+ * Adds a Custom event listener. It will use a fixed priority of 1.
+ * @param {string} eventName
+ * @param {function} callback
+ * @return {cc.EventListener} the generated event. Needed in order to remove the event from the dispatcher
+ */
+ addCustomListener: function (eventName, callback, target) {
+ var listener = new cc._EventListenerCustom(eventName, callback, target);
+ this.addListener(listener, 1);
+ return listener;
+ },
+
+ /**
+ * Remove a listener
+ * @param {cc.EventListener} listener an event listener or a registered node target
+ */
+ removeListener: function (listener) {
+ if (listener == null)
+ return;
+
+ var isFound, locListener = this._listenersMap;
+ for (var selKey in locListener) {
+ var listeners = locListener[selKey];
+ var fixedPriorityListeners = listeners.getFixedPriorityListeners(), sceneGraphPriorityListeners = listeners.getSceneGraphPriorityListeners();
+
+ isFound = this._removeListenerInVector(sceneGraphPriorityListeners, listener);
+ if (isFound){
+ // fixed #4160: Dirty flag need to be updated after listeners were removed.
+ this._setDirty(listener._getListenerID(), this.DIRTY_SCENE_GRAPH_PRIORITY);
+ }else{
+ isFound = this._removeListenerInVector(fixedPriorityListeners, listener);
+ if (isFound)
+ this._setDirty(listener._getListenerID(), this.DIRTY_FIXED_PRIORITY);
+ }
+
+ if (listeners.empty()) {
+ delete this._priorityDirtyFlagMap[listener._getListenerID()];
+ delete locListener[selKey];
+ }
+
+ if (isFound)
+ break;
+ }
+
+ if (!isFound) {
+ var locToAddedListeners = this._toAddedListeners;
+ for (var i = 0, len = locToAddedListeners.length; i < len; i++) {
+ var selListener = locToAddedListeners[i];
+ if (selListener === listener) {
+ cc.arrayRemoveObject(locToAddedListeners, selListener);
+ selListener._setRegistered(false);
+ break;
+ }
+ }
+ }
+ },
+
+ _removeListenerInCallback: function (listeners, callback) {
+ if (listeners == null)
+ return false;
+
+ for (var i = 0, len = listeners.length; i < len; i++) {
+ var selListener = listeners[i];
+ if (selListener._onCustomEvent === callback || selListener._onEvent === callback) {
+ selListener._setRegistered(false);
+ if (selListener._getSceneGraphPriority() != null) {
+ this._dissociateNodeAndEventListener(selListener._getSceneGraphPriority(), selListener);
+ selListener._setSceneGraphPriority(null); // NULL out the node pointer so we don't have any dangling pointers to destroyed nodes.
+ }
+
+ if (this._inDispatch === 0)
+ cc.arrayRemoveObject(listeners, selListener);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _removeListenerInVector: function (listeners, listener) {
+ if (listeners == null)
+ return false;
+
+ for (var i = 0, len = listeners.length; i < len; i++) {
+ var selListener = listeners[i];
+ if (selListener === listener) {
+ selListener._setRegistered(false);
+ if (selListener._getSceneGraphPriority() != null) {
+ this._dissociateNodeAndEventListener(selListener._getSceneGraphPriority(), selListener);
+ selListener._setSceneGraphPriority(null); // NULL out the node pointer so we don't have any dangling pointers to destroyed nodes.
+ }
+
+ if (this._inDispatch === 0)
+ cc.arrayRemoveObject(listeners, selListener);
+ else
+ this._toRemovedListeners.push(selListener);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Removes all listeners with the same event listener type or removes all listeners of a node
+ * @param {Number|cc.Node} listenerType listenerType or a node
+ * @param {Boolean} [recursive=false]
+ */
+ removeListeners: function (listenerType, recursive) {
+ var _t = this;
+ if (listenerType instanceof cc.Node) {
+ // Ensure the node is removed from these immediately also.
+ // Don't want any dangling pointers or the possibility of dealing with deleted objects..
+ delete _t._nodePriorityMap[listenerType.__instanceId];
+ cc.arrayRemoveObject(_t._dirtyNodes, listenerType);
+ var listeners = _t._nodeListenersMap[listenerType.__instanceId], i;
+ if (listeners) {
+ var listenersCopy = cc.copyArray(listeners);
+ for (i = 0; i < listenersCopy.length; i++)
+ _t.removeListener(listenersCopy[i]);
+ listenersCopy.length = 0;
+ }
+
+ // Bug fix: ensure there are no references to the node in the list of listeners to be added.
+ // If we find any listeners associated with the destroyed node in this list then remove them.
+ // This is to catch the scenario where the node gets destroyed before it's listener
+ // is added into the event dispatcher fully. This could happen if a node registers a listener
+ // and gets destroyed while we are dispatching an event (touch etc.)
+ var locToAddedListeners = _t._toAddedListeners;
+ for (i = 0; i < locToAddedListeners.length; ) {
+ var listener = locToAddedListeners[i];
+ if (listener._getSceneGraphPriority() === listenerType) {
+ listener._setSceneGraphPriority(null); // Ensure no dangling ptr to the target node.
+ listener._setRegistered(false);
+ locToAddedListeners.splice(i, 1);
+ } else
+ ++i;
+ }
+
+ if (recursive === true) {
+ var locChildren = listenerType.getChildren(), len;
+ for (i = 0, len = locChildren.length; i< len; i++)
+ _t.removeListeners(locChildren[i], true);
+ }
+ } else {
+ if (listenerType === cc.EventListener.TOUCH_ONE_BY_ONE)
+ _t._removeListenersForListenerID(cc._EventListenerTouchOneByOne.LISTENER_ID);
+ else if (listenerType === cc.EventListener.TOUCH_ALL_AT_ONCE)
+ _t._removeListenersForListenerID(cc._EventListenerTouchAllAtOnce.LISTENER_ID);
+ else if (listenerType === cc.EventListener.MOUSE)
+ _t._removeListenersForListenerID(cc._EventListenerMouse.LISTENER_ID);
+ else if (listenerType === cc.EventListener.ACCELERATION)
+ _t._removeListenersForListenerID(cc._EventListenerAcceleration.LISTENER_ID);
+ else if (listenerType === cc.EventListener.KEYBOARD)
+ _t._removeListenersForListenerID(cc._EventListenerKeyboard.LISTENER_ID);
+ else
+ cc.log(cc._LogInfos.eventManager_removeListeners);
+ }
+ },
+
+ /**
+ * Removes all custom listeners with the same event name
+ * @param {string} customEventName
+ */
+ removeCustomListeners: function (customEventName) {
+ this._removeListenersForListenerID(customEventName);
+ },
+
+ /**
+ * Removes all listeners
+ */
+ removeAllListeners: function () {
+ var locListeners = this._listenersMap, locInternalCustomEventIDs = this._internalCustomListenerIDs;
+ for (var selKey in locListeners) {
+ if (locInternalCustomEventIDs.indexOf(selKey) === -1)
+ this._removeListenersForListenerID(selKey);
+ }
+ },
+
+ /**
+ * Sets listener's priority with fixed value.
+ * @param {cc.EventListener} listener
+ * @param {Number} fixedPriority
+ */
+ setPriority: function (listener, fixedPriority) {
+ if (listener == null)
+ return;
+
+ var locListeners = this._listenersMap;
+ for (var selKey in locListeners) {
+ var selListeners = locListeners[selKey];
+ var fixedPriorityListeners = selListeners.getFixedPriorityListeners();
+ if (fixedPriorityListeners) {
+ var found = fixedPriorityListeners.indexOf(listener);
+ if (found !== -1) {
+ if (listener._getSceneGraphPriority() != null)
+ cc.log(cc._LogInfos.eventManager_setPriority);
+ if (listener._getFixedPriority() !== fixedPriority) {
+ listener._setFixedPriority(fixedPriority);
+ this._setDirty(listener._getListenerID(), this.DIRTY_FIXED_PRIORITY);
+ }
+ return;
+ }
+ }
+ }
+ },
+
+ /**
+ * Whether to enable dispatching events
+ * @param {boolean} enabled
+ */
+ setEnabled: function (enabled) {
+ this._isEnabled = enabled;
+ },
+
+ /**
+ * Checks whether dispatching events is enabled
+ * @returns {boolean}
+ */
+ isEnabled: function () {
+ return this._isEnabled;
+ },
+
+ /**
+ * Dispatches the event, also removes all EventListeners marked for deletion from the event dispatcher list.
+ * @param {cc.Event} event
+ */
+ dispatchEvent: function (event) {
+ if (!this._isEnabled)
+ return;
+
+ this._updateDirtyFlagForSceneGraph();
+ this._inDispatch++;
+ if (!event || !event.getType)
+ throw new Error("event is undefined");
+ if (event._type === cc.Event.TOUCH) {
+ this._dispatchTouchEvent(event);
+ this._inDispatch--;
+ return;
+ }
+
+ var listenerID = __getListenerID(event);
+ this._sortEventListeners(listenerID);
+ var selListeners = this._listenersMap[listenerID];
+ if (selListeners) {
+ this._dispatchEventToListeners(selListeners, this._onListenerCallback, event);
+ this._onUpdateListeners(selListeners);
+ }
+
+ this._inDispatch--;
+ },
+
+ _onListenerCallback: function (listener, event) {
+ event._setCurrentTarget(listener._getSceneGraphPriority());
+ listener._onEvent(event);
+ return event.isStopped();
+ },
+
+ /**
+ * Dispatches a Custom Event with a event name an optional user data
+ * @param {string} eventName
+ * @param {*} optionalUserData
+ */
+ dispatchCustomEvent: function (eventName, optionalUserData) {
+ var ev = new cc.EventCustom(eventName);
+ ev.setUserData(optionalUserData);
+ this.dispatchEvent(ev);
+ }
+};
+
+})();
diff --git a/cocos2d/core/event-manager/CCTouch.js b/cocos2d/core/event-manager/CCTouch.js
new file mode 100644
index 0000000000..3c8ea79fb9
--- /dev/null
+++ b/cocos2d/core/event-manager/CCTouch.js
@@ -0,0 +1,176 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The touch event class
+ * @class
+ * @extends cc.Class
+ *
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} id
+ */
+cc.Touch = cc.Class.extend(/** @lends cc.Touch# */{
+ _lastModified: 0,
+ _point:null,
+ _prevPoint:null,
+ _id:0,
+ _startPointCaptured: false,
+ _startPoint:null,
+
+ ctor:function (x, y, id) {
+ this.setTouchInfo(id, x, y);
+ },
+
+ /**
+ * Returns the current touch location in OpenGL coordinates
+ * @return {cc.Point}
+ */
+ getLocation:function () {
+ //TODO
+ //return cc.director.convertToGL(this._point);
+ return {x: this._point.x, y: this._point.y};
+ },
+
+ /**
+ * Returns X axis location value
+ * @returns {number}
+ */
+ getLocationX: function () {
+ return this._point.x;
+ },
+
+ /**
+ * Returns Y axis location value
+ * @returns {number}
+ */
+ getLocationY: function () {
+ return this._point.y;
+ },
+
+ /**
+ * Returns the previous touch location in OpenGL coordinates
+ * @return {cc.Point}
+ */
+ getPreviousLocation:function () {
+ //TODO
+ //return cc.director.convertToGL(this._prevPoint);
+ return {x: this._prevPoint.x, y: this._prevPoint.y};
+ },
+
+ /**
+ * Returns the start touch location in OpenGL coordinates
+ * @returns {cc.Point}
+ */
+ getStartLocation: function() {
+ //TODO
+ //return cc.director.convertToGL(this._startPoint);
+ return {x: this._startPoint.x, y: this._startPoint.y};
+ },
+
+ /**
+ * Returns the delta distance from the previous touche to the current one in screen coordinates
+ * @return {cc.Point}
+ */
+ getDelta:function () {
+ return cc.pSub(this._point, this._prevPoint);
+ },
+
+ /**
+ * Returns the current touch location in screen coordinates
+ * @return {cc.Point}
+ */
+ getLocationInView: function() {
+ return {x: this._point.x, y: this._point.y};
+ },
+
+ /**
+ * Returns the previous touch location in screen coordinates
+ * @return {cc.Point}
+ */
+ getPreviousLocationInView: function(){
+ return {x: this._prevPoint.x, y: this._prevPoint.y};
+ },
+
+ /**
+ * Returns the start touch location in screen coordinates
+ * @return {cc.Point}
+ */
+ getStartLocationInView: function(){
+ return {x: this._startPoint.x, y: this._startPoint.y};
+ },
+
+ /**
+ * Returns the id of cc.Touch
+ * @return {Number}
+ */
+ getID:function () {
+ return this._id;
+ },
+
+ /**
+ * Returns the id of cc.Touch
+ * @return {Number}
+ * @deprecated since v3.0, please use getID() instead
+ */
+ getId:function () {
+ cc.log("getId is deprecated. Please use getID instead.");
+ return this._id;
+ },
+
+ /**
+ * Sets information to touch
+ * @param {Number} id
+ * @param {Number} x
+ * @param {Number} y
+ */
+ setTouchInfo:function (id, x, y) {
+ this._prevPoint = this._point;
+ this._point = cc.p(x || 0, y || 0);
+ this._id = id;
+ if (!this._startPointCaptured) {
+ this._startPoint = cc.p(this._point);
+ cc.view._convertPointWithScale(this._startPoint);
+ this._startPointCaptured = true;
+ }
+ },
+
+ _setPoint: function(x, y){
+ if(y === undefined){
+ this._point.x = x.x;
+ this._point.y = x.y;
+ }else{
+ this._point.x = x;
+ this._point.y = y;
+ }
+ },
+
+ _setPrevPoint:function (x, y) {
+ if(y === undefined)
+ this._prevPoint = cc.p(x.x, x.y);
+ else
+ this._prevPoint = cc.p(x || 0, y || 0);
+ }
+});
\ No newline at end of file
diff --git a/cocos2d/core/labelttf/CCLabelTTF.js b/cocos2d/core/labelttf/CCLabelTTF.js
new file mode 100644
index 0000000000..ac988109b9
--- /dev/null
+++ b/cocos2d/core/labelttf/CCLabelTTF.js
@@ -0,0 +1,974 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels with system font or a ttf font file
+ * All features from cc.Sprite are valid in cc.LabelTTF
+ * cc.LabelTTF objects are slow for js-binding on mobile devices.
+ * Consider using cc.LabelAtlas or cc.LabelBMFont instead.
+ * You can create a cc.LabelTTF from a font name, alignment, dimension and font size or a cc.FontDefinition object.
+ * @class
+ * @extends cc.Sprite
+ *
+ * @param {String} text
+ * @param {String|cc.FontDefinition} [fontName="Arial"]
+ * @param {Number} [fontSize=16]
+ * @param {cc.Size} [dimensions=cc.size(0,0)]
+ * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT]
+ * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
+ * @example
+ * var myLabel = new cc.LabelTTF('label text', 'Times New Roman', 32, cc.size(320,32), cc.TEXT_ALIGNMENT_LEFT);
+ *
+ * var fontDef = new cc.FontDefinition();
+ * fontDef.fontName = "Arial";
+ * fontDef.fontSize = "32";
+ * var myLabel = new cc.LabelTTF('label text', fontDef);
+ *
+ * @property {String} string - Content string of label
+ * @property {Number} textAlign - Horizontal Alignment of label: cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT
+ * @property {Number} verticalAlign - Vertical Alignment of label: cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM
+ * @property {Number} fontSize - Font size of label
+ * @property {String} fontName - Font name of label
+ * @property {String} font - The label font with a style string: e.g. "18px Verdana"
+ * @property {Number} boundingWidth - Width of the bounding box of label, the real content width is limited by boundingWidth
+ * @property {Number} boundingHeight - Height of the bounding box of label, the real content height is limited by boundingHeight
+ * @property {cc.Color} fillStyle - The fill color
+ * @property {cc.Color} strokeStyle - The stroke color
+ * @property {Number} lineWidth - The line width for stroke
+ * @property {Number} shadowOffsetX - The x axis offset of shadow
+ * @property {Number} shadowOffsetY - The y axis offset of shadow
+ * @property {Number} shadowOpacity - The opacity of shadow
+ * @property {Number} shadowBlur - The blur size of shadow
+ */
+cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{
+ _dimensions: null,
+ _hAlignment: cc.TEXT_ALIGNMENT_CENTER,
+ _vAlignment: cc.VERTICAL_TEXT_ALIGNMENT_TOP,
+ _fontName: null,
+ _fontSize: 0.0,
+ _string: "",
+ _originalText: null,
+ _onCacheCanvasMode: true,
+
+ // font shadow
+ _shadowEnabled: false,
+ _shadowOffset: null,
+ _shadowOpacity: 0,
+ _shadowBlur: 0,
+ _shadowColor: null,
+
+ // font stroke
+ _strokeEnabled: false,
+ _strokeColor: null,
+ _strokeSize: 0,
+
+ // font tint
+ _textFillColor: null,
+
+ _strokeShadowOffsetX: 0,
+ _strokeShadowOffsetY: 0,
+ _needUpdateTexture: false,
+
+ _lineWidths: null,
+ _className: "LabelTTF",
+
+ //for web
+ _fontStyle: "normal",
+ _fontWeight: "normal",
+ _lineHeight: "normal",
+
+ /**
+ * Initializes the cc.LabelTTF with a font name, alignment, dimension and font size, do not call it by yourself,
+ * you should pass the correct arguments in constructor to initialize the label.
+ * @param {String} label string
+ * @param {String} fontName
+ * @param {Number} fontSize
+ * @param {cc.Size} [dimensions=]
+ * @param {Number} [hAlignment=]
+ * @param {Number} [vAlignment=]
+ * @return {Boolean} return false on error
+ */
+ initWithString: function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) {
+ var strInfo;
+ if (label)
+ strInfo = label + "";
+ else
+ strInfo = "";
+
+ fontSize = fontSize || 16;
+ dimensions = dimensions || cc.size(0, 0/*fontSize*/);
+ hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT;
+ vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP;
+
+ this._opacityModifyRGB = false;
+ this._dimensions = cc.size(dimensions.width, dimensions.height);
+ this._fontName = fontName || "Arial";
+ this._hAlignment = hAlignment;
+ this._vAlignment = vAlignment;
+
+ this._fontSize = fontSize;
+ this._renderCmd._setFontStyle(this._fontName, fontSize, this._fontStyle, this._fontWeight);
+ this.string = strInfo;
+ this._renderCmd._setColorsString();
+ this._renderCmd._updateTexture();
+ this._setUpdateTextureDirty();
+
+ // Needed for high dpi text.
+ // In order to render it crisp, we request devicePixelRatio times the
+ // font size and scale it down 1/devicePixelRatio.
+ this._scaleX = this._scaleY = 1 / cc.view.getDevicePixelRatio();
+ return true;
+ },
+
+ _setUpdateTextureDirty: function () {
+ this._needUpdateTexture = true;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.textDirty);
+ },
+
+ ctor: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
+ cc.Sprite.prototype.ctor.call(this);
+
+ this._dimensions = cc.size(0, 0);
+ this._hAlignment = cc.TEXT_ALIGNMENT_LEFT;
+ this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
+ this._opacityModifyRGB = false;
+ this._fontName = "Arial";
+
+ this._shadowEnabled = false;
+ this._shadowOffset = cc.p(0, 0);
+ this._shadowOpacity = 0;
+ this._shadowBlur = 0;
+
+ this._strokeEnabled = false;
+ this._strokeColor = cc.color(255, 255, 255, 255);
+ this._strokeSize = 0;
+
+ this._textFillColor = cc.color(255, 255, 255, 255);
+ this._strokeShadowOffsetX = 0;
+ this._strokeShadowOffsetY = 0;
+ this._needUpdateTexture = false;
+
+ this._lineWidths = [];
+ this._renderCmd._setColorsString();
+ this._textureLoaded = true;
+
+ if (fontName && fontName instanceof cc.FontDefinition) {
+ this.initWithStringAndTextDefinition(text, fontName);
+ } else {
+ cc.LabelTTF.prototype.initWithString.call(this, text, fontName, fontSize, dimensions, hAlignment, vAlignment);
+ }
+ },
+
+ init: function () {
+ return this.initWithString(" ", this._fontName, this._fontSize);
+ },
+
+ description: function () {
+ return "";
+ },
+
+ getLineHeight: function () {
+ return !this._lineHeight || this._lineHeight.charAt ?
+ this._renderCmd._getFontClientHeight() :
+ this._lineHeight || this._renderCmd._getFontClientHeight();
+ },
+
+ setLineHeight: function (lineHeight) {
+ this._lineHeight = lineHeight;
+ },
+
+ /**
+ * Returns the text of the label
+ * @return {String}
+ */
+ getString: function () {
+ return this._string;
+ },
+
+ /**
+ * Returns Horizontal Alignment of cc.LabelTTF
+ * @return {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT}
+ */
+ getHorizontalAlignment: function () {
+ return this._hAlignment;
+ },
+
+ /**
+ * Returns Vertical Alignment of cc.LabelTTF
+ * @return {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM}
+ */
+ getVerticalAlignment: function () {
+ return this._vAlignment;
+ },
+
+ /**
+ * Returns the dimensions of cc.LabelTTF, the dimension is the maximum size of the label, set it so that label will automatically change lines when necessary.
+ * @see cc.LabelTTF#setDimensions, cc.LabelTTF#boundingWidth and cc.LabelTTF#boundingHeight
+ * @return {cc.Size}
+ */
+ getDimensions: function () {
+ return cc.size(this._dimensions);
+ },
+
+ /**
+ * Returns font size of cc.LabelTTF
+ * @return {Number}
+ */
+ getFontSize: function () {
+ return this._fontSize;
+ },
+
+ /**
+ * Returns font name of cc.LabelTTF
+ * @return {String}
+ */
+ getFontName: function () {
+ return this._fontName;
+ },
+
+ /**
+ * Initializes the CCLabelTTF with a font name, alignment, dimension and font size, do not call it by yourself, you should pass the correct arguments in constructor to initialize the label.
+ * @param {String} text
+ * @param {cc.FontDefinition} textDefinition
+ * @return {Boolean}
+ */
+ initWithStringAndTextDefinition: function (text, textDefinition) {
+ // prepare everything needed to render the label
+ this._updateWithTextDefinition(textDefinition, false);
+ // set the string
+ this.string = text;
+ return true;
+ },
+
+ /**
+ * Sets the text definition used by this label
+ * @param {cc.FontDefinition} theDefinition
+ */
+ setTextDefinition: function (theDefinition) {
+ if (theDefinition)
+ this._updateWithTextDefinition(theDefinition, true);
+ },
+
+ /**
+ * Extract the text definition used by this label
+ * @return {cc.FontDefinition}
+ */
+ getTextDefinition: function () {
+ return this._prepareTextDefinition(false);
+ },
+
+ /**
+ * Enable or disable shadow for the label
+ * @param {cc.Color | Number} a Color or The x axis offset of the shadow
+ * @param {cc.Size | Number} b Size or The y axis offset of the shadow
+ * @param {Number} c The blur size of the shadow or The opacity of the shadow (0 to 1)
+ * @param {null | Number} d Null or The blur size of the shadow
+ * @example
+ * old:
+ * labelttf.enableShadow(shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur);
+ * new:
+ * labelttf.enableShadow(shadowColor, offset, blurRadius);
+ */
+ enableShadow: function (a, b, c, d) {
+ if (a.r != null && a.g != null && a.b != null && a.a != null) {
+ this._enableShadow(a, b, c);
+ } else {
+ this._enableShadowNoneColor(a, b, c, d);
+ }
+ },
+
+ _enableShadowNoneColor: function (shadowOffsetX, shadowOffsetY, shadowOpacity, shadowBlur) {
+ shadowOpacity = shadowOpacity || 0.5;
+ if (false === this._shadowEnabled)
+ this._shadowEnabled = true;
+
+ var locShadowOffset = this._shadowOffset;
+ if (locShadowOffset && (locShadowOffset.x !== shadowOffsetX) || (locShadowOffset._y !== shadowOffsetY)) {
+ locShadowOffset.x = shadowOffsetX;
+ locShadowOffset.y = shadowOffsetY;
+ }
+
+ if (this._shadowOpacity !== shadowOpacity) {
+ this._shadowOpacity = shadowOpacity;
+ }
+ this._renderCmd._setColorsString();
+
+ if (this._shadowBlur !== shadowBlur)
+ this._shadowBlur = shadowBlur;
+ this._setUpdateTextureDirty();
+ },
+
+ _enableShadow: function (shadowColor, offset, blurRadius) {
+ if (!this._shadowColor) {
+ this._shadowColor = cc.color(255, 255, 255, 128);
+ }
+ this._shadowColor.r = shadowColor.r;
+ this._shadowColor.g = shadowColor.g;
+ this._shadowColor.b = shadowColor.b;
+
+ var x, y, a, b;
+ x = offset.width || offset.x || 0;
+ y = offset.height || offset.y || 0;
+ a = (shadowColor.a != null) ? (shadowColor.a / 255) : 0.5;
+ b = blurRadius;
+
+ this._enableShadowNoneColor(x, y, a, b);
+ },
+
+ _getShadowOffsetX: function () {
+ return this._shadowOffset.x;
+ },
+ _setShadowOffsetX: function (x) {
+ if (false === this._shadowEnabled)
+ this._shadowEnabled = true;
+
+ if (this._shadowOffset.x !== x) {
+ this._shadowOffset.x = x;
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getShadowOffsetY: function () {
+ return this._shadowOffset._y;
+ },
+ _setShadowOffsetY: function (y) {
+ if (false === this._shadowEnabled)
+ this._shadowEnabled = true;
+
+ if (this._shadowOffset._y !== y) {
+ this._shadowOffset._y = y;
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getShadowOffset: function () {
+ return cc.p(this._shadowOffset.x, this._shadowOffset.y);
+ },
+ _setShadowOffset: function (offset) {
+ if (false === this._shadowEnabled)
+ this._shadowEnabled = true;
+
+ if (this._shadowOffset.x !== offset.x || this._shadowOffset.y !== offset.y) {
+ this._shadowOffset.x = offset.x;
+ this._shadowOffset.y = offset.y;
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getShadowOpacity: function () {
+ return this._shadowOpacity;
+ },
+ _setShadowOpacity: function (shadowOpacity) {
+ if (false === this._shadowEnabled)
+ this._shadowEnabled = true;
+
+ if (this._shadowOpacity !== shadowOpacity) {
+ this._shadowOpacity = shadowOpacity;
+ this._renderCmd._setColorsString();
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getShadowBlur: function () {
+ return this._shadowBlur;
+ },
+ _setShadowBlur: function (shadowBlur) {
+ if (false === this._shadowEnabled)
+ this._shadowEnabled = true;
+
+ if (this._shadowBlur !== shadowBlur) {
+ this._shadowBlur = shadowBlur;
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Disable shadow rendering
+ */
+ disableShadow: function () {
+ if (this._shadowEnabled) {
+ this._shadowEnabled = false;
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Enable label stroke with stroke parameters
+ * @param {cc.Color} strokeColor The color of stroke
+ * @param {Number} strokeSize The size of stroke
+ */
+ enableStroke: function (strokeColor, strokeSize) {
+ if (this._strokeEnabled === false)
+ this._strokeEnabled = true;
+
+ var locStrokeColor = this._strokeColor;
+ if ((locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b)) {
+ locStrokeColor.r = strokeColor.r;
+ locStrokeColor.g = strokeColor.g;
+ locStrokeColor.b = strokeColor.b;
+ this._renderCmd._setColorsString();
+ }
+
+ if (this._strokeSize !== strokeSize)
+ this._strokeSize = strokeSize || 0;
+ this._setUpdateTextureDirty();
+ },
+
+ _getStrokeStyle: function () {
+ return this._strokeColor;
+ },
+ _setStrokeStyle: function (strokeStyle) {
+ if (this._strokeEnabled === false)
+ this._strokeEnabled = true;
+
+ var locStrokeColor = this._strokeColor;
+ if ((locStrokeColor.r !== strokeStyle.r) || (locStrokeColor.g !== strokeStyle.g) || (locStrokeColor.b !== strokeStyle.b)) {
+ locStrokeColor.r = strokeStyle.r;
+ locStrokeColor.g = strokeStyle.g;
+ locStrokeColor.b = strokeStyle.b;
+ this._renderCmd._setColorsString();
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getLineWidth: function () {
+ return this._strokeSize;
+ },
+ _setLineWidth: function (lineWidth) {
+ if (this._strokeEnabled === false)
+ this._strokeEnabled = true;
+ if (this._strokeSize !== lineWidth) {
+ this._strokeSize = lineWidth || 0;
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Disable label stroke
+ */
+ disableStroke: function () {
+ if (this._strokeEnabled) {
+ this._strokeEnabled = false;
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Sets the text fill color
+ * @function
+ * @param {cc.Color} fillColor The fill color of the label
+ */
+ setFontFillColor: function (fillColor) {
+ var locTextFillColor = this._textFillColor;
+ if (locTextFillColor.r !== fillColor.r || locTextFillColor.g !== fillColor.g || locTextFillColor.b !== fillColor.b) {
+ locTextFillColor.r = fillColor.r;
+ locTextFillColor.g = fillColor.g;
+ locTextFillColor.b = fillColor.b;
+ this._renderCmd._setColorsString();
+ this._needUpdateTexture = true;
+ }
+ },
+
+ _getFillStyle: function () {
+ return this._textFillColor;
+ },
+
+ //set the text definition for this label
+ _updateWithTextDefinition: function (textDefinition, mustUpdateTexture) {
+ if (textDefinition.fontDimensions) {
+ this._dimensions.width = textDefinition.boundingWidth;
+ this._dimensions.height = textDefinition.boundingHeight;
+ } else {
+ this._dimensions.width = 0;
+ this._dimensions.height = 0;
+ }
+
+ this._hAlignment = textDefinition.textAlign;
+ this._vAlignment = textDefinition.verticalAlign;
+
+ this._fontName = textDefinition.fontName;
+ this._fontSize = textDefinition.fontSize || 12;
+
+ if (textDefinition.lineHeight)
+ this._lineHeight = textDefinition.lineHeight;
+ else
+ this._lineHeight = this._fontSize;
+
+ this._renderCmd._setFontStyle(textDefinition);
+
+
+ // shadow
+ if (textDefinition.shadowEnabled)
+ this.enableShadow(textDefinition.shadowOffsetX,
+ textDefinition.shadowOffsetY,
+ textDefinition.shadowOpacity,
+ textDefinition.shadowBlur);
+
+ // stroke
+ if (textDefinition.strokeEnabled)
+ this.enableStroke(textDefinition.strokeStyle, textDefinition.lineWidth);
+
+ // fill color
+ this.setFontFillColor(textDefinition.fillStyle);
+
+ if (mustUpdateTexture)
+ this._renderCmd._updateTexture();
+ var flags = cc.Node._dirtyFlags;
+ this._renderCmd.setDirtyFlag(flags.colorDirty | flags.opacityDirty | flags.textDirty);
+ },
+
+ _prepareTextDefinition: function (adjustForResolution) {
+ var texDef = new cc.FontDefinition();
+
+ if (adjustForResolution) {
+ texDef.fontSize = this._fontSize;
+ texDef.boundingWidth = cc.contentScaleFactor() * this._dimensions.width;
+ texDef.boundingHeight = cc.contentScaleFactor() * this._dimensions.height;
+ } else {
+ texDef.fontSize = this._fontSize;
+ texDef.boundingWidth = this._dimensions.width;
+ texDef.boundingHeight = this._dimensions.height;
+ }
+
+ texDef.fontName = this._fontName;
+ texDef.textAlign = this._hAlignment;
+ texDef.verticalAlign = this._vAlignment;
+
+ // stroke
+ if (this._strokeEnabled) {
+ texDef.strokeEnabled = true;
+ var locStrokeColor = this._strokeColor;
+ texDef.strokeStyle = cc.color(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b);
+ texDef.lineWidth = this._strokeSize;
+ } else
+ texDef.strokeEnabled = false;
+
+ // shadow
+ if (this._shadowEnabled) {
+ texDef.shadowEnabled = true;
+ texDef.shadowBlur = this._shadowBlur;
+ texDef.shadowOpacity = this._shadowOpacity;
+
+ texDef.shadowOffsetX = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.x;
+ texDef.shadowOffsetY = (adjustForResolution ? cc.contentScaleFactor() : 1) * this._shadowOffset.y;
+ } else
+ texDef._shadowEnabled = false;
+
+ // text tint
+ var locTextFillColor = this._textFillColor;
+ texDef.fillStyle = cc.color(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b);
+ return texDef;
+ },
+
+ /*
+ * BEGIN SCALE METHODS
+ *
+ * In order to make the value of scaleX and scaleY consistent across
+ * screens, we provide patched versions that return the same values as if
+ * the screen was not HiDPI.
+ */
+
+ /**
+ * Returns the scale factor of the node.
+ * @warning: Assertion will fail when _scaleX != _scaleY.
+ * @function
+ * @return {Number} The scale factor
+ */
+ getScale: function () {
+ if (this._scaleX !== this._scaleY)
+ cc.log(cc._LogInfos.Node_getScale);
+ return this._scaleX * cc.view.getDevicePixelRatio();
+ },
+
+ /**
+ * Sets the scale factor of the node. 1.0 is the default scale factor. This function can modify the X and Y scale at the same time.
+ * @function
+ * @param {Number} scale or scaleX value
+ * @param {Number} [scaleY=]
+ */
+ setScale: function (scale, scaleY) {
+ var ratio = cc.view.getDevicePixelRatio();
+ this._scaleX = scale / ratio;
+ this._scaleY = ((scaleY || scaleY === 0) ? scaleY : scale) / ratio;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the scale factor on X axis of this node
+ * @function
+ * @return {Number} The scale factor on X axis.
+ */
+ getScaleX: function () {
+ return this._scaleX * cc.view.getDevicePixelRatio();
+ },
+
+ /**
+ *
+ * Changes the scale factor on X axis of this node
+ * The default value is 1.0 if you haven't changed it before
+ *
+ * @function
+ * @param {Number} newScaleX The scale factor on X axis.
+ */
+ setScaleX: function (newScaleX) {
+ this._scaleX = newScaleX / cc.view.getDevicePixelRatio();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Returns the scale factor on Y axis of this node
+ * @function
+ * @return {Number} The scale factor on Y axis.
+ */
+ getScaleY: function () {
+ return this._scaleY * cc.view.getDevicePixelRatio();
+ },
+
+ /**
+ *
+ * Changes the scale factor on Y axis of this node
+ * The Default value is 1.0 if you haven't changed it before.
+ *
+ * @function
+ * @param {Number} newScaleY The scale factor on Y axis.
+ */
+ setScaleY: function (newScaleY) {
+ this._scaleY = newScaleY / cc.view.getDevicePixelRatio();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /*
+ * END SCALE METHODS
+ */
+
+ /**
+ * Changes the text content of the label
+ * @warning Changing the string is as expensive as creating a new cc.LabelTTF. To obtain better performance use cc.LabelAtlas
+ * @param {String} text Text content for the label
+ */
+ setString: function (text) {
+ text = String(text);
+ if (this._originalText !== text) {
+ this._originalText = text + "";
+
+ this._updateString();
+
+ // Force update
+ this._setUpdateTextureDirty();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ }
+ },
+ _updateString: function () {
+ if ((!this._string || this._string === "") && this._string !== this._originalText)
+ cc.renderer.childrenOrderDirty = true;
+ this._string = this._originalText;
+ },
+
+ /**
+ * Sets Horizontal Alignment of cc.LabelTTF
+ * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
+ */
+ setHorizontalAlignment: function (alignment) {
+ if (alignment !== this._hAlignment) {
+ this._hAlignment = alignment;
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Sets Vertical Alignment of cc.LabelTTF
+ * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment
+ */
+ setVerticalAlignment: function (verticalAlignment) {
+ if (verticalAlignment !== this._vAlignment) {
+ this._vAlignment = verticalAlignment;
+
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Set Dimensions of cc.LabelTTF, the dimension is the maximum size of the label, set it so that label will automatically change lines when necessary.
+ * @param {cc.Size|Number} dim dimensions or width of dimensions
+ * @param {Number} [height] height of dimensions
+ */
+ setDimensions: function (dim, height) {
+ var width;
+ if (height === undefined) {
+ width = dim.width;
+ height = dim.height;
+ } else
+ width = dim;
+
+ if (width !== this._dimensions.width || height !== this._dimensions.height) {
+ this._dimensions.width = width;
+ this._dimensions.height = height;
+ this._updateString();
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getBoundingWidth: function () {
+ return this._dimensions.width;
+ },
+ _setBoundingWidth: function (width) {
+ if (width !== this._dimensions.width) {
+ this._dimensions.width = width;
+ this._updateString();
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getBoundingHeight: function () {
+ return this._dimensions.height;
+ },
+ _setBoundingHeight: function (height) {
+ if (height !== this._dimensions.height) {
+ this._dimensions.height = height;
+ this._updateString();
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Sets font size of cc.LabelTTF
+ * @param {Number} fontSize
+ */
+ setFontSize: function (fontSize) {
+ if (this._fontSize !== fontSize) {
+ this._fontSize = fontSize;
+ this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Sets font name of cc.LabelTTF
+ * @param {String} fontName
+ */
+ setFontName: function (fontName) {
+ if (this._fontName && this._fontName !== fontName) {
+ this._fontName = fontName;
+ this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getFont: function () {
+ return this._renderCmd._getFontStyle();
+ },
+ _setFont: function (fontStyle) {
+ var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
+ if (res) {
+ this._fontSize = parseInt(res[1]);
+ this._fontName = res[2];
+ this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
+
+ // Force update
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ /**
+ * Returns the actual content size of the label, the content size is the real size that the label occupied while dimension is the outer bounding box of the label.
+ * @returns {cc.Size} The content size
+ */
+ getContentSize: function () {
+ if (this._needUpdateTexture)
+ this._renderCmd._updateTTF();
+ var ratio = cc.view.getDevicePixelRatio();
+ return cc.size( this._contentSize.width / ratio, this._contentSize.height / ratio );
+ },
+
+ _getWidth: function () {
+ if (this._needUpdateTexture)
+ this._renderCmd._updateTTF();
+ return this._contentSize.width / cc.view.getDevicePixelRatio();
+ },
+ _getHeight: function () {
+ if (this._needUpdateTexture)
+ this._renderCmd._updateTTF();
+ return this._contentSize.height / cc.view.getDevicePixelRatio();
+ },
+
+ setTextureRect: function (rect, rotated, untrimmedSize) {
+ var _t = this;
+ _t._rectRotated = rotated || false;
+ _t.setContentSize(untrimmedSize || rect);
+
+ var locRect = _t._rect;
+ locRect.x = rect.x;
+ locRect.y = rect.y;
+ locRect.width = rect.width;
+ locRect.height = rect.height;
+ _t._renderCmd._setTextureCoords(rect, false);
+
+ var relativeOffsetX = _t._unflippedOffsetPositionFromCenter.x, relativeOffsetY = _t._unflippedOffsetPositionFromCenter.y;
+ if (_t._flippedX)
+ relativeOffsetX = -relativeOffsetX;
+ if (_t._flippedY)
+ relativeOffsetY = -relativeOffsetY;
+ _t._offsetPosition.x = relativeOffsetX + (rect.width - locRect.width) / 2;
+ _t._offsetPosition.y = relativeOffsetY + (rect.height - locRect.height) / 2;
+ },
+
+ /**
+ * set Target to draw on
+ * @param boolean onCanvas
+ */
+ setDrawMode: function (onCacheMode) {
+ this._onCacheCanvasMode = onCacheMode;
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new cc.LabelTTF.WebGLRenderCmd(this);
+ else if (this._onCacheCanvasMode)
+ return new cc.LabelTTF.CacheCanvasRenderCmd(this);
+ else
+ return new cc.LabelTTF.CanvasRenderCmd(this);
+ },
+
+ //For web only
+ _setFontStyle: function (fontStyle) {
+ if (this._fontStyle !== fontStyle) {
+ this._fontStyle = fontStyle;
+ this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getFontStyle: function () {
+ return this._fontStyle;
+ },
+
+ _setFontWeight: function (fontWeight) {
+ if (this._fontWeight !== fontWeight) {
+ this._fontWeight = fontWeight;
+ this._renderCmd._setFontStyle(this._fontName, this._fontSize, this._fontStyle, this._fontWeight);
+ this._setUpdateTextureDirty();
+ }
+ },
+
+ _getFontWeight: function () {
+ return this._fontWeight;
+ }
+});
+
+cc.assert(cc.isFunction(cc._tmp.PrototypeLabelTTF), cc._LogInfos.MissingFile, "LabelTTFPropertyDefine.js");
+cc._tmp.PrototypeLabelTTF();
+delete cc._tmp.PrototypeLabelTTF;
+
+// Only support style in this format: "18px Verdana" or "18px 'Helvetica Neue'"
+cc.LabelTTF._fontStyleRE = /^(\d+)px\s+['"]?([\w\s\d]+)['"]?$/;
+
+/**
+ * creates a cc.LabelTTF from a font name, alignment, dimension and font size
+ * @deprecated since v3.0, please use the new construction instead
+ * @see cc.LabelTTF
+ * @static
+ * @param {String} text
+ * @param {String|cc.FontDefinition} [fontName="Arial"]
+ * @param {Number} [fontSize=16]
+ * @param {cc.Size} [dimensions=cc.size(0,0)]
+ * @param {Number} [hAlignment=cc.TEXT_ALIGNMENT_LEFT]
+ * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
+ * @return {cc.LabelTTF|Null}
+ */
+cc.LabelTTF.create = function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
+ return new cc.LabelTTF(text, fontName, fontSize, dimensions, hAlignment, vAlignment);
+};
+
+/**
+ * @deprecated since v3.0, please use the new construction instead
+ * @function
+ * @static
+ */
+cc.LabelTTF.createWithFontDefinition = cc.LabelTTF.create;
+
+cc.LabelTTF.__labelHeightDiv = document.createElement("div");
+cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial";
+cc.LabelTTF.__labelHeightDiv.style.position = "absolute";
+cc.LabelTTF.__labelHeightDiv.style.left = "-100px";
+cc.LabelTTF.__labelHeightDiv.style.top = "-100px";
+cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal";
+
+document.body ?
+ document.body.appendChild(cc.LabelTTF.__labelHeightDiv) :
+ window.addEventListener('load', function () {
+ this.removeEventListener('load', arguments.callee, false);
+ document.body.appendChild(cc.LabelTTF.__labelHeightDiv);
+ }, false);
+
+/**
+ * Returns the height of text with an specified font family and font size, in
+ * device independent pixels.
+ *
+ * @param {string|cc.FontDefinition} fontName
+ * @param {number} fontSize
+ * @returns {number}
+ * @private
+ */
+cc.LabelTTF.__getFontHeightByDiv = function (fontName, fontSize) {
+ var clientHeight, labelDiv = cc.LabelTTF.__labelHeightDiv;
+ if(fontName instanceof cc.FontDefinition){
+ /** @type cc.FontDefinition */
+ var fontDef = fontName;
+ clientHeight = cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()];
+ if (clientHeight > 0) return clientHeight;
+ labelDiv.innerHTML = "ajghl~!";
+ labelDiv.style.fontFamily = fontDef.fontName;
+ labelDiv.style.fontSize = fontDef.fontSize + "px";
+ labelDiv.style.fontStyle = fontDef.fontStyle;
+ labelDiv.style.fontWeight = fontDef.fontWeight;
+
+ clientHeight = labelDiv.clientHeight;
+ cc.LabelTTF.__fontHeightCache[fontDef._getCanvasFontStr()] = clientHeight;
+ labelDiv.innerHTML = "";
+ }
+ else {
+ //Default
+ clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize];
+ if (clientHeight > 0) return clientHeight;
+ labelDiv.innerHTML = "ajghl~!";
+ labelDiv.style.fontFamily = fontName;
+ labelDiv.style.fontSize = fontSize + "px";
+ clientHeight = labelDiv.clientHeight;
+ cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight;
+ labelDiv.innerHTML = "";
+ }
+ return clientHeight;
+
+};
+
+cc.LabelTTF.__fontHeightCache = {};
diff --git a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js
new file mode 100644
index 0000000000..44c8f1866f
--- /dev/null
+++ b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js
@@ -0,0 +1,570 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ http://www.cocos2d-x.org
+ 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.
+ ****************************************************************************/
+
+cc.LabelTTF._textAlign = ["left", "center", "right"];
+cc.LabelTTF._textBaseline = ["top", "middle", "bottom"];
+
+//check the first character
+cc.LabelTTF.wrapInspection = true;
+
+// These regular expressions consider a word any sequence of characters
+// from these Unicode (sub)blocks:
+// - Basic Latin (letters and numbers, plus the hypen-minus '-')
+// - Latin-1 Supplement (accentuated letters and ¿¡ only)
+// - Latin Extended-A (complete)
+// - Latin Extended-B (complete)
+// - IPA Extensions (complete)
+// - Spacing Modifier Letters (complete)
+// - Combining Diacritical Marks (Combining Grapheme Joiner excluded)
+// - Greek and Coptic (complete, including reserved code points)
+// - Cyrillic (complete)
+// - Cyrillic Supplement (complete)
+// - General Punctuation (Non-Breaking Hyphen* [U+2011] and quotation marks)
+// * Note that Hyphen [U+2010] is considered a word boundary.
+cc.LabelTTF._wordRex = /([a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-Ô¯\u2011‵-‷‹â…]+|\S)/;
+cc.LabelTTF._symbolRex = /^[!,.:;}\]%\?>ã€â€˜â€œã€‹Â»ï¼Ÿã€‚,ï¼\u2010′-‴›‼â†â‡-â‰]/;
+cc.LabelTTF._lastWordRex = /([a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-Ô¯\u2011‵-‷‹â…]+|\S)$/;
+cc.LabelTTF._lastEnglish = /[a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-Ô¯\u2011‵-‷‹â…]+$/;
+cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-Ô¯\u2011‵-‷‹â…]/;
+
+(function () {
+ cc.LabelTTF.RenderCmd = function () {
+ this._fontClientHeight = 18;
+ this._fontStyleStr = "";
+ this._shadowColorStr = "rgba(128, 128, 128, 0.5)";
+ this._strokeColorStr = "";
+ this._fillColorStr = "rgba(255,255,255,1)";
+
+ this._labelCanvas = null;
+ this._labelContext = null;
+ this._lineWidths = [];
+ this._strings = [];
+ this._isMultiLine = false;
+ this._status = [];
+ this._renderingIndex = 0;
+
+ this._canUseDirtyRegion = true;
+ };
+ var proto = cc.LabelTTF.RenderCmd.prototype;
+ proto.constructor = cc.LabelTTF.RenderCmd;
+ proto._labelCmdCtor = cc.LabelTTF.RenderCmd;
+
+ proto._setFontStyle = function (fontNameOrFontDef, fontSize, fontStyle, fontWeight) {
+ if (fontNameOrFontDef instanceof cc.FontDefinition) {
+ this._fontStyleStr = fontNameOrFontDef._getCanvasFontStr();
+ this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontNameOrFontDef);
+ } else {
+ var deviceFontSize = fontSize * cc.view.getDevicePixelRatio();
+ this._fontStyleStr = fontStyle + " " + fontWeight + " " + deviceFontSize + "px '" + fontNameOrFontDef + "'";
+ this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontNameOrFontDef, fontSize);
+ }
+ };
+
+ proto._getFontStyle = function () {
+ return this._fontStyleStr;
+ };
+
+ proto._getFontClientHeight = function () {
+ return this._fontClientHeight;
+ };
+
+ proto._updateColor = function () {
+ this._setColorsString();
+ this._updateTexture();
+ };
+
+ proto._setColorsString = function () {
+ var locDisplayColor = this._displayedColor, node = this._node,
+ locShadowColor = node._shadowColor || this._displayedColor;
+ var locStrokeColor = node._strokeColor, locFontFillColor = node._textFillColor;
+ var dr = locDisplayColor.r / 255, dg = locDisplayColor.g / 255, db = locDisplayColor.b / 255;
+
+ this._shadowColorStr = "rgba(" + (0 | (dr * locShadowColor.r)) + "," + (0 | ( dg * locShadowColor.g)) + ","
+ + (0 | (db * locShadowColor.b)) + "," + node._shadowOpacity + ")";
+ this._fillColorStr = "rgba(" + (0 | (dr * locFontFillColor.r)) + "," + (0 | (dg * locFontFillColor.g)) + ","
+ + (0 | (db * locFontFillColor.b)) + ", 1)";
+ this._strokeColorStr = "rgba(" + (0 | (dr * locStrokeColor.r)) + "," + (0 | (dg * locStrokeColor.g)) + ","
+ + (0 | (db * locStrokeColor.b)) + ", 1)";
+ };
+
+ var localBB = new cc.Rect();
+ proto.getLocalBB = function () {
+ var node = this._node;
+ localBB.x = localBB.y = 0;
+ var pixelRatio = cc.view.getDevicePixelRatio();
+ localBB.width = node._getWidth() * pixelRatio;
+ localBB.height = node._getHeight() * pixelRatio;
+ return localBB;
+ };
+
+ proto._updateTTF = function () {
+ var node = this._node;
+ var pixelRatio = cc.view.getDevicePixelRatio();
+ var locDimensionsWidth = node._dimensions.width * pixelRatio, i, strLength;
+ var locLineWidth = this._lineWidths;
+ locLineWidth.length = 0;
+
+ this._isMultiLine = false;
+ this._measureConfig();
+ var textWidthCache = {};
+ if (locDimensionsWidth !== 0) {
+ // Content processing
+ this._strings = node._string.split('\n');
+
+ for (i = 0; i < this._strings.length; i++) {
+ this._checkWarp(this._strings, i, locDimensionsWidth);
+ }
+ } else {
+ this._strings = node._string.split('\n');
+ for (i = 0, strLength = this._strings.length; i < strLength; i++) {
+ if(this._strings[i]) {
+ var measuredWidth = this._measure(this._strings[i]);
+ locLineWidth.push(measuredWidth);
+ textWidthCache[this._strings[i]] = measuredWidth;
+ } else {
+ locLineWidth.push(0);
+ }
+ }
+ }
+
+ if (this._strings.length > 1)
+ this._isMultiLine = true;
+
+ var locSize, locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0;
+ if (node._strokeEnabled)
+ locStrokeShadowOffsetX = locStrokeShadowOffsetY = node._strokeSize * 2;
+ if (node._shadowEnabled) {
+ var locOffsetSize = node._shadowOffset;
+ locStrokeShadowOffsetX += Math.abs(locOffsetSize.x) * 2;
+ locStrokeShadowOffsetY += Math.abs(locOffsetSize.y) * 2;
+ }
+
+ //get offset for stroke and shadow
+ if (locDimensionsWidth === 0) {
+ if (this._isMultiLine) {
+ locSize = cc.size(Math.ceil(Math.max.apply(Math, locLineWidth) + locStrokeShadowOffsetX),
+ Math.ceil((this._fontClientHeight * pixelRatio * this._strings.length) + locStrokeShadowOffsetY));
+ }
+ else {
+ var measuredWidth = textWidthCache[node._string];
+ if(!measuredWidth && node._string) {
+ measuredWidth = this._measure(node._string);
+ }
+ locSize = cc.size(Math.ceil((measuredWidth ? measuredWidth : 0) + locStrokeShadowOffsetX),
+ Math.ceil(this._fontClientHeight * pixelRatio + locStrokeShadowOffsetY));
+ }
+ } else {
+ if (node._dimensions.height === 0) {
+ if (this._isMultiLine)
+ locSize = cc.size(
+ Math.ceil(locDimensionsWidth + locStrokeShadowOffsetX),
+ Math.ceil((node.getLineHeight() * pixelRatio * this._strings.length) + locStrokeShadowOffsetY));
+ else
+ locSize = cc.size(
+ Math.ceil(locDimensionsWidth + locStrokeShadowOffsetX),
+ Math.ceil(node.getLineHeight() * pixelRatio + locStrokeShadowOffsetY));
+ } else {
+ //dimension is already set, contentSize must be same as dimension
+ locSize = cc.size(
+ Math.ceil(locDimensionsWidth + locStrokeShadowOffsetX),
+ Math.ceil(node._dimensions.height * pixelRatio + locStrokeShadowOffsetY));
+ }
+ }
+ if (node._getFontStyle() !== "normal") { //add width for 'italic' and 'oblique'
+ locSize.width = Math.ceil(locSize.width + node._fontSize * 0.3);
+ }
+ node.setContentSize(locSize);
+ node._strokeShadowOffsetX = locStrokeShadowOffsetX;
+ node._strokeShadowOffsetY = locStrokeShadowOffsetY;
+
+ // need computing _anchorPointInPoints
+ var locAP = node._anchorPoint;
+ this._anchorPointInPoints.x = (locStrokeShadowOffsetX * 0.5) + ((locSize.width - locStrokeShadowOffsetX) * locAP.x);
+ this._anchorPointInPoints.y = (locStrokeShadowOffsetY * 0.5) + ((locSize.height - locStrokeShadowOffsetY) * locAP.y);
+ };
+
+ proto._saveStatus = function () {
+ var node = this._node;
+ var scale = cc.view.getDevicePixelRatio();
+ var locStrokeShadowOffsetX = node._strokeShadowOffsetX, locStrokeShadowOffsetY = node._strokeShadowOffsetY;
+ var locContentSizeHeight = node._contentSize.height - locStrokeShadowOffsetY, locVAlignment = node._vAlignment,
+ locHAlignment = node._hAlignment;
+ var dx = locStrokeShadowOffsetX * 0.5,
+ dy = locContentSizeHeight + locStrokeShadowOffsetY * 0.5;
+ var xOffset = 0, yOffset = 0, OffsetYArray = [];
+ var locContentWidth = node._contentSize.width - locStrokeShadowOffsetX;
+
+ //lineHeight
+ var lineHeight = node.getLineHeight() * scale;
+ var transformTop = (lineHeight - this._fontClientHeight * scale) / 2;
+
+ if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT)
+ xOffset += locContentWidth;
+ else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER)
+ xOffset += locContentWidth / 2;
+ else
+ xOffset += 0;
+
+ if (this._isMultiLine) {
+ var locStrLen = this._strings.length;
+ if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM)
+ yOffset = lineHeight - transformTop * 2 + locContentSizeHeight - lineHeight * locStrLen;
+ else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
+ yOffset = (lineHeight - transformTop * 2) / 2 + (locContentSizeHeight - lineHeight * locStrLen) / 2;
+
+ for (var i = 0; i < locStrLen; i++) {
+ var tmpOffsetY = -locContentSizeHeight + (lineHeight * i + transformTop) + yOffset;
+ OffsetYArray.push(tmpOffsetY);
+ }
+ } else {
+ if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) {
+ //do nothing
+ } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) {
+ yOffset -= locContentSizeHeight;
+ } else {
+ yOffset -= locContentSizeHeight * 0.5;
+ }
+ OffsetYArray.push(yOffset);
+ }
+ var tmpStatus = {
+ contextTransform: cc.p(dx, dy),
+ xOffset: xOffset,
+ OffsetYArray: OffsetYArray
+ };
+ this._status.push(tmpStatus);
+ };
+
+ proto._drawTTFInCanvas = function (context) {
+ if (!context)
+ return;
+ var locStatus = this._status.pop();
+ context.setTransform(1, 0, 0, 1, locStatus.contextTransform.x, locStatus.contextTransform.y);
+ var xOffset = locStatus.xOffset;
+ var yOffsetArray = locStatus.OffsetYArray;
+ this.drawLabels(context, xOffset, yOffsetArray);
+ };
+
+ proto._checkWarp = function (strArr, i, maxWidth) {
+ var text = strArr[i];
+ var allWidth = this._measure(text);
+ if (allWidth > maxWidth && text.length > 1) {
+
+ var fuzzyLen = text.length * ( maxWidth / allWidth ) | 0;
+ var tmpText = text.substr(fuzzyLen);
+ var width = allWidth - this._measure(tmpText);
+ var sLine;
+ var pushNum = 0;
+
+ //Increased while cycle maximum ceiling. default 100 time
+ var checkWhile = 0;
+
+ //Exceeded the size
+ while (width > maxWidth && checkWhile++ < 100) {
+ fuzzyLen *= maxWidth / width;
+ fuzzyLen = fuzzyLen | 0;
+ tmpText = text.substr(fuzzyLen);
+ width = allWidth - this._measure(tmpText);
+ }
+
+ checkWhile = 0;
+
+ //Find the truncation point
+ while (width < maxWidth && checkWhile++ < 100) {
+ if (tmpText) {
+ var exec = cc.LabelTTF._wordRex.exec(tmpText);
+ pushNum = exec ? exec[0].length : 1;
+ sLine = tmpText;
+ }
+
+ fuzzyLen = fuzzyLen + pushNum;
+ tmpText = text.substr(fuzzyLen);
+ width = allWidth - this._measure(tmpText);
+ }
+
+ fuzzyLen -= pushNum;
+ if (fuzzyLen === 0) {
+ fuzzyLen = 1;
+ sLine = sLine.substr(1);
+ }
+
+ var sText = text.substr(0, fuzzyLen), result;
+
+ //symbol in the first
+ if (cc.LabelTTF.wrapInspection) {
+ if (cc.LabelTTF._symbolRex.test(sLine || tmpText)) {
+ result = cc.LabelTTF._lastWordRex.exec(sText);
+ fuzzyLen -= result ? result[0].length : 0;
+ if (fuzzyLen === 0) fuzzyLen = 1;
+
+ sLine = text.substr(fuzzyLen);
+ sText = text.substr(0, fuzzyLen);
+ }
+ }
+
+ //To judge whether a English words are truncated
+ if (cc.LabelTTF._firsrEnglish.test(sLine)) {
+ result = cc.LabelTTF._lastEnglish.exec(sText);
+ if (result && sText !== result[0]) {
+ fuzzyLen -= result[0].length;
+ sLine = text.substr(fuzzyLen);
+ sText = text.substr(0, fuzzyLen);
+ }
+ }
+
+ strArr[i] = sLine || tmpText;
+ strArr.splice(i, 0, sText);
+ }
+ };
+
+ proto.updateStatus = function () {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+
+ if (locFlag & flags.textDirty)
+ this._updateTexture();
+
+ this.originUpdateStatus();
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+
+ if (locFlag & flags.textDirty)
+ this._updateTexture();
+
+ this._originSyncStatus(parentCmd);
+
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL || locFlag & flags.transformDirty)
+ this.transform(parentCmd);
+ };
+
+ proto.drawLabels = function (context, xOffset, yOffsetArray) {
+ var node = this._node;
+ //shadow style setup
+ if (node._shadowEnabled) {
+ var locShadowOffset = node._shadowOffset;
+ context.shadowColor = this._shadowColorStr;
+ context.shadowOffsetX = locShadowOffset.x;
+ context.shadowOffsetY = -locShadowOffset.y;
+ context.shadowBlur = node._shadowBlur;
+ }
+
+ var locHAlignment = node._hAlignment,
+ locVAlignment = node._vAlignment,
+ locStrokeSize = node._strokeSize;
+
+ //this is fillText for canvas
+ if (context.font !== this._fontStyleStr)
+ context.font = this._fontStyleStr;
+ context.fillStyle = this._fillColorStr;
+
+ //stroke style setup
+ var locStrokeEnabled = node._strokeEnabled;
+ if (locStrokeEnabled) {
+ context.lineWidth = locStrokeSize * 2;
+ context.strokeStyle = this._strokeColorStr;
+ }
+
+ context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment];
+ context.textAlign = cc.LabelTTF._textAlign[locHAlignment];
+
+ var locStrLen = this._strings.length;
+ for (var i = 0; i < locStrLen; i++) {
+ var line = this._strings[i];
+ if (locStrokeEnabled) {
+ context.lineJoin = 'round';
+ context.strokeText(line, xOffset, yOffsetArray[i]);
+ }
+ context.fillText(line, xOffset, yOffsetArray[i]);
+ }
+ cc.g_NumberOfDraws++;
+ };
+})();
+
+(function () {
+ cc.LabelTTF.CacheRenderCmd = function () {
+ this._labelCmdCtor();
+ var locCanvas = this._labelCanvas = document.createElement("canvas");
+ locCanvas.width = 1;
+ locCanvas.height = 1;
+ this._labelContext = locCanvas.getContext("2d");
+ };
+
+ cc.LabelTTF.CacheRenderCmd.prototype = Object.create(cc.LabelTTF.RenderCmd.prototype);
+ cc.inject(cc.LabelTTF.RenderCmd.prototype, cc.LabelTTF.CacheRenderCmd.prototype);
+
+ var proto = cc.LabelTTF.CacheRenderCmd.prototype;
+ proto.constructor = cc.LabelTTF.CacheRenderCmd;
+ proto._cacheCmdCtor = cc.LabelTTF.CacheRenderCmd;
+
+ proto._updateTexture = function () {
+ this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.textDirty ^ this._dirtyFlag;
+ var node = this._node;
+ node._needUpdateTexture = false;
+ var locContentSize = node._contentSize;
+ this._updateTTF();
+ var width = locContentSize.width, height = locContentSize.height;
+
+ var locContext = this._labelContext, locLabelCanvas = this._labelCanvas;
+
+ if (!node._texture) {
+ var labelTexture = new cc.Texture2D();
+ labelTexture.initWithElement(this._labelCanvas);
+ node.setTexture(labelTexture);
+ }
+
+ if (node._string.length === 0) {
+ locLabelCanvas.width = 1;
+ locLabelCanvas.height = locContentSize.height || 1;
+ if (node._texture) {
+ node._texture._htmlElementObj = this._labelCanvas;
+ node._texture.handleLoadedTexture();
+ }
+ node.setTextureRect(cc.rect(0, 0, 1, locContentSize.height));
+ return true;
+ }
+
+ //set size for labelCanvas
+ locContext.font = this._fontStyleStr;
+
+ var flag = locLabelCanvas.width === width && locLabelCanvas.height === height;
+ locLabelCanvas.width = width;
+ locLabelCanvas.height = height;
+ if (flag) locContext.clearRect(0, 0, width, height);
+ this._saveStatus();
+ this._drawTTFInCanvas(locContext);
+ if (node._texture) {
+ node._texture._htmlElementObj = this._labelCanvas;
+ node._texture.handleLoadedTexture();
+ }
+ node.setTextureRect(cc.rect(0, 0, width, height));
+ return true;
+ };
+
+ proto._measureConfig = function () {
+ this._labelContext.font = this._fontStyleStr;
+ };
+
+ proto._measure = function (text) {
+ if (text) {
+ return this._labelContext.measureText(text).width;
+ } else {
+ return 0;
+ }
+ };
+
+})();
+
+(function () {
+ cc.LabelTTF.CacheCanvasRenderCmd = function (renderable) {
+ this._spriteCmdCtor(renderable);
+ this._cacheCmdCtor();
+ };
+
+ var proto = cc.LabelTTF.CacheCanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
+ cc.inject(cc.LabelTTF.CacheRenderCmd.prototype, proto);
+ proto.constructor = cc.LabelTTF.CacheCanvasRenderCmd;
+})();
+
+(function () {
+ cc.LabelTTF.CanvasRenderCmd = function (renderable) {
+ this._spriteCmdCtor(renderable);
+ this._labelCmdCtor();
+ };
+
+ cc.LabelTTF.CanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
+ cc.inject(cc.LabelTTF.RenderCmd.prototype, cc.LabelTTF.CanvasRenderCmd.prototype);
+
+ var proto = cc.LabelTTF.CanvasRenderCmd.prototype;
+ proto.constructor = cc.LabelTTF.CanvasRenderCmd;
+
+ proto._measureConfig = function () {
+ };
+
+ proto._measure = function (text) {
+ if(text) {
+ var context = cc._renderContext.getContext();
+ context.font = this._fontStyleStr;
+ return context.measureText(text).width;
+ } else {
+ return 0;
+ }
+ };
+
+ proto._updateTexture = function () {
+ this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.textDirty ^ this._dirtyFlag;
+ var node = this._node;
+ var locContentSize = node._contentSize;
+ this._updateTTF();
+ var width = locContentSize.width, height = locContentSize.height;
+ if (node._string.length === 0) {
+ node.setTextureRect(cc.rect(0, 0, 1, locContentSize.height));
+ return true;
+ }
+ this._saveStatus();
+ node.setTextureRect(cc.rect(0, 0, width, height));
+ return true;
+ };
+
+ proto.rendering = function (ctx) {
+ var scaleX = cc.view.getScaleX(),
+ scaleY = cc.view.getScaleY();
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+ if (!context)
+ return;
+ var node = this._node;
+ wrapper.computeRealOffsetY();
+ if (this._status.length <= 0)
+ return;
+ var locIndex = (this._renderingIndex >= this._status.length) ? this._renderingIndex - this._status.length : this._renderingIndex;
+ var status = this._status[locIndex];
+ this._renderingIndex = locIndex + 1;
+
+ var locHeight = node._rect.height,
+ locX = node._offsetPosition.x,
+ locY = -node._offsetPosition.y - locHeight;
+
+ var alpha = (this._displayedOpacity / 255);
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ wrapper.setCompositeOperation(this._blendFuncStr);
+ wrapper.setGlobalAlpha(alpha);
+
+ wrapper.save();
+
+ if (node._flippedX) {
+ locX = -locX - node._rect.width;
+ context.scale(-1, 1);
+ }
+ if (node._flippedY) {
+ locY = node._offsetPosition.y;
+ context.scale(1, -1);
+ }
+
+ var xOffset = status.xOffset + status.contextTransform.x + locX * scaleX;
+ var yOffsetArray = [];
+
+ var locStrLen = this._strings.length;
+ for (var i = 0; i < locStrLen; i++)
+ yOffsetArray.push(status.OffsetYArray[i] + status.contextTransform.y + locY * scaleY);
+
+ this.drawLabels(context, xOffset, yOffsetArray);
+ wrapper.restore();
+ };
+})();
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UISwitch.js b/cocos2d/core/labelttf/CCLabelTTFWebGLRenderCmd.js
similarity index 68%
rename from extensions/CocoStudio/GUI/UIWidgets/UISwitch.js
rename to cocos2d/core/labelttf/CCLabelTTFWebGLRenderCmd.js
index b6da4524b4..e1e8411e58 100644
--- a/extensions/CocoStudio/GUI/UIWidgets/UISwitch.js
+++ b/cocos2d/core/labelttf/CCLabelTTFWebGLRenderCmd.js
@@ -1,5 +1,5 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,6 +22,16 @@
THE SOFTWARE.
****************************************************************************/
-cc.UISwitch = cc.UIWidget.extend({
+// ----------------------------------- LabelTTF WebGL render cmd ----------------------------
+(function () {
+ cc.LabelTTF.WebGLRenderCmd = function (renderable) {
+ this._spriteCmdCtor(renderable);
+ this._cacheCmdCtor();
+ };
+ var proto = cc.LabelTTF.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
-});
\ No newline at end of file
+ cc.inject(cc.LabelTTF.CacheRenderCmd.prototype, proto);
+ proto.constructor = cc.LabelTTF.WebGLRenderCmd;
+ proto._updateColor = function () {
+ };
+})();
diff --git a/cocos2d/core/labelttf/LabelTTFPropertyDefine.js b/cocos2d/core/labelttf/LabelTTFPropertyDefine.js
new file mode 100644
index 0000000000..71ff3a964a
--- /dev/null
+++ b/cocos2d/core/labelttf/LabelTTFPropertyDefine.js
@@ -0,0 +1,88 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+
+cc._tmp.PrototypeLabelTTF = function () {
+ var _p = cc.LabelTTF.prototype;
+
+ // Override properties
+ cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
+ cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
+
+ // Extended properties
+ /** @expose */
+ _p.string;
+ cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
+ /** @expose */
+ _p.textAlign;
+ cc.defineGetterSetter(_p, "textAlign", _p.getHorizontalAlignment, _p.setHorizontalAlignment);
+ /** @expose */
+ _p.verticalAlign;
+ cc.defineGetterSetter(_p, "verticalAlign", _p.getVerticalAlignment, _p.setVerticalAlignment);
+ /** @expose */
+ _p.fontSize;
+ cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
+ /** @expose */
+ _p.fontName;
+ cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
+ /** @expose */
+ _p.font;
+ cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
+ /** @expose */
+ _p.boundingSize;
+ //cc.defineGetterSetter(_p, "boundingSize", _p.getDimensions, _p.setDimensions);
+ /** @expose */
+ _p.boundingWidth;
+ cc.defineGetterSetter(_p, "boundingWidth", _p._getBoundingWidth, _p._setBoundingWidth);
+ /** @expose */
+ _p.boundingHeight;
+ cc.defineGetterSetter(_p, "boundingHeight", _p._getBoundingHeight, _p._setBoundingHeight);
+ /** @expose */
+ _p.fillStyle;
+ cc.defineGetterSetter(_p, "fillStyle", _p._getFillStyle, _p.setFontFillColor);
+ /** @expose */
+ _p.strokeStyle;
+ cc.defineGetterSetter(_p, "strokeStyle", _p._getStrokeStyle, _p._setStrokeStyle);
+ /** @expose */
+ _p.lineWidth;
+ cc.defineGetterSetter(_p, "lineWidth", _p._getLineWidth, _p._setLineWidth);
+ /** @expose */
+ _p.shadowOffset;
+ //cc.defineGetterSetter(_p, "shadowOffset", _p._getShadowOffset, _p._setShadowOffset);
+ /** @expose */
+ _p.shadowOffsetX;
+ cc.defineGetterSetter(_p, "shadowOffsetX", _p._getShadowOffsetX, _p._setShadowOffsetX);
+ /** @expose */
+ _p.shadowOffsetY;
+ cc.defineGetterSetter(_p, "shadowOffsetY", _p._getShadowOffsetY, _p._setShadowOffsetY);
+ /** @expose */
+ _p.shadowOpacity;
+ cc.defineGetterSetter(_p, "shadowOpacity", _p._getShadowOpacity, _p._setShadowOpacity);
+ /** @expose */
+ _p.shadowBlur;
+ cc.defineGetterSetter(_p, "shadowBlur", _p._getShadowBlur, _p._setShadowBlur);
+
+};
\ No newline at end of file
diff --git a/cocos2d/core/layers/CCLayer.js b/cocos2d/core/layers/CCLayer.js
new file mode 100644
index 0000000000..c752ad814f
--- /dev/null
+++ b/cocos2d/core/layers/CCLayer.js
@@ -0,0 +1,782 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/** cc.Layer is a subclass of cc.Node that implements the TouchEventsDelegate protocol.
+ * All features from cc.Node are valid, plus the bake feature: Baked layer can cache a static layer to improve performance
+ * @class
+ * @extends cc.Node
+ */
+cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{
+ _className: "Layer",
+
+ /**
+ * Constructor of cc.Layer, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ */
+ ctor: function () {
+ cc.Node.prototype.ctor.call(this);
+ this._ignoreAnchorPointForPosition = true;
+ this.setAnchorPoint(0.5, 0.5);
+ this.setContentSize(cc.winSize);
+ this._cascadeColorEnabled = false;
+ this._cascadeOpacityEnabled = false;
+ },
+
+ /**
+ * Sets the layer to cache all of children to a bake sprite, and draw itself by bake sprite. recommend using it in UI.
+ * This is useful only in html5 engine
+ * @function
+ * @see cc.Layer#unbake
+ */
+ bake: function () {
+ this._renderCmd.bake();
+ },
+
+ /**
+ * Cancel the layer to cache all of children to a bake sprite.
+ * This is useful only in html5 engine
+ * @function
+ * @see cc.Layer#bake
+ */
+ unbake: function () {
+ this._renderCmd.unbake();
+ },
+
+ /**
+ * Determines if the layer is baked.
+ * @function
+ * @returns {boolean}
+ * @see cc.Layer#bake and cc.Layer#unbake
+ */
+ isBaked: function () {
+ return this._renderCmd._isBaked;
+ },
+
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ var renderer = cc.renderer;
+ cmd.visit(parentCmd);
+
+ if (cmd._isBaked) {
+ renderer.pushRenderCommand(cmd);
+ cmd._bakeSprite.visit(this);
+ }
+ else {
+ var i, children = this._children, len = children.length, child;
+ if (len > 0) {
+ if (this._reorderChildDirty) {
+ this.sortAllChildren();
+ }
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0) {
+ child.visit(this);
+ }
+ else {
+ break;
+ }
+ }
+
+ renderer.pushRenderCommand(cmd);
+ for (; i < len; i++) {
+ children[i].visit(this);
+ }
+ } else {
+ renderer.pushRenderCommand(cmd);
+ }
+ }
+ cmd._dirtyFlag = 0;
+ },
+
+ addChild: function (child, localZOrder, tag) {
+ cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
+ this._renderCmd._bakeForAddChild(child);
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.Layer.CanvasRenderCmd(this);
+ else
+ return new cc.Layer.WebGLRenderCmd(this);
+ }
+});
+
+/**
+ * Creates a layer
+ * @deprecated since v3.0, please use the new construction instead
+ * @see cc.Layer
+ * @return {cc.Layer|Null}
+ */
+cc.Layer.create = function () {
+ return new cc.Layer();
+};
+
+/**
+ *
+ * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.
+ * All features from CCLayer are valid, plus the following new features:
+ * - opacity
+ * - RGB colors
+ * @class
+ * @extends cc.Layer
+ *
+ * @param {cc.Color} [color=] The color of the layer
+ * @param {Number} [width=] The width of the layer
+ * @param {Number} [height=] The height of the layer
+ *
+ * @example
+ * // Example
+ * //Create a yellow color layer as background
+ * var yellowBackground = new cc.LayerColor(cc.color(255,255,0,255));
+ * //If you didn't pass in width and height, it defaults to the same size as the canvas
+ *
+ * //create a yellow box, 200 by 200 in size
+ * var yellowBox = new cc.LayerColor(cc.color(255,255,0,255), 200, 200);
+ */
+cc.LayerColor = cc.Layer.extend(/** @lends cc.LayerColor# */{
+ _blendFunc: null,
+ _className: "LayerColor",
+
+ /**
+ * Returns the blend function
+ * @return {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ return this._blendFunc;
+ },
+
+ /**
+ * Changes width and height
+ * @deprecated since v3.0 please use setContentSize instead
+ * @see cc.Node#setContentSize
+ * @param {Number} w width
+ * @param {Number} h height
+ */
+ changeWidthAndHeight: function (w, h) {
+ this.width = w;
+ this.height = h;
+ },
+
+ /**
+ * Changes width in Points
+ * @deprecated since v3.0 please use setContentSize instead
+ * @see cc.Node#setContentSize
+ * @param {Number} w width
+ */
+ changeWidth: function (w) {
+ this.width = w;
+ },
+
+ /**
+ * change height in Points
+ * @deprecated since v3.0 please use setContentSize instead
+ * @see cc.Node#setContentSize
+ * @param {Number} h height
+ */
+ changeHeight: function (h) {
+ this.height = h;
+ },
+
+ setOpacityModifyRGB: function (value) {
+ },
+
+ isOpacityModifyRGB: function () {
+ return false;
+ },
+
+ /**
+ * Constructor of cc.LayerColor
+ * @function
+ * @param {cc.Color} [color=]
+ * @param {Number} [width=]
+ * @param {Number} [height=]
+ */
+ ctor: function (color, width, height) {
+ cc.Layer.prototype.ctor.call(this);
+ this._blendFunc = cc.BlendFunc._alphaNonPremultiplied();
+ cc.LayerColor.prototype.init.call(this, color, width, height);
+ },
+
+ /**
+ * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer
+ * @param {cc.Color} [color=]
+ * @param {Number} [width=]
+ * @param {Number} [height=]
+ * @return {Boolean}
+ */
+ init: function (color, width, height) {
+ var winSize = cc.director.getWinSize();
+ color = color || cc.color(0, 0, 0, 255);
+ width = width === undefined ? winSize.width : width;
+ height = height === undefined ? winSize.height : height;
+
+ var locRealColor = this._realColor;
+ locRealColor.r = color.r;
+ locRealColor.g = color.g;
+ locRealColor.b = color.b;
+ this._realOpacity = color.a;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty | cc.Node._dirtyFlags.opacityDirty);
+
+ cc.LayerColor.prototype.setContentSize.call(this, width, height);
+ return true;
+ },
+
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ var renderer = cc.renderer;
+ cmd.visit(parentCmd);
+
+ if (cmd._isBaked) {
+ renderer.pushRenderCommand(cmd._bakeRenderCmd);
+ //the bakeSprite is drawing
+ cmd._bakeSprite._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ cmd._bakeSprite.visit(this);
+ }
+ else {
+ var i, children = this._children, len = children.length;
+ if (len > 0) {
+ if (this._reorderChildDirty) {
+ this.sortAllChildren();
+ }
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0) {
+ child.visit(this);
+ }
+ else {
+ break;
+ }
+ }
+
+ renderer.pushRenderCommand(cmd);
+ for (; i < len; i++) {
+ children[i].visit(this);
+ }
+ } else {
+ renderer.pushRenderCommand(cmd);
+ }
+ }
+
+ cmd._dirtyFlag = 0;
+ },
+
+ /**
+ * Sets the blend func, you can pass either a cc.BlendFunc object or source and destination value separately
+ * @param {Number|cc.BlendFunc} src
+ * @param {Number} [dst]
+ */
+ setBlendFunc: function (src, dst) {
+ var locBlendFunc = this._blendFunc;
+ if (dst === undefined) {
+ locBlendFunc.src = src.src;
+ locBlendFunc.dst = src.dst;
+ } else {
+ locBlendFunc.src = src;
+ locBlendFunc.dst = dst;
+ }
+ this._renderCmd.updateBlendFunc(locBlendFunc);
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.LayerColor.CanvasRenderCmd(this);
+ else
+ return new cc.LayerColor.WebGLRenderCmd(this);
+ }
+});
+
+/**
+ * Creates a cc.Layer with color, width and height in Points
+ * @deprecated since v3.0 please use the new construction instead
+ * @see cc.LayerColor
+ * @param {cc.Color} color
+ * @param {Number|Null} [width=]
+ * @param {Number|Null} [height=]
+ * @return {cc.LayerColor}
+ */
+cc.LayerColor.create = function (color, width, height) {
+ return new cc.LayerColor(color, width, height);
+};
+
+//LayerColor - Getter Setter
+(function () {
+ var proto = cc.LayerColor.prototype;
+ cc.defineGetterSetter(proto, "width", proto._getWidth, proto._setWidth);
+ cc.defineGetterSetter(proto, "height", proto._getHeight, proto._setHeight);
+})();
+
+/**
+ *
+ * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.
+ *
+ * All features from cc.LayerColor are valid, plus the following new features:
+ *
direction
+ * final color
+ * interpolation mode
+ *
+ * Color is interpolated between the startColor and endColor along the given
+ * vector (starting at the origin, ending at the terminus). If no vector is
+ * supplied, it defaults to (0, -1) -- a fade from top to bottom.
+ *
+ * If 'compressedInterpolation' is disabled, you will not see either the start or end color for
+ * non-cardinal vectors; a smooth gradient implying both end points will be still
+ * be drawn, however.
+ *
+ * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient.
+ *
+ * @class
+ * @extends cc.LayerColor
+ *
+ * @param {cc.Color} start Starting color
+ * @param {cc.Color} end Ending color
+ * @param {cc.Point} [v=cc.p(0, -1)] A vector defines the gradient direction, default direction is from top to bottom
+ *
+ * @property {cc.Color} startColor - Start color of the color gradient
+ * @property {cc.Color} endColor - End color of the color gradient
+ * @property {Number} startOpacity - Start opacity of the color gradient
+ * @property {Number} endOpacity - End opacity of the color gradient
+ * @property {Number} vector - Direction vector of the color gradient
+ * @property {Number} compressedInterpolation - Indicate whether or not the interpolation will be compressed
+ */
+cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
+ _endColor: null,
+ _startOpacity: 255,
+ _endOpacity: 255,
+ _alongVector: null,
+ _compressedInterpolation: false,
+ _className: "LayerGradient",
+ _colorStops: [],
+
+ /**
+ * Constructor of cc.LayerGradient
+ * @param {cc.Color} start
+ * @param {cc.Color} end
+ * @param {cc.Point} [v=cc.p(0, -1)]
+ * @param {Array|Null} stops
+ *
+ * @example Using ColorStops argument:
+ * //startColor & endColor are for default and backward compatibility
+ * var layerGradient = new cc.LayerGradient(cc.color.RED, new cc.Color(255,0,0,0), cc.p(0, -1),
+ * [{p:0, color: cc.color.RED},
+ * {p:.5, color: new cc.Color(0,0,0,0)},
+ * {p:1, color: cc.color.RED}]);
+ * //where p = A value between 0.0 and 1.0 that represents the position between start and end in a gradient
+ *
+ */
+ ctor: function (start, end, v, stops) {
+ cc.LayerColor.prototype.ctor.call(this);
+ this._endColor = cc.color(0, 0, 0, 255);
+ this._alongVector = cc.p(0, -1);
+ this._startOpacity = 255;
+ this._endOpacity = 255;
+
+ if (stops && stops instanceof Array) {
+ this._colorStops = stops;
+ stops.splice(0, 0, {p: 0, color: start || cc.color.BLACK});
+ stops.push({p: 1, color: end || cc.color.BLACK});
+ } else
+ this._colorStops = [{p: 0, color: start || cc.color.BLACK}, {p: 1, color: end || cc.color.BLACK}];
+
+ cc.LayerGradient.prototype.init.call(this, start, end, v, stops);
+ },
+
+ /**
+ * Initialization of the layer, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer
+ * @param {cc.Color} start starting color
+ * @param {cc.Color} end
+ * @param {cc.Point|Null} v
+ * @param {Array|Null} stops
+ * @return {Boolean}
+ */
+ init: function (start, end, v, stops) {
+ start = start || cc.color(0, 0, 0, 255);
+ end = end || cc.color(0, 0, 0, 255);
+ v = v || cc.p(0, -1);
+ var _t = this;
+
+ // Initializes the CCLayer with a gradient between start and end in the direction of v.
+ var locEndColor = _t._endColor;
+ _t._startOpacity = start.a;
+
+ locEndColor.r = end.r;
+ locEndColor.g = end.g;
+ locEndColor.b = end.b;
+ _t._endOpacity = end.a;
+
+ _t._alongVector = v;
+ _t._compressedInterpolation = true;
+
+ cc.LayerColor.prototype.init.call(_t, cc.color(start.r, start.g, start.b, 255));
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty | cc.Node._dirtyFlags.opacityDirty | cc.Node._dirtyFlags.gradientDirty);
+ return true;
+ },
+
+ /**
+ * Sets the untransformed size of the LayerGradient.
+ * @param {cc.Size|Number} size The untransformed size of the LayerGradient or The untransformed size's width of the LayerGradient.
+ * @param {Number} [height] The untransformed size's height of the LayerGradient.
+ */
+ setContentSize: function (size, height) {
+ cc.LayerColor.prototype.setContentSize.call(this, size, height);
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
+ },
+
+ _setWidth: function (width) {
+ cc.LayerColor.prototype._setWidth.call(this, width);
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
+ },
+ _setHeight: function (height) {
+ cc.LayerColor.prototype._setHeight.call(this, height);
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
+ },
+
+ /**
+ * Returns the starting color
+ * @return {cc.Color}
+ */
+ getStartColor: function () {
+ return cc.color(this._realColor);
+ },
+
+ /**
+ * Sets the starting color
+ * @param {cc.Color} color
+ * @example
+ * // Example
+ * myGradientLayer.setStartColor(cc.color(255,0,0));
+ * //set the starting gradient to red
+ */
+ setStartColor: function (color) {
+ this.color = color;
+ //update the color stops
+ var stops = this._colorStops;
+ if (stops && stops.length > 0) {
+ var selColor = stops[0].color;
+ selColor.r = color.r;
+ selColor.g = color.g;
+ selColor.b = color.b;
+ }
+ },
+
+ /**
+ * Sets the end gradient color
+ * @param {cc.Color} color
+ * @example
+ * // Example
+ * myGradientLayer.setEndColor(cc.color(255,0,0));
+ * //set the ending gradient to red
+ */
+ setEndColor: function (color) {
+ var locColor = this._endColor;
+ locColor.r = color.r;
+ locColor.g = color.g;
+ locColor.b = color.b;
+ //update the color stops
+ var stops = this._colorStops;
+ if (stops && stops.length > 0) {
+ var selColor = stops[stops.length - 1].color;
+ selColor.r = color.r;
+ selColor.g = color.g;
+ selColor.b = color.b;
+ }
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ },
+
+ /**
+ * Returns the end color
+ * @return {cc.Color}
+ */
+ getEndColor: function () {
+ return cc.color(this._endColor);
+ },
+
+ /**
+ * Sets starting gradient opacity
+ * @param {Number} o from 0 to 255, 0 is transparent
+ */
+ setStartOpacity: function (o) {
+ this._startOpacity = o;
+ //update the color stops
+ var stops = this._colorStops;
+ if (stops && stops.length > 0)
+ stops[0].color.a = o;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
+ },
+
+ /**
+ * Returns the starting gradient opacity
+ * @return {Number}
+ */
+ getStartOpacity: function () {
+ return this._startOpacity;
+ },
+
+ /**
+ * Sets the end gradient opacity
+ * @param {Number} o
+ */
+ setEndOpacity: function (o) {
+ this._endOpacity = o;
+ var stops = this._colorStops;
+ if (stops && stops.length > 0)
+ stops[stops.length - 1].color.a = o;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
+ },
+
+ /**
+ * Returns the end gradient opacity
+ * @return {Number}
+ */
+ getEndOpacity: function () {
+ return this._endOpacity;
+ },
+
+ /**
+ * Sets the direction vector of the gradient
+ * @param {cc.Point} Var
+ */
+ setVector: function (Var) {
+ this._alongVector.x = Var.x;
+ this._alongVector.y = Var.y;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
+ },
+
+ /**
+ * Returns the direction vector of the gradient
+ * @return {cc.Point}
+ */
+ getVector: function () {
+ return cc.p(this._alongVector.x, this._alongVector.y);
+ },
+
+ /**
+ * Returns whether compressed interpolation is enabled
+ * @return {Boolean}
+ */
+ isCompressedInterpolation: function () {
+ return this._compressedInterpolation;
+ },
+
+ /**
+ * Sets whether compressed interpolation is enabled
+ * @param {Boolean} compress
+ */
+ setCompressedInterpolation: function (compress) {
+ this._compressedInterpolation = compress;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.gradientDirty);
+ },
+
+ /**
+ * Return an array of Object representing a colorStop for the gradient, if no stops was specified
+ * start & endColor will be provided as default values
+ * @example
+ * [{p: 0, color: cc.color.RED},{p: 1, color: cc.color.RED},...]
+ * @returns {Array}
+ */
+ getColorStops: function () {
+ return this._colorStops;
+ },
+ /**
+ * Set the colorStops to create the gradient using multiple point & color
+ *
+ * @param colorStops
+ *
+ * @example
+ * //startColor & endColor are for default and backward compatibility
+ * var layerGradient = new cc.LayerGradient(cc.color.RED, new cc.Color(255,0,0,0), cc.p(0, -1));
+ * layerGradient.setColorStops([{p:0, color: cc.color.RED},
+ * {p:.5, color: new cc.Color(0,0,0,0)},
+ * {p:1, color: cc.color.RED}]);
+ * //where p = A value between 0.0 and 1.0 that represents the position between start and end in a gradient
+ *
+ */
+ setColorStops: function (colorStops) {
+ this._colorStops = colorStops;
+ //todo need update the start color and end color
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty | cc.Node._dirtyFlags.opacityDirty | cc.Node._dirtyFlags.gradientDirty);
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.LayerGradient.CanvasRenderCmd(this);
+ else
+ return new cc.LayerGradient.WebGLRenderCmd(this);
+ }
+});
+
+/**
+ * Creates a gradient layer
+ * @deprecated since v3.0, please use the new construction instead
+ * @see cc.layerGradient
+ * @param {cc.Color} start starting color
+ * @param {cc.Color} end ending color
+ * @param {cc.Point|Null} v
+ * @param {Array|NULL} stops
+ * @return {cc.LayerGradient}
+ */
+cc.LayerGradient.create = function (start, end, v, stops) {
+ return new cc.LayerGradient(start, end, v, stops);
+};
+//LayerGradient - Getter Setter
+(function () {
+ var proto = cc.LayerGradient.prototype;
+ // Extended properties
+ /** @expose */
+ proto.startColor;
+ cc.defineGetterSetter(proto, "startColor", proto.getStartColor, proto.setStartColor);
+ /** @expose */
+ proto.endColor;
+ cc.defineGetterSetter(proto, "endColor", proto.getEndColor, proto.setEndColor);
+ /** @expose */
+ proto.startOpacity;
+ cc.defineGetterSetter(proto, "startOpacity", proto.getStartOpacity, proto.setStartOpacity);
+ /** @expose */
+ proto.endOpacity;
+ cc.defineGetterSetter(proto, "endOpacity", proto.getEndOpacity, proto.setEndOpacity);
+ /** @expose */
+ proto.vector;
+ cc.defineGetterSetter(proto, "vector", proto.getVector, proto.setVector);
+ /** @expose */
+ proto.colorStops;
+ cc.defineGetterSetter(proto, "colorStops", proto.getColorStops, proto.setColorStops);
+})();
+
+/**
+ * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.
+ * Features:
+ * - It supports one or more children
+ * - Only one children will be active a time
+ * @class
+ * @extends cc.Layer
+ * @param {Array} layers an array of cc.Layer
+ * @example
+ * // Example
+ * var multiLayer = new cc.LayerMultiple(layer1, layer2, layer3);//any number of layers
+ */
+cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{
+ _enabledLayer: 0,
+ _layers: null,
+ _className: "LayerMultiplex",
+
+ /**
+ * Constructor of cc.LayerMultiplex
+ * @param {Array} layers an array of cc.Layer
+ */
+ ctor: function (layers) {
+ cc.Layer.prototype.ctor.call(this);
+ if (layers instanceof Array)
+ cc.LayerMultiplex.prototype.initWithLayers.call(this, layers);
+ else
+ cc.LayerMultiplex.prototype.initWithLayers.call(this, Array.prototype.slice.call(arguments));
+ },
+
+ /**
+ * Initialization of the layer multiplex, please do not call this function by yourself, you should pass the parameters to constructor to initialize a layer multiplex
+ * @param {Array} layers an array of cc.Layer
+ * @return {Boolean}
+ */
+ initWithLayers: function (layers) {
+ if ((layers.length > 0) && (layers[layers.length - 1] == null))
+ cc.log(cc._LogInfos.LayerMultiplex_initWithLayers);
+
+ this._layers = layers;
+ this._enabledLayer = 0;
+ this.addChild(this._layers[this._enabledLayer]);
+ return true;
+ },
+
+ /**
+ * Switches to a certain layer indexed by n.
+ * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
+ * @param {Number} n the layer index to switch to
+ */
+ switchTo: function (n) {
+ if (n >= this._layers.length) {
+ cc.log(cc._LogInfos.LayerMultiplex_switchTo);
+ return;
+ }
+
+ this.removeChild(this._layers[this._enabledLayer], true);
+ this._enabledLayer = n;
+ this.addChild(this._layers[n]);
+ },
+
+ /**
+ * Release the current layer and switches to another layer indexed by n.
+ * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
+ * @param {Number} n the layer index to switch to
+ */
+ switchToAndReleaseMe: function (n) {
+ if (n >= this._layers.length) {
+ cc.log(cc._LogInfos.LayerMultiplex_switchToAndReleaseMe);
+ return;
+ }
+
+ this.removeChild(this._layers[this._enabledLayer], true);
+
+ //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]];
+ this._layers[this._enabledLayer] = null;
+ this._enabledLayer = n;
+ this.addChild(this._layers[n]);
+ },
+
+ /**
+ * Add a layer to the multiplex layers list
+ * @param {cc.Layer} layer
+ */
+ addLayer: function (layer) {
+ if (!layer) {
+ cc.log(cc._LogInfos.LayerMultiplex_addLayer);
+ return;
+ }
+ this._layers.push(layer);
+ }
+});
+
+/**
+ * Creates a cc.LayerMultiplex with one or more layers using a variable argument list.
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.LayerMultiplex
+ * @return {cc.LayerMultiplex|Null}
+ */
+cc.LayerMultiplex.create = function (/*Multiple Arguments*/) {
+ return new cc.LayerMultiplex(Array.prototype.slice.call(arguments));
+};
diff --git a/cocos2d/core/layers/CCLayerCanvasRenderCmd.js b/cocos2d/core/layers/CCLayerCanvasRenderCmd.js
new file mode 100644
index 0000000000..3149895ee3
--- /dev/null
+++ b/cocos2d/core/layers/CCLayerCanvasRenderCmd.js
@@ -0,0 +1,419 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//-----------------------//
+// 1. cc.Layer //
+// 2. cc.LayerColor //
+// 3. cc.LayerGradient //
+//-----------------------//
+
+/**
+ * cc.Layer's rendering objects of Canvas
+ */
+(function () {
+ //Layer's canvas render command
+ cc.Layer.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._isBaked = false;
+ this._bakeSprite = null;
+ this._canUseDirtyRegion = true;
+ this._updateCache = 2; // 2: Updated child visit 1: Rendering 0: Nothing to do
+ };
+
+ var proto = cc.Layer.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.Layer.CanvasRenderCmd;
+ proto._layerCmdCtor = cc.Layer.CanvasRenderCmd;
+
+ proto._setCacheDirty = function (child) {
+ if (child && this._updateCache === 0)
+ this._updateCache = 2;
+ if (this._cacheDirty === false) {
+ this._cacheDirty = true;
+ var cachedP = this._cachedParent;
+ cachedP && cachedP !== this && cachedP._setNodeDirtyForCache && cachedP._setNodeDirtyForCache();
+ }
+ };
+
+ proto.updateStatus = function () {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ if (locFlag & flags.orderDirty) {
+ this._cacheDirty = true;
+ if (this._updateCache === 0)
+ this._updateCache = 2;
+ this._dirtyFlag &= ~flags.orderDirty;
+ }
+
+ this.originUpdateStatus();
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ // if (locFlag & flags.orderDirty) {
+ if (this._isBaked || locFlag & flags.orderDirty) {
+ this._cacheDirty = true;
+ if (this._updateCache === 0)
+ this._updateCache = 2;
+ this._dirtyFlag &= ~flags.orderDirty;
+ }
+ this._originSyncStatus(parentCmd);
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ if (!this._worldTransform) {
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ }
+ var wt = this._worldTransform;
+ var a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty;
+ this.originTransform(parentCmd, recursive);
+ if (( wt.a !== a || wt.b !== b || wt.c !== c || wt.d !== d ) && this._updateCache === 0)
+ this._updateCache = 2;
+ };
+
+ proto.bake = function () {
+ if (!this._isBaked) {
+ this._needDraw = true;
+ cc.renderer.childrenOrderDirty = true;
+ //limit: 1. its children's blendfunc are invalid.
+ this._isBaked = this._cacheDirty = true;
+ if (this._updateCache === 0)
+ this._updateCache = 2;
+
+ var children = this._node._children;
+ for (var i = 0, len = children.length; i < len; i++)
+ children[i]._renderCmd._setCachedParent(this);
+
+ if (!this._bakeSprite) {
+ this._bakeSprite = new cc.BakeSprite();
+ this._bakeSprite.setAnchorPoint(0, 0);
+ }
+ }
+ };
+
+ proto.unbake = function () {
+ if (this._isBaked) {
+ cc.renderer.childrenOrderDirty = true;
+ this._needDraw = false;
+ this._isBaked = false;
+ this._cacheDirty = true;
+ if (this._updateCache === 0)
+ this._updateCache = 2;
+
+ var children = this._node._children;
+ for (var i = 0, len = children.length; i < len; i++)
+ children[i]._renderCmd._setCachedParent(null);
+ }
+ };
+
+ proto.isBaked = function () {
+ return this._isBaked;
+ };
+
+ proto.rendering = function () {
+ if (this._cacheDirty) {
+ var node = this._node;
+ var children = node._children, locBakeSprite = this._bakeSprite;
+
+ //compute the bounding box of the bake layer.
+ this.transform(this.getParentRenderCmd(), true);
+
+ var boundingBox = this._getBoundingBoxForBake();
+ boundingBox.width = 0 | (boundingBox.width + 0.5);
+ boundingBox.height = 0 | (boundingBox.height + 0.5);
+
+ var bakeContext = locBakeSprite.getCacheContext();
+ var ctx = bakeContext.getContext();
+
+ locBakeSprite.setPosition(boundingBox.x, boundingBox.y);
+
+ if (this._updateCache > 0) {
+ locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height);
+ bakeContext.setOffset(0 - boundingBox.x, ctx.canvas.height - boundingBox.height + boundingBox.y);
+ //visit for canvas
+ node.sortAllChildren();
+ cc.renderer._turnToCacheMode(this.__instanceId);
+ for (var i = 0, len = children.length; i < len; i++) {
+ children[i].visit(this);
+ }
+ cc.renderer._renderingToCacheCanvas(bakeContext, this.__instanceId);
+ locBakeSprite.transform(); //because bake sprite's position was changed at rendering.
+ this._updateCache--;
+ }
+
+ this._cacheDirty = false;
+ }
+ };
+
+ proto._bakeForAddChild = function (child) {
+ if (child._parent === this._node && this._isBaked)
+ child._renderCmd._setCachedParent(this);
+ };
+
+ proto._getBoundingBoxForBake = function () {
+ var rect = null, node = this._node;
+
+ //query child's BoundingBox
+ if (!node._children || node._children.length === 0)
+ return cc.rect(0, 0, 10, 10);
+ var trans = node.getNodeToWorldTransform();
+
+ var locChildren = node._children;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var child = locChildren[i];
+ if (child && child._visible) {
+ if (rect) {
+ var childRect = child._getBoundingBoxToCurrentNode(trans);
+ if (childRect)
+ rect = cc.rectUnion(rect, childRect);
+ } else {
+ rect = child._getBoundingBoxToCurrentNode(trans);
+ }
+ }
+ }
+ return rect;
+ };
+})();
+
+/**
+ * cc.LayerColor's rendering objects of Canvas
+ */
+(function () {
+ //LayerColor's canvas render command
+ cc.LayerColor.CanvasRenderCmd = function (renderable) {
+ this._layerCmdCtor(renderable);
+ this._needDraw = true;
+ this._blendFuncStr = "source-over";
+ this._bakeRenderCmd = new cc.CustomRenderCmd(this, this._bakeRendering);
+ };
+ var proto = cc.LayerColor.CanvasRenderCmd.prototype = Object.create(cc.Layer.CanvasRenderCmd.prototype);
+ proto.constructor = cc.LayerColor.CanvasRenderCmd;
+
+ proto.unbake = function () {
+ cc.Layer.CanvasRenderCmd.prototype.unbake.call(this);
+ this._needDraw = true;
+ };
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext(),
+ node = this._node,
+ curColor = this._displayedColor,
+ opacity = this._displayedOpacity / 255,
+ locWidth = node._contentSize.width,
+ locHeight = node._contentSize.height;
+
+ if (opacity === 0)
+ return;
+
+ wrapper.setCompositeOperation(this._blendFuncStr);
+ wrapper.setGlobalAlpha(opacity);
+ wrapper.setFillStyle("rgba(" + (0 | curColor.r) + "," + (0 | curColor.g) + ","
+ + (0 | curColor.b) + ", 1)"); //TODO: need cache the color string
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ context.fillRect(0, 0, locWidth, -locHeight);
+
+ cc.g_NumberOfDraws++;
+ };
+
+ proto.updateBlendFunc = function (blendFunc) {
+ this._blendFuncStr = cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc(blendFunc);
+ };
+
+ proto._updateSquareVertices =
+ proto._updateSquareVerticesWidth =
+ proto._updateSquareVerticesHeight = function () {};
+
+ proto._bakeRendering = function () {
+ if (this._cacheDirty) {
+ var node = this._node;
+ var locBakeSprite = this._bakeSprite, children = node._children;
+ var i, len = children.length;
+
+ //compute the bounding box of the bake layer.
+ this.transform(this.getParentRenderCmd(), true);
+ //compute the bounding box of the bake layer.
+ var boundingBox = this._getBoundingBoxForBake();
+ boundingBox.width = 0 | (boundingBox.width + 0.5);
+ boundingBox.height = 0 | (boundingBox.height + 0.5);
+
+ var bakeContext = locBakeSprite.getCacheContext();
+ var ctx = bakeContext.getContext();
+
+ locBakeSprite.setPosition(boundingBox.x, boundingBox.y);
+
+ if (this._updateCache > 0) {
+ ctx.fillStyle = bakeContext._currentFillStyle;
+ locBakeSprite.resetCanvasSize(boundingBox.width, boundingBox.height);
+ bakeContext.setOffset(0 - boundingBox.x, ctx.canvas.height - boundingBox.height + boundingBox.y);
+
+ var child;
+ cc.renderer._turnToCacheMode(this.__instanceId);
+ //visit for canvas
+ if (len > 0) {
+ node.sortAllChildren();
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0)
+ child.visit(node);
+ else
+ break;
+ }
+ cc.renderer.pushRenderCommand(this);
+ for (; i < len; i++) {
+ children[i].visit(node);
+ }
+ } else
+ cc.renderer.pushRenderCommand(this);
+ cc.renderer._renderingToCacheCanvas(bakeContext, this.__instanceId);
+ locBakeSprite.transform();
+ this._updateCache--;
+ }
+ this._cacheDirty = false;
+ }
+ };
+
+ proto._getBoundingBoxForBake = function () {
+ var node = this._node;
+ //default size
+ var rect = cc.rect(0, 0, node._contentSize.width, node._contentSize.height);
+ var trans = node.getNodeToWorldTransform();
+ rect = cc.rectApplyAffineTransform(rect, node.getNodeToWorldTransform());
+
+ //query child's BoundingBox
+ if (!node._children || node._children.length === 0)
+ return rect;
+
+ var locChildren = node._children;
+ for (var i = 0; i < locChildren.length; i++) {
+ var child = locChildren[i];
+ if (child && child._visible) {
+ var childRect = child._getBoundingBoxToCurrentNode(trans);
+ rect = cc.rectUnion(rect, childRect);
+ }
+ }
+ return rect;
+ };
+})();
+
+/**
+ * cc.LayerGradient's rendering objects of Canvas
+ */
+(function () {
+ cc.LayerGradient.CanvasRenderCmd = function (renderable) {
+ cc.LayerColor.CanvasRenderCmd.call(this, renderable);
+ this._needDraw = true;
+ this._startPoint = cc.p(0, 0);
+ this._endPoint = cc.p(0, 0);
+ this._startStopStr = null;
+ this._endStopStr = null;
+ };
+ var proto = cc.LayerGradient.CanvasRenderCmd.prototype = Object.create(cc.LayerColor.CanvasRenderCmd.prototype);
+ proto.constructor = cc.LayerGradient.CanvasRenderCmd;
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext(),
+ node = this._node,
+ opacity = this._displayedOpacity / 255;
+
+ if (opacity === 0)
+ return;
+
+ var locWidth = node._contentSize.width, locHeight = node._contentSize.height;
+ wrapper.setCompositeOperation(this._blendFuncStr);
+ wrapper.setGlobalAlpha(opacity);
+ var gradient = context.createLinearGradient(this._startPoint.x, this._startPoint.y, this._endPoint.x, this._endPoint.y);
+
+ if (node._colorStops) { //Should always fall here now
+ for (var i = 0; i < node._colorStops.length; i++) {
+ var stop = node._colorStops[i];
+ gradient.addColorStop(stop.p, this._colorStopsStr[i]);
+ }
+ } else {
+ gradient.addColorStop(0, this._startStopStr);
+ gradient.addColorStop(1, this._endStopStr);
+ }
+
+ wrapper.setFillStyle(gradient);
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ context.fillRect(0, 0, locWidth, -locHeight);
+ cc.g_NumberOfDraws++;
+ };
+
+ proto.updateStatus = function () {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ if (locFlag & flags.gradientDirty) {
+ this._dirtyFlag |= flags.colorDirty;
+ this._dirtyFlag &= ~flags.gradientDirty;
+ }
+
+ this.originUpdateStatus();
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ if (locFlag & flags.gradientDirty) {
+ this._dirtyFlag |= flags.colorDirty;
+ this._dirtyFlag &= ~flags.gradientDirty;
+ }
+
+ this._originSyncStatus(parentCmd);
+ };
+
+ proto._updateColor = function () {
+ var node = this._node;
+ var contentSize = node._contentSize;
+ var tWidth = contentSize.width * 0.5, tHeight = contentSize.height * 0.5;
+
+ //fix the bug of gradient layer
+ var angle = cc.pAngleSigned(cc.p(0, -1), node._alongVector);
+ var p1 = cc.pRotateByAngle(cc.p(0, -1), cc.p(0, 0), angle);
+ var factor = Math.min(Math.abs(1 / p1.x), Math.abs(1 / p1.y));
+
+ this._startPoint.x = tWidth * (-p1.x * factor) + tWidth;
+ this._startPoint.y = tHeight * (p1.y * factor) - tHeight;
+ this._endPoint.x = tWidth * (p1.x * factor) + tWidth;
+ this._endPoint.y = tHeight * (-p1.y * factor) - tHeight;
+
+ var locStartColor = this._displayedColor, locEndColor = node._endColor;
+ var startOpacity = node._startOpacity / 255, endOpacity = node._endOpacity / 255;
+ this._startStopStr = "rgba(" + Math.round(locStartColor.r) + "," + Math.round(locStartColor.g) + ","
+ + Math.round(locStartColor.b) + "," + startOpacity.toFixed(4) + ")";
+ this._endStopStr = "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + ","
+ + Math.round(locEndColor.b) + "," + endOpacity.toFixed(4) + ")";
+
+ if (node._colorStops) {
+ this._startOpacity = 0;
+ this._endOpacity = 0;
+
+ this._colorStopsStr = [];
+ for (var i = 0; i < node._colorStops.length; i++) {
+ var stopColor = node._colorStops[i].color;
+ var stopOpacity = stopColor.a == null ? 1 : stopColor.a / 255;
+ this._colorStopsStr.push("rgba(" + Math.round(stopColor.r) + "," + Math.round(stopColor.g) + ","
+ + Math.round(stopColor.b) + "," + stopOpacity.toFixed(4) + ")");
+ }
+ }
+ };
+})();
diff --git a/cocos2d/core/layers/CCLayerWebGLRenderCmd.js b/cocos2d/core/layers/CCLayerWebGLRenderCmd.js
new file mode 100644
index 0000000000..4acf7f22d6
--- /dev/null
+++ b/cocos2d/core/layers/CCLayerWebGLRenderCmd.js
@@ -0,0 +1,328 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//-----------------------//
+// 1. cc.Layer //
+// 2. cc.LayerColor //
+// 3. cc.LayerGradient //
+//-----------------------//
+
+/**
+ * cc.Layer's rendering objects of WebGL
+ */
+(function () {
+ cc.Layer.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._isBaked = false;
+ };
+
+ var proto = cc.Layer.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.Layer.WebGLRenderCmd;
+ proto._layerCmdCtor = cc.Layer.WebGLRenderCmd;
+
+ proto.bake = function () {
+ };
+
+ proto.unbake = function () {
+ };
+
+ proto._bakeForAddChild = function () {
+ };
+})();
+
+/**
+ * cc.LayerColor's rendering objects of WebGL
+ */
+(function () {
+ var FLOAT_PER_VERTEX = 4;
+
+ cc.LayerColor.WebGLRenderCmd = function (renderable) {
+ this._layerCmdCtor(renderable);
+ this._needDraw = true;
+
+ this._matrix = null;
+
+ this.initData(4);
+ this._color = new Uint32Array(1);
+ this._vertexBuffer = null;
+
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_COLOR);
+ };
+ var proto = cc.LayerColor.WebGLRenderCmd.prototype = Object.create(cc.Layer.WebGLRenderCmd.prototype);
+ proto.constructor = cc.LayerColor.WebGLRenderCmd;
+
+ proto.initData = function (vertexCount) {
+ this._data = new ArrayBuffer(16 * vertexCount);
+ this._positionView = new Float32Array(this._data);
+ this._colorView = new Uint32Array(this._data);
+ this._dataDirty = true;
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+
+ var node = this._node,
+ width = node._contentSize.width,
+ height = node._contentSize.height;
+
+ var pos = this._positionView;
+ pos[FLOAT_PER_VERTEX] = width; // br.x
+ pos[FLOAT_PER_VERTEX * 2 + 1] = height; // tl.y
+ pos[FLOAT_PER_VERTEX * 3] = width; // tr.x
+ pos[FLOAT_PER_VERTEX * 3 + 1] = height; // tr.y
+ pos[2].z =
+ pos[FLOAT_PER_VERTEX + 2] =
+ pos[FLOAT_PER_VERTEX * 2 + 2] =
+ pos[FLOAT_PER_VERTEX * 3 + 2] = node._vertexZ;
+
+ this._dataDirty = true;
+ };
+
+ proto._updateColor = function () {
+ var color = this._displayedColor;
+ this._color[0] = ((this._displayedOpacity << 24) | (color.b << 16) | (color.g << 8) | color.r);
+
+ var colors = this._colorView;
+ for (var i = 0; i < 4; i++) {
+ colors[i * FLOAT_PER_VERTEX + 3] = this._color[0];
+ }
+ this._dataDirty = true;
+ };
+
+ proto.rendering = function (ctx) {
+ var gl = ctx || cc._renderContext;
+ var node = this._node;
+
+ if (!this._matrix) {
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ }
+
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ if (this._dataDirty) {
+ if (!this._vertexBuffer) {
+ this._vertexBuffer = gl.createBuffer();
+ }
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, this._data, gl.DYNAMIC_DRAW);
+ this._dataDirty = false;
+ }
+
+ this._glProgramState.apply(this._matrix);
+ cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 16, 0);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 16, 12);
+
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+ };
+
+ proto.updateBlendFunc = function (blendFunc) {
+ };
+})();
+
+/**
+ * cc.LayerGradient's rendering objects of WebGL
+ */
+(function () {
+ var FLOAT_PER_VERTEX = 4;
+
+ cc.LayerGradient.WebGLRenderCmd = function (renderable) {
+ cc.LayerColor.WebGLRenderCmd.call(this, renderable);
+ this._needDraw = true;
+ this._clipRect = new cc.Rect();
+ this._clippingRectDirty = false;
+ };
+ var proto = cc.LayerGradient.WebGLRenderCmd.prototype = Object.create(cc.LayerColor.WebGLRenderCmd.prototype);
+ proto.constructor = cc.LayerGradient.WebGLRenderCmd;
+
+ proto.updateStatus = function () {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ if (locFlag & flags.gradientDirty) {
+ this._dirtyFlag |= flags.colorDirty;
+ this._updateVertex();
+ this._dirtyFlag &= ~flags.gradientDirty;
+ }
+
+ this.originUpdateStatus();
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ if (locFlag & flags.gradientDirty) {
+ this._dirtyFlag |= flags.colorDirty;
+ this._updateVertex();
+ this._dirtyFlag &= ~flags.gradientDirty;
+ }
+
+ this._originSyncStatus(parentCmd);
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+ this._updateVertex();
+ };
+
+ proto._updateVertex = function () {
+ var node = this._node, stops = node._colorStops;
+ if (!stops || stops.length < 2)
+ return;
+
+ this._clippingRectDirty = true;
+ var i, stopsLen = stops.length, verticesLen = stopsLen * 2, contentSize = node._contentSize;
+ if (this._positionView.length / FLOAT_PER_VERTEX < verticesLen) {
+ this.initData(verticesLen);
+ }
+
+ //init vertex
+ var angle = Math.PI + cc.pAngleSigned(cc.p(0, -1), node._alongVector), locAnchor = cc.p(contentSize.width / 2, contentSize.height / 2);
+ var degrees = Math.round(cc.radiansToDegrees(angle));
+ var transMat = cc.affineTransformMake(1, 0, 0, 1, locAnchor.x, locAnchor.y);
+ transMat = cc.affineTransformRotate(transMat, angle);
+ var a, b;
+ if (degrees < 90) {
+ a = cc.p(-locAnchor.x, locAnchor.y);
+ b = cc.p(locAnchor.x, locAnchor.y);
+ } else if (degrees < 180) {
+ a = cc.p(locAnchor.x, locAnchor.y);
+ b = cc.p(locAnchor.x, -locAnchor.y);
+ } else if (degrees < 270) {
+ a = cc.p(locAnchor.x, -locAnchor.y);
+ b = cc.p(-locAnchor.x, -locAnchor.y);
+ } else {
+ a = cc.p(-locAnchor.x, -locAnchor.y);
+ b = cc.p(-locAnchor.x, locAnchor.y);
+ }
+
+ var sin = Math.sin(angle), cos = Math.cos(angle);
+ var tx = Math.abs((a.x * cos - a.y * sin) / locAnchor.x), ty = Math.abs((b.x * sin + b.y * cos) / locAnchor.y);
+ transMat = cc.affineTransformScale(transMat, tx, ty);
+ var pos = this._positionView;
+ for (i = 0; i < stopsLen; i++) {
+ var stop = stops[i], y = stop.p * contentSize.height;
+ var p0 = cc.pointApplyAffineTransform(-locAnchor.x, y - locAnchor.y, transMat);
+ var offset = i * 2 * FLOAT_PER_VERTEX;
+ pos[offset] = p0.x;
+ pos[offset + 1] = p0.y;
+ pos[offset + 2] = node._vertexZ;
+ var p1 = cc.pointApplyAffineTransform(contentSize.width - locAnchor.x, y - locAnchor.y, transMat);
+ offset += FLOAT_PER_VERTEX;
+ pos[offset] = p1.x;
+ pos[offset + 1] = p1.y;
+ pos[offset + 2] = node._vertexZ;
+ }
+
+ this._dataDirty = true;
+ };
+
+ proto._updateColor = function () {
+ var node = this._node, stops = node._colorStops;
+ if (!stops || stops.length < 2)
+ return;
+
+ var stopsLen = stops.length,
+ stopColor,
+ offset,
+ colors = this._colorView,
+ opacityf = this._displayedOpacity / 255;
+ for (i = 0; i < stopsLen; i++) {
+ stopColor = stops[i].color;
+ this._color[0] = ((stopColor.a*opacityf) << 24) | (stopColor.b << 16) | (stopColor.g << 8) | stopColor.r;
+
+ offset = i * 2 * FLOAT_PER_VERTEX;
+ colors[offset + 3] = this._color[0];
+ offset += FLOAT_PER_VERTEX;
+ colors[offset + 3] = this._color[0];
+ }
+ this._dataDirty = true;
+ };
+
+ proto.rendering = function (ctx) {
+ var context = ctx || cc._renderContext, node = this._node;
+
+ if (!this._matrix) {
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ }
+
+ //it is too expensive to use stencil to clip, so it use Scissor,
+ //but it has a bug when layer rotated and layer's content size less than canvas's size.
+ var clippingRect = this._getClippingRect();
+ context.enable(context.SCISSOR_TEST);
+ cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
+
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ if (this._dataDirty) {
+ if (!this._vertexBuffer) {
+ this._vertexBuffer = gl.createBuffer();
+ }
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, this._data, gl.DYNAMIC_DRAW);
+ this._dataDirty = false;
+ }
+
+ //draw gradient layer
+ this._glProgramState.apply(this._matrix);
+ cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 16, 0);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 16, 12);
+
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ context.disable(context.SCISSOR_TEST);
+ };
+
+ proto._getClippingRect = function () {
+ if (this._clippingRectDirty) {
+ var node = this._node;
+ var rect = cc.rect(0, 0, node._contentSize.width, node._contentSize.height);
+ var trans = node.getNodeToWorldTransform();
+ this._clipRect = cc._rectApplyAffineTransformIn(rect, trans);
+ }
+ return this._clipRect;
+ };
+})();
diff --git a/cocos2d/core/platform/CCClass.js b/cocos2d/core/platform/CCClass.js
new file mode 100644
index 0000000000..be34ad92eb
--- /dev/null
+++ b/cocos2d/core/platform/CCClass.js
@@ -0,0 +1,311 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+var cc = cc || {};
+
+/**
+ * Common getter setter configuration function
+ * @function
+ * @param {Object} proto A class prototype or an object to config
+ * @param {String} prop Property name
+ * @param {function} getter Getter function for the property
+ * @param {function} setter Setter function for the property
+ * @param {String} getterName Name of getter function for the property
+ * @param {String} setterName Name of setter function for the property
+ */
+cc.defineGetterSetter = function (proto, prop, getter, setter, getterName, setterName) {
+ if (proto.__defineGetter__) {
+ getter && proto.__defineGetter__(prop, getter);
+ setter && proto.__defineSetter__(prop, setter);
+ } else if (Object.defineProperty) {
+ var desc = {enumerable: false, configurable: true};
+ getter && (desc.get = getter);
+ setter && (desc.set = setter);
+ Object.defineProperty(proto, prop, desc);
+ } else {
+ throw new Error("browser does not support getters");
+ }
+
+ if (!getterName && !setterName) {
+ // Lookup getter/setter function
+ var hasGetter = (getter != null), hasSetter = (setter != undefined), props = Object.getOwnPropertyNames(proto);
+ for (var i = 0; i < props.length; i++) {
+ var name = props[i];
+
+ if ((proto.__lookupGetter__ ? proto.__lookupGetter__(name)
+ : Object.getOwnPropertyDescriptor(proto, name))
+ || typeof proto[name] !== "function")
+ continue;
+
+ var func = proto[name];
+ if (hasGetter && func === getter) {
+ getterName = name;
+ if (!hasSetter || setterName) break;
+ }
+ if (hasSetter && func === setter) {
+ setterName = name;
+ if (!hasGetter || getterName) break;
+ }
+ }
+ }
+
+ // Found getter/setter
+ var ctor = proto.constructor;
+ if (getterName) {
+ if (!ctor.__getters__) {
+ ctor.__getters__ = {};
+ }
+ ctor.__getters__[getterName] = prop;
+ }
+ if (setterName) {
+ if (!ctor.__setters__) {
+ ctor.__setters__ = {};
+ }
+ ctor.__setters__[setterName] = prop;
+ }
+};
+
+/**
+ * Create a new object and copy all properties in an exist object to the new object
+ * @function
+ * @param {object|Array} obj The source object
+ * @return {Array|object} The created object
+ */
+cc.clone = function (obj) {
+ // Cloning is better if the new object is having the same prototype chain
+ // as the copied obj (or otherwise, the cloned object is certainly going to
+ // have a different hidden class). Play with C1/C2 of the
+ // PerformanceVirtualMachineTests suite to see how this makes an impact
+ // under extreme conditions.
+ //
+ // Object.create(Object.getPrototypeOf(obj)) doesn't work well because the
+ // prototype lacks a link to the constructor (Carakan, V8) so the new
+ // object wouldn't have the hidden class that's associated with the
+ // constructor (also, for whatever reasons, utilizing
+ // Object.create(Object.getPrototypeOf(obj)) + Object.defineProperty is even
+ // slower than the original in V8). Therefore, we call the constructor, but
+ // there is a big caveat - it is possible that the this.init() in the
+ // constructor would throw with no argument. It is also possible that a
+ // derived class forgets to set "constructor" on the prototype. We ignore
+ // these possibities for and the ultimate solution is a standardized
+ // Object.clone().
+ var newObj = (obj.constructor) ? new obj.constructor : {};
+
+ // Assuming that the constuctor above initialized all properies on obj, the
+ // following keyed assignments won't turn newObj into dictionary mode
+ // because they're not *appending new properties* but *assigning existing
+ // ones* (note that appending indexed properties is another story). See
+ // CCClass.js for a link to the devils when the assumption fails.
+ for (var key in obj) {
+ var copy = obj[key];
+ // Beware that typeof null == "object" !
+ if (((typeof copy) === "object") && copy && !(copy instanceof cc.Node) && !(copy instanceof HTMLElement)) {
+ newObj[key] = cc.clone(copy);
+ } else {
+ newObj[key] = copy;
+ }
+ }
+ return newObj;
+};
+
+cc.inject = function (srcPrototype, destPrototype) {
+ for (var key in srcPrototype)
+ destPrototype[key] = srcPrototype[key];
+};
+
+/**
+ * @namespace
+ * @name ClassManager
+ */
+var ClassManager = function () {
+ var id = (0|(Math.random()*998));
+ var instanceId = (0|(Math.random()*998));
+
+ this.getNewID = function () {
+ return id++;
+ };
+
+ this.getNewInstanceId = function () {
+ return instanceId++;
+ };
+};
+var classManager = new ClassManager();
+
+/* Managed JavaScript Inheritance
+ * Based on John Resig's Simple JavaScript Inheritance http://ejohn.org/blog/simple-javascript-inheritance/
+ * MIT Licensed.
+ */
+(function () {
+ var fnTest = /\b_super\b/;
+
+ /**
+ * The base Class implementation (does nothing)
+ * @class
+ */
+ cc.Class = function () {
+ };
+
+ /**
+ * Create a new Class that inherits from this Class
+ * @static
+ * @param {object} props
+ * @return {function}
+ */
+ cc.Class.extend = function (props) {
+ var _super = this.prototype;
+
+ // Instantiate a base Class (but only create the instance,
+ // don't run the init constructor)
+ var prototype = Object.create(_super);
+
+ // Copy the properties over onto the new prototype. We make function
+ // properties non-eumerable as this makes typeof === 'function' check
+ // unnecessary in the for...in loop used 1) for generating Class()
+ // 2) for cc.clone and perhaps more. It is also required to make
+ // these function properties cacheable in Carakan.
+ var desc = {writable: true, enumerable: false, configurable: true};
+
+ // The dummy Class constructor
+ var Class;
+ if (cc.game.config && cc.game.config[cc.game.CONFIG_KEY.exposeClassName]) {
+ var constructor = "(function " + (props._className || "Class") + " (arg0, arg1, arg2, arg3, arg4, arg5) {\n";
+ constructor += " this.__instanceId = classManager.getNewInstanceId();\n";
+ constructor += " if (this.ctor) {\n";
+ constructor += " switch (arguments.length) {\n";
+ constructor += " case 0: this.ctor(); break;\n";
+ constructor += " case 1: this.ctor(arg0); break;\n";
+ constructor += " case 3: this.ctor(arg0, arg1, arg2); break;\n";
+ constructor += " case 4: this.ctor(arg0, arg1, arg2, arg3); break;\n";
+ constructor += " case 5: this.ctor(arg0, arg1, arg2, arg3, arg4); break;\n";
+ constructor += " default: this.ctor.apply(this, arguments);\n";
+ constructor += " }\n";
+ constructor += " }\n";
+ constructor += "})";
+ Class = eval(constructor);
+ }
+ else {
+ Class = function (arg0, arg1, arg2, arg3, arg4) {
+ this.__instanceId = classManager.getNewInstanceId();
+ if (this.ctor) {
+ switch (arguments.length) {
+ case 0: this.ctor(); break;
+ case 1: this.ctor(arg0); break;
+ case 2: this.ctor(arg0, arg1); break;
+ case 3: this.ctor(arg0, arg1, arg2); break;
+ case 4: this.ctor(arg0, arg1, arg2, arg3); break;
+ case 5: this.ctor(arg0, arg1, arg2, arg3, arg4); break;
+ default: this.ctor.apply(this, arguments);
+ }
+ }
+ };
+ }
+
+ desc.value = classManager.getNewID();
+ Object.defineProperty(prototype, '__pid', desc);
+
+ // Populate our constructed prototype object
+ Class.prototype = prototype;
+
+ // Enforce the constructor to be what we expect
+ desc.value = Class;
+ Object.defineProperty(prototype, 'constructor', desc);
+
+ // Copy getter/setter
+ this.__getters__ && (Class.__getters__ = cc.clone(this.__getters__));
+ this.__setters__ && (Class.__setters__ = cc.clone(this.__setters__));
+
+ for (var idx = 0, li = arguments.length; idx < li; ++idx) {
+ var prop = arguments[idx];
+ for (var name in prop) {
+ var isFunc = (typeof prop[name] === "function");
+ var override = (typeof _super[name] === "function");
+ var hasSuperCall = fnTest.test(prop[name]);
+
+ if (isFunc && override && hasSuperCall) {
+ desc.value = (function (name, fn) {
+ return function () {
+ var tmp = this._super;
+
+ // Add a new ._super() method that is the same method
+ // but on the super-Class
+ this._super = _super[name];
+
+ // The method only need to be bound temporarily, so we
+ // remove it when we're done executing
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+
+ return ret;
+ };
+ })(name, prop[name]);
+ Object.defineProperty(prototype, name, desc);
+ } else if (isFunc) {
+ desc.value = prop[name];
+ Object.defineProperty(prototype, name, desc);
+ } else {
+ prototype[name] = prop[name];
+ }
+
+ if (isFunc) {
+ // Override registered getter/setter
+ var getter, setter, propertyName;
+ if (this.__getters__ && this.__getters__[name]) {
+ propertyName = this.__getters__[name];
+ for (var i in this.__setters__) {
+ if (this.__setters__[i] === propertyName) {
+ setter = i;
+ break;
+ }
+ }
+ cc.defineGetterSetter(prototype, propertyName, prop[name], prop[setter] ? prop[setter] : prototype[setter], name, setter);
+ }
+ if (this.__setters__ && this.__setters__[name]) {
+ propertyName = this.__setters__[name];
+ for (var i in this.__getters__) {
+ if (this.__getters__[i] === propertyName) {
+ getter = i;
+ break;
+ }
+ }
+ cc.defineGetterSetter(prototype, propertyName, prop[getter] ? prop[getter] : prototype[getter], prop[name], getter, name);
+ }
+ }
+ }
+ }
+
+ // And make this Class extendable
+ Class.extend = cc.Class.extend;
+
+ //add implementation method
+ Class.implement = function (prop) {
+ for (var name in prop) {
+ prototype[name] = prop[name];
+ }
+ };
+ return Class;
+ };
+})();
+
diff --git a/cocos2d/core/platform/CCCommon.js b/cocos2d/core/platform/CCCommon.js
new file mode 100644
index 0000000000..b99ee95f2f
--- /dev/null
+++ b/cocos2d/core/platform/CCCommon.js
@@ -0,0 +1,248 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+var cc = cc || {};
+cc._tmp = cc._tmp || {};
+
+/**
+ * Function added for JS bindings compatibility. Not needed in cocos2d-html5.
+ * @function
+ * @param {object} jsObj subclass
+ * @param {object} superclass
+ */
+cc.associateWithNative = function (jsObj, superclass) {
+};
+
+/**
+ * Key map for keyboard event
+ *
+ * @constant
+ * @type {Object}
+ * @example
+ cc.eventManager.addListener({
+ event: cc.EventListener.KEYBOARD,
+ onKeyPressed: function(keyCode, event){
+ if (cc.KEY["a"] == keyCode) {
+ cc.log("A is pressed");
+ }
+ }
+ }, this);
+ */
+cc.KEY = {
+ none: 0,
+
+ // android
+ back: 6,
+ menu: 18,
+
+ backspace: 8,
+ tab: 9,
+
+ enter: 13,
+
+ shift: 16, //should use shiftkey instead
+ ctrl: 17, //should use ctrlkey
+ alt: 18, //should use altkey
+ pause: 19,
+ capslock: 20,
+
+ escape: 27,
+ space: 32,
+ pageup: 33,
+ pagedown: 34,
+ end: 35,
+ home: 36,
+ left: 37,
+ up: 38,
+ right: 39,
+ down: 40,
+ select: 41,
+
+ insert: 45,
+ Delete: 46,
+ 0: 48,
+ 1: 49,
+ 2: 50,
+ 3: 51,
+ 4: 52,
+ 5: 53,
+ 6: 54,
+ 7: 55,
+ 8: 56,
+ 9: 57,
+ a: 65,
+ b: 66,
+ c: 67,
+ d: 68,
+ e: 69,
+ f: 70,
+ g: 71,
+ h: 72,
+ i: 73,
+ j: 74,
+ k: 75,
+ l: 76,
+ m: 77,
+ n: 78,
+ o: 79,
+ p: 80,
+ q: 81,
+ r: 82,
+ s: 83,
+ t: 84,
+ u: 85,
+ v: 86,
+ w: 87,
+ x: 88,
+ y: 89,
+ z: 90,
+
+ num0: 96,
+ num1: 97,
+ num2: 98,
+ num3: 99,
+ num4: 100,
+ num5: 101,
+ num6: 102,
+ num7: 103,
+ num8: 104,
+ num9: 105,
+ '*': 106,
+ '+': 107,
+ '-': 109,
+ 'numdel': 110,
+ '/': 111,
+ f1: 112, //f1-f12 don't work on ie
+ f2: 113,
+ f3: 114,
+ f4: 115,
+ f5: 116,
+ f6: 117,
+ f7: 118,
+ f8: 119,
+ f9: 120,
+ f10: 121,
+ f11: 122,
+ f12: 123,
+
+ numlock: 144,
+ scrolllock: 145,
+
+ ';': 186,
+ semicolon: 186,
+ equal: 187,
+ '=': 187,
+ ',': 188,
+ comma: 188,
+ dash: 189,
+ '.': 190,
+ period: 190,
+ forwardslash: 191,
+ grave: 192,
+ '[': 219,
+ openbracket: 219,
+ backslash: 220,
+ ']': 221,
+ closebracket: 221,
+ quote: 222,
+
+ // gamepad control
+ dpadLeft: 1000,
+ dpadRight: 1001,
+ dpadUp: 1003,
+ dpadDown: 1004,
+ dpadCenter: 1005
+};
+
+/**
+ * Image Format:JPG
+ * @constant
+ * @type {Number}
+ */
+cc.FMT_JPG = 0;
+
+/**
+ * Image Format:PNG
+ * @constant
+ * @type {Number}
+ */
+cc.FMT_PNG = 1;
+
+/**
+ * Image Format:TIFF
+ * @constant
+ * @type {Number}
+ */
+cc.FMT_TIFF = 2;
+
+/**
+ * Image Format:RAWDATA
+ * @constant
+ * @type {Number}
+ */
+cc.FMT_RAWDATA = 3;
+
+/**
+ * Image Format:WEBP
+ * @constant
+ * @type {Number}
+ */
+cc.FMT_WEBP = 4;
+
+/**
+ * Image Format:UNKNOWN
+ * @constant
+ * @type {Number}
+ */
+cc.FMT_UNKNOWN = 5;
+
+/**
+ * get image format by image data
+ * @function
+ * @param {Array} imgData
+ * @returns {Number}
+ */
+cc.getImageFormatByData = function (imgData) {
+ // if it is a png file buffer.
+ if (imgData.length > 8 && imgData[0] === 0x89
+ && imgData[1] === 0x50
+ && imgData[2] === 0x4E
+ && imgData[3] === 0x47
+ && imgData[4] === 0x0D
+ && imgData[5] === 0x0A
+ && imgData[6] === 0x1A
+ && imgData[7] === 0x0A) {
+ return cc.FMT_PNG;
+ }
+
+ // if it is a tiff file buffer.
+ if (imgData.length > 2 && ((imgData[0] === 0x49 && imgData[1] === 0x49)
+ || (imgData[0] === 0x4d && imgData[1] === 0x4d)
+ || (imgData[0] === 0xff && imgData[1] === 0xd8))) {
+ return cc.FMT_TIFF;
+ }
+ return cc.FMT_UNKNOWN;
+};
\ No newline at end of file
diff --git a/cocos2d/platform/CCConfig.js b/cocos2d/core/platform/CCConfig.js
similarity index 76%
rename from cocos2d/platform/CCConfig.js
rename to cocos2d/core/platform/CCConfig.js
index a5d8eb5feb..b4795155ed 100644
--- a/cocos2d/platform/CCConfig.js
+++ b/cocos2d/core/platform/CCConfig.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -25,21 +25,19 @@
****************************************************************************/
/**
- *
- * The current version of Cocos2d-html5 being used.
+ * The current version of Cocos2d-JS being used.
* Please DO NOT remove this String, it is an important flag for bug tracking.
* If you post a bug to forum, please attach this flag.
- *
- * @constant
- * @type String
+ * @type {String}
+ * @name cc.ENGINE_VERSION
*/
-cc.ENGINE_VERSION = "Cocos2d-html5-v2.2";
+window["CocosEngine"] = cc.ENGINE_VERSION = "Cocos2d-JS v3.17";
/**
*
* If enabled, the texture coordinates will be calculated by using this formula:
- * - texCoord.left = (rect.origin.x*2+1) / (texture.wide*2);
- * - texCoord.right = texCoord.left + (rect.size.width*2-2)/(texture.wide*2);
+ * - texCoord.left = (rect.x*2+1) / (texture.wide*2);
+ * - texCoord.right = texCoord.left + (rect.width*2-2)/(texture.wide*2);
*
* The same for bottom and top.
*
@@ -52,30 +50,33 @@ cc.ENGINE_VERSION = "Cocos2d-html5-v2.2";
* - cc.QuadParticleSystem
* - cc.TileMap
*
- * To enabled set it to 1. Disabled by default.
+ * To enabled set it to 1. Disabled by default.
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL = 0;
/**
- * Position of the FPS (Default: 0,0 (bottom-left corner))
+ * Position of the FPS (Default: 0,0 (bottom-left corner))
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
* @constant
- * @type cc.Point
+ * @type {cc.Point}
*/
cc.DIRECTOR_STATS_POSITION = cc.p(0, 0);
/**
*
- * Senconds between FPS updates.
+ * Seconds between FPS updates.
* 0.5 seconds, means that the FPS number will be updated every 0.5 seconds.
* Having a bigger number means a more reliable FPS
*
* Default value: 0.1f
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.DIRECTOR_FPS_INTERVAL = 0.5;
@@ -84,10 +85,11 @@ cc.DIRECTOR_FPS_INTERVAL = 0.5;
* If enabled, the cc.Node objects (cc.Sprite, cc.Label,etc) will be able to render in subpixels.
* If disabled, integer pixels will be used.
*
- * To enable set it to 1. Enabled by default.
+ * To enable set it to 1. Enabled by default.
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.COCOSNODE_RENDER_SUBPIXEL = 1;
@@ -96,34 +98,37 @@ cc.COCOSNODE_RENDER_SUBPIXEL = 1;
* If enabled, the cc.Sprite objects rendered with cc.SpriteBatchNode will be able to render in subpixels.
* If disabled, integer pixels will be used.
*
- * To enable set it to 1. Enabled by default.
+ * To enable set it to 1. Enabled by default.
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.SPRITEBATCHNODE_RENDER_SUBPIXEL = 1;
/**
*
- * If most of your imamges have pre-multiplied alpha, set it to 1 (if you are going to use .PNG/.JPG file images).
+ * If most of your images have pre-multiplied alpha, set it to 1 (if you are going to use .PNG/.JPG file images).
* Only set to 0 if ALL your images by-pass Apple UIImage loading system (eg: if you use libpng or PVR images)
*
- * To enable set it to a value different than 0. Enabled by default.
+ * To enable set it to a value different than 0. Enabled by default.
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
*/
-cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA = 0;
+cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA = 1;
/**
*
* Use GL_TRIANGLE_STRIP instead of GL_TRIANGLES when rendering the texture atlas.
* It seems it is the recommend way, but it is much slower, so, enable it at your own risk
*
- * To enable set it to a value different than 0. Disabled by default.
+ * To enable set it to a value different than 0. Disabled by default.
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP = 0;
@@ -134,9 +139,10 @@ cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP = 0;
* So for certain cases, where you might need hundreds of VAO objects, it might be a good idea to disable it.
*
* To disable it set it to 0. disable by default.(Not Supported on WebGL)
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.TEXTURE_ATLAS_USE_VAO = 0;
@@ -150,30 +156,15 @@ cc.TEXTURE_ATLAS_USE_VAO = 0;
* To enable set it to a value different than 0. Disabled by default.
*
* This value governs only the PNG, GIF, BMP, images.
- * This value DOES NOT govern the PVR (PVR.GZ, PVR.CCZ) files. If NPOT PVR is loaded, then it will create an NPOT texture ignoring this value.
+ * This value DOES NOT govern the PVR (PVR.GZ, PVR.CCZ) files. If NPOT PVR is loaded, then it will create an NPOT texture ignoring this value.
+ * To modify it, in Web engine please refer to CCConfig.js, in JSB please refer to CCConfig.h
*
* @constant
- * @type Number
+ * @type {Number}
* @deprecated This value will be removed in 1.1 and NPOT textures will be loaded by default if the device supports it.
*/
cc.TEXTURE_NPOT_SUPPORT = 0;
-/**
- *
- * If enabled, cocos2d supports retina display.
- * For performance reasons, it's recommended disable it in games without retina display support, like iPad only games.
- *
- * To enable set it to 1. Use 0 to disable it. Enabled by default.
- *
- * This value governs only the PNG, GIF, BMP, images.
- * This value DOES NOT govern the PVR (PVR.GZ, PVR.CCZ) files. If NPOT PVR is loaded, then it will create an NPOT texture ignoring this value.
- *
- * @constant
- * @type Number
- * @deprecated This value will be removed in 1.1 and NPOT textures will be loaded by default if the device supports it.
- */
-cc.RETINA_DISPLAY_SUPPORT = 1;
-
/**
*
* It's the suffix that will be appended to the files in order to load "retina display" images.
@@ -184,7 +175,7 @@ cc.RETINA_DISPLAY_SUPPORT = 1;
* Platforms: Only used on Retina Display devices like iPhone 4.
*
* @constant
- * @type String
+ * @type {String}
*/
cc.RETINA_DISPLAY_FILENAME_SUFFIX = "-hd";
@@ -197,14 +188,14 @@ cc.RETINA_DISPLAY_FILENAME_SUFFIX = "-hd";
* This feature is enabled by default.
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.USE_LA88_LABELS = 1;
/**
*
* If enabled, all subclasses of cc.Sprite will draw a bounding box
- * Useful for debugging purposes only. It is recommened to leave it disabled.
+ * Useful for debugging purposes only. It is recommend to leave it disabled.
*
* To enable set it to a value different than 0. Disabled by default:
* 0 -- disabled
@@ -212,76 +203,55 @@ cc.USE_LA88_LABELS = 1;
* 2 -- draw texture box
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.SPRITE_DEBUG_DRAW = 0;
/**
*
* If enabled, all subclasses of cc.Sprite that are rendered using an cc.SpriteBatchNode draw a bounding box.
- * Useful for debugging purposes only. It is recommened to leave it disabled.
+ * Useful for debugging purposes only. It is recommend to leave it disabled.
*
* To enable set it to a value different than 0. Disabled by default.
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.SPRITEBATCHNODE_DEBUG_DRAW = 0;
/**
*
* If enabled, all subclasses of cc.LabelBMFont will draw a bounding box
- * Useful for debugging purposes only. It is recommened to leave it disabled.
+ * Useful for debugging purposes only. It is recommend to leave it disabled.
*
* To enable set it to a value different than 0. Disabled by default.
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.LABELBMFONT_DEBUG_DRAW = 0;
/**
*
- * If enabled, all subclasses of cc.LabeltAtlas will draw a bounding box
- * Useful for debugging purposes only. It is recommened to leave it disabled.
+ * If enabled, all subclasses of cc.LabelAtlas will draw a bounding box
+ * Useful for debugging purposes only. It is recommend to leave it disabled.
*
* To enable set it to a value different than 0. Disabled by default.
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.LABELATLAS_DEBUG_DRAW = 0;
-/**
- * whether or not support retina display
- * @constant
- * @type Number
- */
-cc.IS_RETINA_DISPLAY_SUPPORTED = 1;
+cc.DRAWNODE_TOTAL_VERTICES = 20000;
/**
- * default engine
+ * Default engine
* @constant
- * @type String
+ * @type {String}
*/
cc.DEFAULT_ENGINE = cc.ENGINE_VERSION + "-canvas";
-/**
- * Runtime information
- * @deprecated Use "sys" instead.
- */
-cc.config = {
- 'platform' : sys.platform
-};
-
-/**
- * dump config info, but only in debug mode
- */
-cc.dumpConfig = function() {
- for(var i in sys )
- cc.log( i + " = " + sys[i] );
-};
-
/**
*
* If enabled, actions that alter the position property (eg: CCMoveBy, CCJumpBy, CCBezierBy, etc..) will be stacked.
@@ -296,16 +266,16 @@ cc.ENABLE_STACKABLE_ACTIONS = 1;
/**
*
* If enabled, cocos2d will maintain an OpenGL state cache internally to avoid unnecessary switches.
- * In order to use them, you have to use the following functions, insead of the the GL ones:
+ * In order to use them, you have to use the following functions, instead of the the GL ones:
* - ccGLUseProgram() instead of glUseProgram()
* - ccGLDeleteProgram() instead of glDeleteProgram()
* - ccGLBlendFunc() instead of glBlendFunc()
*
* If this functionality is disabled, then ccGLUseProgram(), ccGLDeleteProgram(), ccGLBlendFunc() will call the GL ones, without using the cache.
- * It is recommened to enable whenever possible to improve speed.
+ * It is recommend to enable whenever possible to improve speed.
* If you are migrating your code from GL ES 1.1, then keep it disabled. Once all your code works as expected, turn it on.
*
* @constant
- * @type Number
+ * @type {Number}
*/
cc.ENABLE_GL_STATE_CACHE = 1;
\ No newline at end of file
diff --git a/cocos2d/core/platform/CCEGLView.js b/cocos2d/core/platform/CCEGLView.js
new file mode 100755
index 0000000000..f91e54b8b8
--- /dev/null
+++ b/cocos2d/core/platform/CCEGLView.js
@@ -0,0 +1,1411 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @ignore
+ */
+cc.Touches = [];
+cc.TouchesIntergerDict = {};
+
+cc.DENSITYDPI_DEVICE = "device-dpi";
+cc.DENSITYDPI_HIGH = "high-dpi";
+cc.DENSITYDPI_MEDIUM = "medium-dpi";
+cc.DENSITYDPI_LOW = "low-dpi";
+
+var __BrowserGetter = {
+ init: function () {
+ this.html = document.documentElement;
+ },
+ availWidth: function (frame) {
+ if (!frame || frame === this.html)
+ return window.innerWidth;
+ else
+ return frame.clientWidth;
+ },
+ availHeight: function (frame) {
+ if (!frame || frame === this.html)
+ return window.innerHeight;
+ else
+ return frame.clientHeight;
+ },
+ meta: {
+ "width": "device-width"
+ },
+ adaptationType: cc.sys.browserType
+};
+
+if (window.navigator.userAgent.indexOf("OS 8_1_") > -1) //this mistake like MIUI, so use of MIUI treatment method
+ __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_MIUI;
+
+if (cc.sys.os === cc.sys.OS_IOS) // All browsers are WebView
+ __BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_SAFARI;
+
+switch (__BrowserGetter.adaptationType) {
+ case cc.sys.BROWSER_TYPE_SAFARI:
+ __BrowserGetter.meta["minimal-ui"] = "true";
+ break;
+ case cc.sys.BROWSER_TYPE_CHROME:
+ __BrowserGetter.__defineGetter__("target-densitydpi", function () {
+ return cc.view._targetDensityDPI;
+ });
+ break;
+ case cc.sys.BROWSER_TYPE_MIUI:
+ __BrowserGetter.init = function (view) {
+ if (view.__resizeWithBrowserSize) return;
+ var resize = function () {
+ view.setDesignResolutionSize(
+ view._designResolutionSize.width,
+ view._designResolutionSize.height,
+ view._resolutionPolicy
+ );
+ window.removeEventListener("resize", resize, false);
+ };
+ window.addEventListener("resize", resize, false);
+ };
+ break;
+}
+
+var _scissorRect = null;
+
+/**
+ * cc.view is the singleton object which represents the game window.
+ * It's main task include:
+ * - Apply the design resolution policy
+ * - Provide interaction with the window, like resize event on web, retina display support, etc...
+ * - Manage the game view port which can be different with the window
+ * - Manage the content scale and translation
+ *
+ * Since the cc.view is a singleton, you don't need to call any constructor or create functions,
+ * the standard way to use it is by calling:
+ * - cc.view.methodName();
+ * @class
+ * @name cc.view
+ * @extend cc.Class
+ */
+cc.EGLView = cc.Class.extend(/** @lends cc.view# */{
+ _delegate: null,
+ // Size of parent node that contains cc.container and cc._canvas
+ _frameSize: null,
+ // resolution size, it is the size appropriate for the app resources.
+ _designResolutionSize: null,
+ _originalDesignResolutionSize: null,
+ // Viewport is the container's rect related to content's coordinates in pixel
+ _viewPortRect: null,
+ // The visible rect in content's coordinate in point
+ _visibleRect: null,
+ _retinaEnabled: false,
+ _autoFullScreen: false,
+ // The device's pixel ratio (for retina displays)
+ _devicePixelRatio: 1,
+ // the view name
+ _viewName: "",
+ // Custom callback for resize event
+ _resizeCallback: null,
+
+ _orientationChanging: true,
+ _resizing: false,
+
+ _scaleX: 1,
+ _originalScaleX: 1,
+ _scaleY: 1,
+ _originalScaleY: 1,
+
+ _isRotated: false,
+ _orientation: 3,
+
+ _resolutionPolicy: null,
+ _rpExactFit: null,
+ _rpShowAll: null,
+ _rpNoBorder: null,
+ _rpFixedHeight: null,
+ _rpFixedWidth: null,
+ _initialized: false,
+
+ _contentTranslateLeftTop: null,
+
+ // Parent node that contains cc.container and cc._canvas
+ _frame: null,
+ _frameZoomFactor: 1.0,
+ __resizeWithBrowserSize: false,
+ _isAdjustViewPort: true,
+ _targetDensityDPI: null,
+
+ /**
+ * Constructor of cc.EGLView
+ */
+ ctor: function () {
+ var _t = this, d = document, _strategyer = cc.ContainerStrategy, _strategy = cc.ContentStrategy;
+
+ __BrowserGetter.init(this);
+
+ _t._frame = (cc.container.parentNode === d.body) ? d.documentElement : cc.container.parentNode;
+ _t._frameSize = cc.size(0, 0);
+ _t._initFrameSize();
+
+ var w = cc._canvas.width, h = cc._canvas.height;
+ _t._designResolutionSize = cc.size(w, h);
+ _t._originalDesignResolutionSize = cc.size(w, h);
+ _t._viewPortRect = cc.rect(0, 0, w, h);
+ _t._visibleRect = cc.rect(0, 0, w, h);
+ _t._contentTranslateLeftTop = {left: 0, top: 0};
+ _t._viewName = "Cocos2dHTML5";
+
+ var sys = cc.sys;
+ cc.visibleRect && cc.visibleRect.init(_t._visibleRect);
+
+ // Setup system default resolution policies
+ _t._rpExactFit = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.EXACT_FIT);
+ _t._rpShowAll = new cc.ResolutionPolicy(_strategyer.PROPORTION_TO_FRAME, _strategy.SHOW_ALL);
+ _t._rpNoBorder = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.NO_BORDER);
+ _t._rpFixedHeight = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_HEIGHT);
+ _t._rpFixedWidth = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_WIDTH);
+
+ _t._targetDensityDPI = cc.DENSITYDPI_HIGH;
+
+ if (sys.isMobile) {
+ window.addEventListener('orientationchange', this._orientationChange);
+ } else {
+ this._orientationChanging = false;
+ }
+ },
+
+ // Resize helper functions
+ _resizeEvent: function () {
+ var view;
+ if (this.setDesignResolutionSize) {
+ view = this;
+ } else {
+ view = cc.view;
+ }
+ if (view._orientationChanging) {
+ return;
+ }
+
+ // Check frame size changed or not
+ var prevFrameW = view._frameSize.width, prevFrameH = view._frameSize.height, prevRotated = view._isRotated;
+ if (cc.sys.isMobile) {
+ var containerStyle = cc.game.container.style,
+ margin = containerStyle.margin;
+ containerStyle.margin = '0';
+ containerStyle.display = 'none';
+ view._initFrameSize();
+ containerStyle.margin = margin;
+ containerStyle.display = 'block';
+ }
+ else {
+ view._initFrameSize();
+ }
+ if (view._isRotated === prevRotated && view._frameSize.width === prevFrameW && view._frameSize.height === prevFrameH)
+ return;
+
+ // Frame size changed, do resize works
+ var width = view._originalDesignResolutionSize.width;
+ var height = view._originalDesignResolutionSize.height;
+ view._resizing = true;
+ if (width > 0) {
+ view.setDesignResolutionSize(width, height, view._resolutionPolicy);
+ }
+ view._resizing = false;
+
+ cc.eventManager.dispatchCustomEvent('canvas-resize');
+ if (view._resizeCallback) {
+ view._resizeCallback.call();
+ }
+ },
+
+ _orientationChange: function () {
+ cc.view._orientationChanging = true;
+ if (cc.sys.isMobile) {
+ cc.game.container.style.display = "none";
+ }
+ setTimeout(function () {
+ cc.view._orientationChanging = false;
+ cc.view._resizeEvent();
+ }, 300);
+ },
+
+ /**
+ *
+ * Sets view's target-densitydpi for android mobile browser. it can be set to:
+ * 1. cc.DENSITYDPI_DEVICE, value is "device-dpi"
+ * 2. cc.DENSITYDPI_HIGH, value is "high-dpi" (default value)
+ * 3. cc.DENSITYDPI_MEDIUM, value is "medium-dpi" (browser's default value)
+ * 4. cc.DENSITYDPI_LOW, value is "low-dpi"
+ * 5. Custom value, e.g: "480"
+ *
+ * @param {String} densityDPI
+ */
+ setTargetDensityDPI: function (densityDPI) {
+ this._targetDensityDPI = densityDPI;
+ this._adjustViewportMeta();
+ },
+
+ /**
+ * Returns the current target-densitydpi value of cc.view.
+ * @returns {String}
+ */
+ getTargetDensityDPI: function () {
+ return this._targetDensityDPI;
+ },
+
+ /**
+ * Sets whether resize canvas automatically when browser's size changed.
+ * Useful only on web.
+ * @param {Boolean} enabled Whether enable automatic resize with browser's resize event
+ */
+ resizeWithBrowserSize: function (enabled) {
+ if (enabled) {
+ //enable
+ if (!this.__resizeWithBrowserSize) {
+ this.__resizeWithBrowserSize = true;
+ window.addEventListener('resize', this._resizeEvent);
+ }
+ } else {
+ //disable
+ if (this.__resizeWithBrowserSize) {
+ this.__resizeWithBrowserSize = false;
+ window.removeEventListener('resize', this._resizeEvent);
+ }
+ }
+ },
+
+ /**
+ * Sets the callback function for cc.view's resize action,
+ * this callback will be invoked before applying resolution policy,
+ * so you can do any additional modifications within the callback.
+ * Useful only on web.
+ * @param {Function|null} callback The callback function
+ */
+ setResizeCallback: function (callback) {
+ if (typeof callback === 'function' || callback == null) {
+ this._resizeCallback = callback;
+ }
+ },
+
+ /**
+ * Sets the orientation of the game, it can be landscape, portrait or auto.
+ * When set it to landscape or portrait, and screen w/h ratio doesn't fit,
+ * cc.view will automatically rotate the game canvas using CSS.
+ * Note that this function doesn't have any effect in native,
+ * in native, you need to set the application orientation in native project settings
+ * @param {Number} orientation - Possible values: cc.ORIENTATION_LANDSCAPE | cc.ORIENTATION_PORTRAIT | cc.ORIENTATION_AUTO
+ */
+ setOrientation: function (orientation) {
+ orientation = orientation & cc.ORIENTATION_AUTO;
+ if (orientation && this._orientation !== orientation) {
+ this._orientation = orientation;
+ if (this._resolutionPolicy) {
+ var designWidth = this._originalDesignResolutionSize.width;
+ var designHeight = this._originalDesignResolutionSize.height;
+ this.setDesignResolutionSize(designWidth, designHeight, this._resolutionPolicy);
+ }
+ }
+ },
+
+ setDocumentPixelWidth: function (width) {
+ // Set viewport's width
+ this._setViewportMeta({"width": width}, true);
+
+ // Set body width to the exact pixel resolution
+ document.documentElement.style.width = width + 'px';
+ document.body.style.width = "100%";
+
+ // Reset the resolution size and policy
+ this.setDesignResolutionSize(this._designResolutionSize.width, this._designResolutionSize.height, this._resolutionPolicy);
+ },
+
+ _initFrameSize: function () {
+ var locFrameSize = this._frameSize;
+ var w = __BrowserGetter.availWidth(this._frame);
+ var h = __BrowserGetter.availHeight(this._frame);
+ var isLandscape = w >= h;
+
+ if (!cc.sys.isMobile ||
+ (isLandscape && this._orientation & cc.ORIENTATION_LANDSCAPE) ||
+ (!isLandscape && this._orientation & cc.ORIENTATION_PORTRAIT)) {
+ locFrameSize.width = w;
+ locFrameSize.height = h;
+ cc.container.style['-webkit-transform'] = 'rotate(0deg)';
+ cc.container.style.transform = 'rotate(0deg)';
+ this._isRotated = false;
+ }
+ else {
+ locFrameSize.width = h;
+ locFrameSize.height = w;
+ cc.container.style['-webkit-transform'] = 'rotate(90deg)';
+ cc.container.style.transform = 'rotate(90deg)';
+ cc.container.style['-webkit-transform-origin'] = '0px 0px 0px';
+ cc.container.style.transformOrigin = '0px 0px 0px';
+ this._isRotated = true;
+ }
+ },
+
+ // hack
+ _adjustSizeKeepCanvasSize: function () {
+ var designWidth = this._originalDesignResolutionSize.width;
+ var designHeight = this._originalDesignResolutionSize.height;
+ if (designWidth > 0)
+ this.setDesignResolutionSize(designWidth, designHeight, this._resolutionPolicy);
+ },
+
+ _setViewportMeta: function (metas, overwrite) {
+ var vp = document.getElementById("cocosMetaElement");
+ if (vp && overwrite) {
+ document.head.removeChild(vp);
+ }
+
+ var elems = document.getElementsByName("viewport"),
+ currentVP = elems ? elems[0] : null,
+ content, key, pattern;
+
+ content = currentVP ? currentVP.content : "";
+ vp = vp || document.createElement("meta");
+ vp.id = "cocosMetaElement";
+ vp.name = "viewport";
+ vp.content = "";
+
+ for (key in metas) {
+ if (content.indexOf(key) == -1) {
+ content += "," + key + "=" + metas[key];
+ }
+ else if (overwrite) {
+ pattern = new RegExp(key + "\s*=\s*[^,]+");
+ content.replace(pattern, key + "=" + metas[key]);
+ }
+ }
+ if (/^,/.test(content))
+ content = content.substr(1);
+
+ vp.content = content;
+ // For adopting certain android devices which don't support second viewport
+ if (currentVP)
+ currentVP.content = content;
+
+ document.head.appendChild(vp);
+ },
+
+ _adjustViewportMeta: function () {
+ if (this._isAdjustViewPort) {
+ this._setViewportMeta(__BrowserGetter.meta, false);
+ // Only adjust viewport once
+ this._isAdjustViewPort = false;
+ }
+ },
+
+ // RenderTexture hacker
+ _setScaleXYForRenderTexture: function () {
+ //hack for RenderTexture on canvas mode when adapting multiple resolution resources
+ var scaleFactor = cc.contentScaleFactor();
+ this._scaleX = scaleFactor;
+ this._scaleY = scaleFactor;
+ },
+
+ // Other helper functions
+ _resetScale: function () {
+ this._scaleX = this._originalScaleX;
+ this._scaleY = this._originalScaleY;
+ },
+
+ // Useless, just make sure the compatibility temporarily, should be removed
+ _adjustSizeToBrowser: function () {
+ },
+
+ initialize: function () {
+ this._initialized = true;
+ },
+
+ /**
+ * Sets whether the engine modify the "viewport" meta in your web page.
+ * It's enabled by default, we strongly suggest you not to disable it.
+ * And even when it's enabled, you can still set your own "viewport" meta, it won't be overridden
+ * Only useful on web
+ * @param {Boolean} enabled Enable automatic modification to "viewport" meta
+ */
+ adjustViewPort: function (enabled) {
+ this._isAdjustViewPort = enabled;
+ },
+
+ /**
+ * Retina support is enabled by default for Apple device but disabled for other devices,
+ * it takes effect only when you called setDesignResolutionPolicy
+ * Only useful on web
+ * @param {Boolean} enabled Enable or disable retina display
+ */
+ enableRetina: function (enabled) {
+ this._retinaEnabled = !!enabled;
+ },
+
+ /**
+ * Check whether retina display is enabled.
+ * Only useful on web
+ * @return {Boolean}
+ */
+ isRetinaEnabled: function () {
+ return this._retinaEnabled;
+ },
+
+ /**
+ * If enabled, the application will try automatically to enter full screen mode on mobile devices
+ * You can pass true as parameter to enable it and disable it by passing false.
+ * Only useful on web
+ * @param {Boolean} enabled Enable or disable auto full screen on mobile devices
+ */
+ enableAutoFullScreen: function (enabled) {
+ if (enabled && enabled !== this._autoFullScreen && cc.sys.isMobile && this._frame === document.documentElement) {
+ // Automatically full screen when user touches on mobile version
+ this._autoFullScreen = true;
+ cc.screen.autoFullScreen(this._frame);
+ }
+ else {
+ this._autoFullScreen = false;
+ }
+ },
+
+ /**
+ * Check whether auto full screen is enabled.
+ * Only useful on web
+ * @return {Boolean} Auto full screen enabled or not
+ */
+ isAutoFullScreenEnabled: function () {
+ return this._autoFullScreen;
+ },
+
+ /**
+ * Get whether render system is ready(no matter opengl or canvas),
+ * this name is for the compatibility with cocos2d-x, subclass must implement this method.
+ * @return {Boolean}
+ */
+ isOpenGLReady: function () {
+ return (cc.game.canvas && cc._renderContext);
+ },
+
+ /*
+ * Set zoom factor for frame. This method is for debugging big resolution (e.g.new ipad) app on desktop.
+ * @param {Number} zoomFactor
+ */
+ setFrameZoomFactor: function (zoomFactor) {
+ this._frameZoomFactor = zoomFactor;
+ this.centerWindow();
+ cc.director.setProjection(cc.director.getProjection());
+ },
+
+ /**
+ * Exchanges the front and back buffers, subclass must implement this method.
+ */
+ swapBuffers: function () {
+ },
+
+ /**
+ * Open or close IME keyboard , subclass must implement this method.
+ * @param {Boolean} isOpen
+ */
+ setIMEKeyboardState: function (isOpen) {
+ },
+
+ /**
+ * Sets the resolution translate on EGLView
+ * @param {Number} offsetLeft
+ * @param {Number} offsetTop
+ */
+ setContentTranslateLeftTop: function (offsetLeft, offsetTop) {
+ this._contentTranslateLeftTop = {left: offsetLeft, top: offsetTop};
+ },
+
+ /**
+ * Returns the resolution translate on EGLView
+ * @return {cc.Size|Object}
+ */
+ getContentTranslateLeftTop: function () {
+ return this._contentTranslateLeftTop;
+ },
+
+ /**
+ * Returns the canvas size of the view.
+ * On native platforms, it returns the screen size since the view is a fullscreen view.
+ * On web, it returns the size of the canvas element.
+ * @return {cc.Size}
+ */
+ getCanvasSize: function () {
+ return cc.size(cc._canvas.width, cc._canvas.height);
+ },
+
+ /**
+ * Returns the frame size of the view.
+ * On native platforms, it returns the screen size since the view is a fullscreen view.
+ * On web, it returns the size of the canvas's outer DOM element.
+ * @return {cc.Size}
+ */
+ getFrameSize: function () {
+ return cc.size(this._frameSize.width, this._frameSize.height);
+ },
+
+ /**
+ * On native, it sets the frame size of view.
+ * On web, it sets the size of the canvas's outer DOM element.
+ * @param {Number} width
+ * @param {Number} height
+ */
+ setFrameSize: function (width, height) {
+ this._frameSize.width = width;
+ this._frameSize.height = height;
+ this._frame.style.width = width + "px";
+ this._frame.style.height = height + "px";
+ this._resizeEvent();
+ cc.director.setProjection(cc.director.getProjection());
+ },
+
+ /**
+ * Returns the visible area size of the view port.
+ * @return {cc.Size}
+ */
+ getVisibleSize: function () {
+ return cc.size(this._visibleRect.width, this._visibleRect.height);
+ },
+
+ /**
+ * Returns the visible area size of the view port.
+ * @return {cc.Size}
+ */
+ getVisibleSizeInPixel: function () {
+ return cc.size( this._visibleRect.width * this._scaleX,
+ this._visibleRect.height * this._scaleY );
+ },
+
+ /**
+ * Returns the visible origin of the view port.
+ * @return {cc.Point}
+ */
+ getVisibleOrigin: function () {
+ return cc.p(this._visibleRect.x, this._visibleRect.y);
+ },
+
+ /**
+ * Returns the visible origin of the view port.
+ * @return {cc.Point}
+ */
+ getVisibleOriginInPixel: function () {
+ return cc.p(this._visibleRect.x * this._scaleX,
+ this._visibleRect.y * this._scaleY);
+ },
+
+ /**
+ * Returns whether developer can set content's scale factor.
+ * @return {Boolean}
+ */
+ canSetContentScaleFactor: function () {
+ return true;
+ },
+
+ /**
+ * Returns the current resolution policy
+ * @see cc.ResolutionPolicy
+ * @return {cc.ResolutionPolicy}
+ */
+ getResolutionPolicy: function () {
+ return this._resolutionPolicy;
+ },
+
+ /**
+ * Sets the current resolution policy
+ * @see cc.ResolutionPolicy
+ * @param {cc.ResolutionPolicy|Number} resolutionPolicy
+ */
+ setResolutionPolicy: function (resolutionPolicy) {
+ var _t = this;
+ if (resolutionPolicy instanceof cc.ResolutionPolicy) {
+ _t._resolutionPolicy = resolutionPolicy;
+ }
+ // Ensure compatibility with JSB
+ else {
+ var _locPolicy = cc.ResolutionPolicy;
+ if (resolutionPolicy === _locPolicy.EXACT_FIT)
+ _t._resolutionPolicy = _t._rpExactFit;
+ if (resolutionPolicy === _locPolicy.SHOW_ALL)
+ _t._resolutionPolicy = _t._rpShowAll;
+ if (resolutionPolicy === _locPolicy.NO_BORDER)
+ _t._resolutionPolicy = _t._rpNoBorder;
+ if (resolutionPolicy === _locPolicy.FIXED_HEIGHT)
+ _t._resolutionPolicy = _t._rpFixedHeight;
+ if (resolutionPolicy === _locPolicy.FIXED_WIDTH)
+ _t._resolutionPolicy = _t._rpFixedWidth;
+ }
+ },
+
+ /**
+ * Sets the resolution policy with designed view size in points.
+ * The resolution policy include:
+ * [1] ResolutionExactFit Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio, your game view will be stretched.
+ * [2] ResolutionNoBorder Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two areas of your game view will be cut.
+ * [3] ResolutionShowAll Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two black borders will be shown.
+ * [4] ResolutionFixedHeight Scale the content's height to screen's height and proportionally scale its width
+ * [5] ResolutionFixedWidth Scale the content's width to screen's width and proportionally scale its height
+ * [cc.ResolutionPolicy] [Web only feature] Custom resolution policy, constructed by cc.ResolutionPolicy
+ * @param {Number} width Design resolution width.
+ * @param {Number} height Design resolution height.
+ * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired
+ */
+ setDesignResolutionSize: function (width, height, resolutionPolicy) {
+ // Defensive code
+ if (!(width > 0 || height > 0)) {
+ cc.log(cc._LogInfos.EGLView_setDesignResolutionSize);
+ return;
+ }
+
+ this.setResolutionPolicy(resolutionPolicy);
+ var policy = this._resolutionPolicy;
+ if (policy) {
+ policy.preApply(this);
+ }
+
+ // Reinit frame size
+ if (cc.sys.isMobile)
+ this._adjustViewportMeta();
+
+ // If resizing, then frame size is already initialized, this logic should be improved
+ if (!this._resizing)
+ this._initFrameSize();
+
+ if (!policy) {
+ cc.log(cc._LogInfos.EGLView_setDesignResolutionSize_2);
+ return;
+ }
+
+ this._originalDesignResolutionSize.width = this._designResolutionSize.width = width;
+ this._originalDesignResolutionSize.height = this._designResolutionSize.height = height;
+
+ var result = policy.apply(this, this._designResolutionSize);
+
+ if (result.scale && result.scale.length === 2) {
+ this._scaleX = result.scale[0];
+ this._scaleY = result.scale[1];
+ }
+
+ if (result.viewport) {
+ var vp = this._viewPortRect,
+ vb = this._visibleRect,
+ rv = result.viewport;
+
+ vp.x = rv.x;
+ vp.y = rv.y;
+ vp.width = rv.width;
+ vp.height = rv.height;
+
+ vb.x = -vp.x / this._scaleX;
+ vb.y = -vp.y / this._scaleY;
+ vb.width = cc._canvas.width / this._scaleX;
+ vb.height = cc._canvas.height / this._scaleY;
+ cc._renderContext.setOffset && cc._renderContext.setOffset(vp.x, -vp.y);
+ }
+
+ // reset director's member variables to fit visible rect
+ var director = cc.director;
+ director._winSizeInPoints.width = this._designResolutionSize.width;
+ director._winSizeInPoints.height = this._designResolutionSize.height;
+ policy.postApply(this);
+ cc.winSize.width = director._winSizeInPoints.width;
+ cc.winSize.height = director._winSizeInPoints.height;
+
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ // reset director's member variables to fit visible rect
+ director.setGLDefaultValues();
+ }
+ else if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+ cc.renderer._allNeedDraw = true;
+ }
+
+ this._originalScaleX = this._scaleX;
+ this._originalScaleY = this._scaleY;
+ cc.visibleRect && cc.visibleRect.init(this._visibleRect);
+ },
+
+ /**
+ * Returns the designed size for the view.
+ * Default resolution size is the same as 'getFrameSize'.
+ * @return {cc.Size}
+ */
+ getDesignResolutionSize: function () {
+ return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
+ },
+
+ /**
+ * Sets the document body to desired pixel resolution and fit the game content to it.
+ * This function is very useful for adaptation in mobile browsers.
+ * In some HD android devices, the resolution is very high, but its browser performance may not be very good.
+ * In this case, enabling retina display is very costy and not suggested, and if retina is disabled, the image may be blurry.
+ * But this API can be helpful to set a desired pixel resolution which is in between.
+ * This API will do the following:
+ * 1. Set viewport's width to the desired width in pixel
+ * 2. Set body width to the exact pixel resolution
+ * 3. The resolution policy will be reset with designed view size in points.
+ * @param {Number} width Design resolution width.
+ * @param {Number} height Design resolution height.
+ * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired
+ */
+ setRealPixelResolution: function (width, height, resolutionPolicy) {
+ // Set viewport's width
+ this._setViewportMeta({"width": width}, true);
+
+ // Set body width to the exact pixel resolution
+ document.documentElement.style.width = width + "px";
+ document.body.style.width = width + "px";
+ document.body.style.left = "0px";
+ document.body.style.top = "0px";
+
+ // Reset the resolution size and policy
+ this.setDesignResolutionSize(width, height, resolutionPolicy);
+ },
+
+ /**
+ * Sets view port rectangle with points.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} w width
+ * @param {Number} h height
+ */
+ setViewPortInPoints: function (x, y, w, h) {
+ var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
+ cc._renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
+ (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
+ (w * locScaleX * locFrameZoomFactor),
+ (h * locScaleY * locFrameZoomFactor));
+ },
+
+ /**
+ * Sets Scissor rectangle with points.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} w
+ * @param {Number} h
+ */
+ setScissorInPoints: function (x, y, w, h) {
+ var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
+ var sx = Math.ceil(x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor);
+ var sy = Math.ceil(y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor);
+ var sw = Math.ceil(w * locScaleX * locFrameZoomFactor);
+ var sh = Math.ceil(h * locScaleY * locFrameZoomFactor);
+
+ if (!_scissorRect) {
+ var boxArr = gl.getParameter(gl.SCISSOR_BOX);
+ _scissorRect = cc.rect(boxArr[0], boxArr[1], boxArr[2], boxArr[3]);
+ }
+
+ if (_scissorRect.x != sx || _scissorRect.y != sy || _scissorRect.width != sw || _scissorRect.height != sh) {
+ _scissorRect.x = sx;
+ _scissorRect.y = sy;
+ _scissorRect.width = sw;
+ _scissorRect.height = sh;
+ cc._renderContext.scissor(sx, sy, sw, sh);
+ }
+ },
+
+ /**
+ * Returns whether GL_SCISSOR_TEST is enable
+ * @return {Boolean}
+ */
+ isScissorEnabled: function () {
+ return cc._renderContext.isEnabled(gl.SCISSOR_TEST);
+ },
+
+ /**
+ * Returns the current scissor rectangle
+ * @return {cc.Rect}
+ */
+ getScissorRect: function () {
+ if (!_scissorRect) {
+ var boxArr = gl.getParameter(gl.SCISSOR_BOX);
+ _scissorRect = cc.rect(boxArr[0], boxArr[1], boxArr[2], boxArr[3]);
+ }
+ var scaleXFactor = 1 / this._scaleX;
+ var scaleYFactor = 1 / this._scaleY;
+ return cc.rect(
+ (_scissorRect.x - this._viewPortRect.x) * scaleXFactor,
+ (_scissorRect.y - this._viewPortRect.y) * scaleYFactor,
+ _scissorRect.width * scaleXFactor,
+ _scissorRect.height * scaleYFactor
+ );
+ },
+
+ /**
+ * Sets the name of the view
+ * @param {String} viewName
+ */
+ setViewName: function (viewName) {
+ if (viewName != null && viewName.length > 0) {
+ this._viewName = viewName;
+ }
+ },
+
+ /**
+ * Returns the name of the view
+ * @return {String}
+ */
+ getViewName: function () {
+ return this._viewName;
+ },
+
+ /**
+ * Returns the view port rectangle.
+ * @return {cc.Rect}
+ */
+ getViewPortRect: function () {
+ return this._viewPortRect;
+ },
+
+ /**
+ * Returns scale factor of the horizontal direction (X axis).
+ * @return {Number}
+ */
+ getScaleX: function () {
+ return this._scaleX;
+ },
+
+ /**
+ * Returns scale factor of the vertical direction (Y axis).
+ * @return {Number}
+ */
+ getScaleY: function () {
+ return this._scaleY;
+ },
+
+ /**
+ * Returns device pixel ratio for retina display.
+ * @return {Number}
+ */
+ getDevicePixelRatio: function () {
+ return this._devicePixelRatio;
+ },
+
+ /**
+ * Returns the real location in view for a translation based on a related position
+ * @param {Number} tx The X axis translation
+ * @param {Number} ty The Y axis translation
+ * @param {Object} relatedPos The related position object including "left", "top", "width", "height" informations
+ * @return {cc.Point}
+ */
+ convertToLocationInView: function (tx, ty, relatedPos) {
+ var x = this._devicePixelRatio * (tx - relatedPos.left);
+ var y = this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty);
+ return this._isRotated ? {x: this._viewPortRect.width - y, y: x} : {x: x, y: y};
+ },
+
+ _convertMouseToLocationInView: function (point, relatedPos) {
+ var viewport = this._viewPortRect, _t = this;
+ point.x = ((_t._devicePixelRatio * (point.x - relatedPos.left)) - viewport.x) / _t._scaleX;
+ point.y = (_t._devicePixelRatio * (relatedPos.top + relatedPos.height - point.y) - viewport.y) / _t._scaleY;
+ },
+
+ _convertPointWithScale: function (point) {
+ var viewport = this._viewPortRect;
+ point.x = (point.x - viewport.x) / this._scaleX;
+ point.y = (point.y - viewport.y) / this._scaleY;
+ },
+
+ _convertTouchesWithScale: function (touches) {
+ var viewport = this._viewPortRect, scaleX = this._scaleX, scaleY = this._scaleY,
+ selTouch, selPoint, selPrePoint;
+ for (var i = 0; i < touches.length; i++) {
+ selTouch = touches[i];
+ selPoint = selTouch._point;
+ selPrePoint = selTouch._prevPoint;
+
+ selPoint.x = (selPoint.x - viewport.x) / scaleX;
+ selPoint.y = (selPoint.y - viewport.y) / scaleY;
+ selPrePoint.x = (selPrePoint.x - viewport.x) / scaleX;
+ selPrePoint.y = (selPrePoint.y - viewport.y) / scaleY;
+ }
+ }
+});
+
+/**
+ * @function
+ * @return {cc.EGLView}
+ * @private
+ */
+cc.EGLView._getInstance = function () {
+ if (!this._instance) {
+ this._instance = this._instance || new cc.EGLView();
+ this._instance.initialize();
+ }
+ return this._instance;
+};
+
+/**
+ * cc.ContainerStrategy class is the root strategy class of container's scale strategy,
+ * it controls the behavior of how to scale the cc.container and cc._canvas object
+ *
+ * @class
+ * @extends cc.Class
+ */
+cc.ContainerStrategy = cc.Class.extend(/** @lends cc.ContainerStrategy# */{
+ /**
+ * Manipulation before appling the strategy
+ * @param {cc.view} The target view
+ */
+ preApply: function (view) {
+ },
+
+ /**
+ * Function to apply this strategy
+ * @param {cc.view} view
+ * @param {cc.Size} designedResolution
+ */
+ apply: function (view, designedResolution) {
+ },
+
+ /**
+ * Manipulation after applying the strategy
+ * @param {cc.view} view The target view
+ */
+ postApply: function (view) {
+
+ },
+
+ _setupContainer: function (view, w, h) {
+ var locCanvas = cc.game.canvas, locContainer = cc.game.container;
+ if (cc.sys.os === cc.sys.OS_ANDROID) {
+ document.body.style.width = (view._isRotated ? h : w) + 'px';
+ document.body.style.height = (view._isRotated ? w : h) + 'px';
+ }
+
+ // Setup style
+ locContainer.style.width = locCanvas.style.width = w + 'px';
+ locContainer.style.height = locCanvas.style.height = h + 'px';
+ // Setup pixel ratio for retina display
+ var devicePixelRatio = view._devicePixelRatio = 1;
+ if (view.isRetinaEnabled())
+ devicePixelRatio = view._devicePixelRatio = Math.min(2, window.devicePixelRatio || 1);
+ // Setup canvas
+ locCanvas.width = w * devicePixelRatio;
+ locCanvas.height = h * devicePixelRatio;
+ cc._renderContext.resetCache && cc._renderContext.resetCache();
+ },
+
+ _fixContainer: function () {
+ // Add container to document body
+ document.body.insertBefore(cc.container, document.body.firstChild);
+ // Set body's width height to window's size, and forbid overflow, so that game will be centered
+ var bs = document.body.style;
+ bs.width = window.innerWidth + "px";
+ bs.height = window.innerHeight + "px";
+ bs.overflow = "hidden";
+ // Body size solution doesn't work on all mobile browser so this is the aleternative: fixed container
+ var contStyle = cc.container.style;
+ contStyle.position = "fixed";
+ contStyle.left = contStyle.top = "0px";
+ // Reposition body
+ document.body.scrollTop = 0;
+ }
+});
+
+/**
+ * cc.ContentStrategy class is the root strategy class of content's scale strategy,
+ * it controls the behavior of how to scale the scene and setup the viewport for the game
+ *
+ * @class
+ * @extends cc.Class
+ */
+cc.ContentStrategy = cc.Class.extend(/** @lends cc.ContentStrategy# */{
+
+ _result: {
+ scale: [1, 1],
+ viewport: null
+ },
+
+ _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
+ // Makes content fit better the canvas
+ Math.abs(containerW - contentW) < 2 && (contentW = containerW);
+ Math.abs(containerH - contentH) < 2 && (contentH = containerH);
+
+ var viewport = cc.rect(Math.round((containerW - contentW) / 2),
+ Math.round((containerH - contentH) / 2),
+ contentW, contentH);
+
+ // Translate the content
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+ //TODO: modify something for setTransform
+ //cc._renderContext.translate(viewport.x, viewport.y + contentH);
+ }
+
+ this._result.scale = [scaleX, scaleY];
+ this._result.viewport = viewport;
+ return this._result;
+ },
+
+ /**
+ * Manipulation before applying the strategy
+ * @param {cc.view} view The target view
+ */
+ preApply: function (view) {
+ },
+
+ /**
+ * Function to apply this strategy
+ * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
+ * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
+ * @param {cc.view} view
+ * @param {cc.Size} designedResolution
+ * @return {object} scaleAndViewportRect
+ */
+ apply: function (view, designedResolution) {
+ return {"scale": [1, 1]};
+ },
+
+ /**
+ * Manipulation after applying the strategy
+ * @param {cc.view} view The target view
+ */
+ postApply: function (view) {
+ }
+});
+
+(function () {
+
+// Container scale strategys
+ /**
+ * @class
+ * @extends cc.ContainerStrategy
+ */
+ var EqualToFrame = cc.ContainerStrategy.extend({
+ apply: function (view) {
+ var frameH = view._frameSize.height, containerStyle = cc.container.style;
+ this._setupContainer(view, view._frameSize.width, view._frameSize.height);
+ // Setup container's margin and padding
+ if (view._isRotated) {
+ containerStyle.margin = '0 0 0 ' + frameH + 'px';
+ }
+ else {
+ containerStyle.margin = '0px';
+ }
+ }
+ });
+
+ /**
+ * @class
+ * @extends cc.ContainerStrategy
+ */
+ var ProportionalToFrame = cc.ContainerStrategy.extend({
+ apply: function (view, designedResolution) {
+ var frameW = view._frameSize.width, frameH = view._frameSize.height, containerStyle = cc.container.style,
+ designW = designedResolution.width, designH = designedResolution.height,
+ scaleX = frameW / designW, scaleY = frameH / designH,
+ containerW, containerH;
+
+ scaleX < scaleY ? (containerW = frameW, containerH = designH * scaleX) : (containerW = designW * scaleY, containerH = frameH);
+
+ // Adjust container size with integer value
+ var offx = Math.round((frameW - containerW) / 2);
+ var offy = Math.round((frameH - containerH) / 2);
+ containerW = frameW - 2 * offx;
+ containerH = frameH - 2 * offy;
+
+ this._setupContainer(view, containerW, containerH);
+ // Setup container's margin and padding
+ if (view._isRotated) {
+ containerStyle.margin = '0 0 0 ' + frameH + 'px';
+ }
+ else {
+ containerStyle.margin = '0px';
+ }
+ containerStyle.paddingLeft = offx + "px";
+ containerStyle.paddingRight = offx + "px";
+ containerStyle.paddingTop = offy + "px";
+ containerStyle.paddingBottom = offy + "px";
+ }
+ });
+
+ /**
+ * @class
+ * @extends EqualToFrame
+ */
+ var EqualToWindow = EqualToFrame.extend({
+ preApply: function (view) {
+ this._super(view);
+ view._frame = document.documentElement;
+ },
+
+ apply: function (view) {
+ this._super(view);
+ this._fixContainer();
+ }
+ });
+
+ /**
+ * @class
+ * @extends ProportionalToFrame
+ */
+ var ProportionalToWindow = ProportionalToFrame.extend({
+ preApply: function (view) {
+ this._super(view);
+ view._frame = document.documentElement;
+ },
+
+ apply: function (view, designedResolution) {
+ this._super(view, designedResolution);
+ this._fixContainer();
+ }
+ });
+
+ /**
+ * @class
+ * @extends cc.ContainerStrategy
+ */
+ var OriginalContainer = cc.ContainerStrategy.extend({
+ apply: function (view) {
+ this._setupContainer(view, cc._canvas.width, cc._canvas.height);
+ }
+ });
+
+// #NOT STABLE on Android# Alias: Strategy that makes the container's size equals to the window's size
+// cc.ContainerStrategy.EQUAL_TO_WINDOW = new EqualToWindow();
+// #NOT STABLE on Android# Alias: Strategy that scale proportionally the container's size to window's size
+// cc.ContainerStrategy.PROPORTION_TO_WINDOW = new ProportionalToWindow();
+// Alias: Strategy that makes the container's size equals to the frame's size
+ cc.ContainerStrategy.EQUAL_TO_FRAME = new EqualToFrame();
+// Alias: Strategy that scale proportionally the container's size to frame's size
+ cc.ContainerStrategy.PROPORTION_TO_FRAME = new ProportionalToFrame();
+// Alias: Strategy that keeps the original container's size
+ cc.ContainerStrategy.ORIGINAL_CONTAINER = new OriginalContainer();
+
+// Content scale strategys
+ var ExactFit = cc.ContentStrategy.extend({
+ apply: function (view, designedResolution) {
+ var containerW = cc._canvas.width, containerH = cc._canvas.height,
+ scaleX = containerW / designedResolution.width, scaleY = containerH / designedResolution.height;
+
+ return this._buildResult(containerW, containerH, containerW, containerH, scaleX, scaleY);
+ }
+ });
+
+ var ShowAll = cc.ContentStrategy.extend({
+ apply: function (view, designedResolution) {
+ var containerW = cc._canvas.width, containerH = cc._canvas.height,
+ designW = designedResolution.width, designH = designedResolution.height,
+ scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
+ contentW, contentH;
+
+ scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
+ : (scale = scaleY, contentW = designW * scale, contentH = containerH);
+
+ return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
+ }
+ });
+
+ var NoBorder = cc.ContentStrategy.extend({
+ apply: function (view, designedResolution) {
+ var containerW = cc._canvas.width, containerH = cc._canvas.height,
+ designW = designedResolution.width, designH = designedResolution.height,
+ scaleX = containerW / designW, scaleY = containerH / designH, scale,
+ contentW, contentH;
+
+ scaleX < scaleY ? (scale = scaleY, contentW = designW * scale, contentH = containerH)
+ : (scale = scaleX, contentW = containerW, contentH = designH * scale);
+
+ return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
+ }
+ });
+
+ var FixedHeight = cc.ContentStrategy.extend({
+ apply: function (view, designedResolution) {
+ var containerW = cc._canvas.width, containerH = cc._canvas.height,
+ designH = designedResolution.height, scale = containerH / designH,
+ contentW = containerW, contentH = containerH;
+
+ return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
+ },
+
+ postApply: function (view) {
+ cc.director._winSizeInPoints = view.getVisibleSize();
+ }
+ });
+
+ var FixedWidth = cc.ContentStrategy.extend({
+ apply: function (view, designedResolution) {
+ var containerW = cc._canvas.width, containerH = cc._canvas.height,
+ designW = designedResolution.width, scale = containerW / designW,
+ contentW = containerW, contentH = containerH;
+
+ return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
+ },
+
+ postApply: function (view) {
+ cc.director._winSizeInPoints = view.getVisibleSize();
+ }
+ });
+
+// Alias: Strategy to scale the content's size to container's size, non proportional
+ cc.ContentStrategy.EXACT_FIT = new ExactFit();
+// Alias: Strategy to scale the content's size proportionally to maximum size and keeps the whole content area to be visible
+ cc.ContentStrategy.SHOW_ALL = new ShowAll();
+// Alias: Strategy to scale the content's size proportionally to fill the whole container area
+ cc.ContentStrategy.NO_BORDER = new NoBorder();
+// Alias: Strategy to scale the content's height to container's height and proportionally scale its width
+ cc.ContentStrategy.FIXED_HEIGHT = new FixedHeight();
+// Alias: Strategy to scale the content's width to container's width and proportionally scale its height
+ cc.ContentStrategy.FIXED_WIDTH = new FixedWidth();
+
+})();
+
+/**
+ * cc.ResolutionPolicy class is the root strategy class of scale strategy,
+ * its main task is to maintain the compatibility with Cocos2d-x
+ *
+ * @class
+ * @extends cc.Class
+ * @param {cc.ContainerStrategy} containerStg The container strategy
+ * @param {cc.ContentStrategy} contentStg The content strategy
+ */
+cc.ResolutionPolicy = cc.Class.extend(/** @lends cc.ResolutionPolicy# */{
+ _containerStrategy: null,
+ _contentStrategy: null,
+
+ /**
+ * Constructor of cc.ResolutionPolicy
+ * @param {cc.ContainerStrategy} containerStg
+ * @param {cc.ContentStrategy} contentStg
+ */
+ ctor: function (containerStg, contentStg) {
+ this.setContainerStrategy(containerStg);
+ this.setContentStrategy(contentStg);
+ },
+
+ /**
+ * Manipulation before applying the resolution policy
+ * @param {cc.view} view The target view
+ */
+ preApply: function (view) {
+ this._containerStrategy.preApply(view);
+ this._contentStrategy.preApply(view);
+ },
+
+ /**
+ * Function to apply this resolution policy
+ * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
+ * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
+ * @param {cc.view} view The target view
+ * @param {cc.Size} designedResolution The user defined design resolution
+ * @return {object} An object contains the scale X/Y values and the viewport rect
+ */
+ apply: function (view, designedResolution) {
+ this._containerStrategy.apply(view, designedResolution);
+ return this._contentStrategy.apply(view, designedResolution);
+ },
+
+ /**
+ * Manipulation after appyling the strategy
+ * @param {cc.view} view The target view
+ */
+ postApply: function (view) {
+ this._containerStrategy.postApply(view);
+ this._contentStrategy.postApply(view);
+ },
+
+ /**
+ * Setup the container's scale strategy
+ * @param {cc.ContainerStrategy} containerStg
+ */
+ setContainerStrategy: function (containerStg) {
+ if (containerStg instanceof cc.ContainerStrategy)
+ this._containerStrategy = containerStg;
+ },
+
+ /**
+ * Setup the content's scale strategy
+ * @param {cc.ContentStrategy} contentStg
+ */
+ setContentStrategy: function (contentStg) {
+ if (contentStg instanceof cc.ContentStrategy)
+ this._contentStrategy = contentStg;
+ }
+});
+
+/**
+ * @memberOf cc.ResolutionPolicy#
+ * @name EXACT_FIT
+ * @constant
+ * @type Number
+ * @static
+ * The entire application is visible in the specified area without trying to preserve the original aspect ratio.
+ * Distortion can occur, and the application may appear stretched or compressed.
+ */
+cc.ResolutionPolicy.EXACT_FIT = 0;
+
+/**
+ * @memberOf cc.ResolutionPolicy#
+ * @name NO_BORDER
+ * @constant
+ * @type Number
+ * @static
+ * The entire application fills the specified area, without distortion but possibly with some cropping,
+ * while maintaining the original aspect ratio of the application.
+ */
+cc.ResolutionPolicy.NO_BORDER = 1;
+
+/**
+ * @memberOf cc.ResolutionPolicy#
+ * @name SHOW_ALL
+ * @constant
+ * @type Number
+ * @static
+ * The entire application is visible in the specified area without distortion while maintaining the original
+ * aspect ratio of the application. Borders can appear on two sides of the application.
+ */
+cc.ResolutionPolicy.SHOW_ALL = 2;
+
+/**
+ * @memberOf cc.ResolutionPolicy#
+ * @name FIXED_HEIGHT
+ * @constant
+ * @type Number
+ * @static
+ * The application takes the height of the design resolution size and modifies the width of the internal
+ * canvas so that it fits the aspect ratio of the device
+ * no distortion will occur however you must make sure your application works on different
+ * aspect ratios
+ */
+cc.ResolutionPolicy.FIXED_HEIGHT = 3;
+
+/**
+ * @memberOf cc.ResolutionPolicy#
+ * @name FIXED_WIDTH
+ * @constant
+ * @type Number
+ * @static
+ * The application takes the width of the design resolution size and modifies the height of the internal
+ * canvas so that it fits the aspect ratio of the device
+ * no distortion will occur however you must make sure your application works on different
+ * aspect ratios
+ */
+cc.ResolutionPolicy.FIXED_WIDTH = 4;
+
+/**
+ * @memberOf cc.ResolutionPolicy#
+ * @name UNKNOWN
+ * @constant
+ * @type Number
+ * @static
+ * Unknow policy
+ */
+cc.ResolutionPolicy.UNKNOWN = 5;
diff --git a/cocos2d/core/platform/CCInputExtension.js b/cocos2d/core/platform/CCInputExtension.js
new file mode 100644
index 0000000000..e61f58459a
--- /dev/null
+++ b/cocos2d/core/platform/CCInputExtension.js
@@ -0,0 +1,139 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+var _p = cc.inputManager;
+
+/**
+ * whether enable accelerometer event
+ * @function
+ * @param {Boolean} isEnable
+ */
+_p.setAccelerometerEnabled = function(isEnable){
+ var _t = this;
+ if(_t._accelEnabled === isEnable)
+ return;
+
+ _t._accelEnabled = isEnable;
+ var scheduler = cc.director.getScheduler();
+ if(_t._accelEnabled){
+ _t._accelCurTime = 0;
+ _t._registerAccelerometerEvent();
+ scheduler.scheduleUpdate(_t);
+ } else {
+ _t._accelCurTime = 0;
+ _t._unregisterAccelerometerEvent();
+ scheduler.unscheduleUpdate(_t);
+ }
+};
+
+/**
+ * set accelerometer interval value
+ * @function
+ * @param {Number} interval
+ */
+_p.setAccelerometerInterval = function(interval){
+ if (this._accelInterval !== interval) {
+ this._accelInterval = interval;
+ }
+};
+
+_p._registerKeyboardEvent = function(){
+ cc._canvas.addEventListener("keydown", function (e) {
+ cc.eventManager.dispatchEvent(new cc.EventKeyboard(e.keyCode, true));
+ e.stopPropagation();
+ e.preventDefault();
+ }, false);
+ cc._canvas.addEventListener("keyup", function (e) {
+ cc.eventManager.dispatchEvent(new cc.EventKeyboard(e.keyCode, false));
+ e.stopPropagation();
+ e.preventDefault();
+ }, false);
+};
+
+_p._registerAccelerometerEvent = function(){
+ var w = window, _t = this;
+ _t._acceleration = new cc.Acceleration();
+ _t._accelDeviceEvent = w.DeviceMotionEvent || w.DeviceOrientationEvent;
+
+ //TODO fix DeviceMotionEvent bug on QQ Browser version 4.1 and below.
+ if (cc.sys.browserType === cc.sys.BROWSER_TYPE_MOBILE_QQ)
+ _t._accelDeviceEvent = window.DeviceOrientationEvent;
+
+ var _deviceEventType = (_t._accelDeviceEvent === w.DeviceMotionEvent) ? "devicemotion" : "deviceorientation";
+ var ua = navigator.userAgent;
+ if (/Android/.test(ua) || (/Adr/.test(ua) && cc.sys.browserType === cc.BROWSER_TYPE_UC)) {
+ _t._minus = -1;
+ }
+
+ _t.didAccelerateCallback = _t.didAccelerate.bind(_t);
+ w.addEventListener(_deviceEventType, _t.didAccelerateCallback, false);
+};
+
+_p._unregisterAccelerometerEvent = function () {
+ this._acceleration = null;
+ var _deviceEventType = (this._accelDeviceEvent === window.DeviceMotionEvent) ? "devicemotion" : "deviceorientation";
+ window.removeEventListener(_deviceEventType, this.didAccelerateCallback, false);
+};
+
+_p.didAccelerate = function (eventData) {
+ var _t = this, w = window;
+ if (!_t._accelEnabled)
+ return;
+
+ var mAcceleration = _t._acceleration;
+
+ var x, y, z;
+
+ if (_t._accelDeviceEvent === window.DeviceMotionEvent) {
+ var eventAcceleration = eventData["accelerationIncludingGravity"];
+ x = _t._accelMinus * eventAcceleration.x * 0.1;
+ y = _t._accelMinus * eventAcceleration.y * 0.1;
+ z = eventAcceleration.z * 0.1;
+ } else {
+ x = (eventData["gamma"] / 90) * 0.981;
+ y = -(eventData["beta"] / 90) * 0.981;
+ z = (eventData["alpha"] / 90) * 0.981;
+ }
+
+ mAcceleration.x = x;
+ mAcceleration.y = y;
+ mAcceleration.z = z;
+
+ mAcceleration.timestamp = eventData.timeStamp || Date.now();
+
+ var tmpX = mAcceleration.x;
+ if(w.orientation === cc.UIInterfaceOrientationLandscapeRight){
+ mAcceleration.x = -mAcceleration.y;
+ mAcceleration.y = tmpX;
+ }else if(w.orientation === cc.UIInterfaceOrientationLandscapeLeft){
+ mAcceleration.x = mAcceleration.y;
+ mAcceleration.y = -tmpX;
+ }else if(w.orientation === cc.UIInterfaceOrientationPortraitUpsideDown){
+ mAcceleration.x = -mAcceleration.x;
+ mAcceleration.y = -mAcceleration.y;
+ }
+};
+
+delete _p;
\ No newline at end of file
diff --git a/cocos2d/core/platform/CCInputManager.js b/cocos2d/core/platform/CCInputManager.js
new file mode 100644
index 0000000000..270c535c7d
--- /dev/null
+++ b/cocos2d/core/platform/CCInputManager.js
@@ -0,0 +1,630 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * ignore
+ */
+
+/**
+ * @constant
+ * @type {number}
+ */
+cc.UIInterfaceOrientationLandscapeLeft = -90;
+/**
+ * @constant
+ * @type {number}
+ */
+cc.UIInterfaceOrientationLandscapeRight = 90;
+/**
+ * @constant
+ * @type {number}
+ */
+cc.UIInterfaceOrientationPortraitUpsideDown = 180;
+/**
+ * @constant
+ * @type {number}
+ */
+cc.UIInterfaceOrientationPortrait = 0;
+
+/**
+ *
+ * This class manages all events of input. include: touch, mouse, accelerometer, keyboard
+ *
+ * @class
+ * @name cc.inputManager
+ */
+cc.inputManager = /** @lends cc.inputManager# */{
+ TOUCH_TIMEOUT: 5000,
+
+ _mousePressed: false,
+
+ _isRegisterEvent: false,
+
+ _preTouchPoint: cc.p(0, 0),
+ _prevMousePoint: cc.p(0, 0),
+
+ _preTouchPool: [],
+ _preTouchPoolPointer: 0,
+
+ _touches: [],
+ _touchesIntegerDict: {},
+
+ _indexBitsUsed: 0,
+ _maxTouches: 5,
+
+ _accelEnabled: false,
+ _accelInterval: 1 / 30,
+ _accelMinus: 1,
+ _accelCurTime: 0,
+ _acceleration: null,
+ _accelDeviceEvent: null,
+
+ _getUnUsedIndex: function () {
+ var temp = this._indexBitsUsed;
+ var now = cc.sys.now();
+
+ for (var i = 0; i < this._maxTouches; i++) {
+ if (!(temp & 0x00000001)) {
+ this._indexBitsUsed |= (1 << i);
+ return i;
+ }
+ else {
+ var touch = this._touches[i];
+ if (now - touch._lastModified > this.TOUCH_TIMEOUT) {
+ this._removeUsedIndexBit(i);
+ delete this._touchesIntegerDict[touch.getID()];
+ return i;
+ }
+ }
+ temp >>= 1;
+ }
+
+ // all bits are used
+ return -1;
+ },
+
+ _removeUsedIndexBit: function (index) {
+ if (index < 0 || index >= this._maxTouches)
+ return;
+
+ var temp = 1 << index;
+ temp = ~temp;
+ this._indexBitsUsed &= temp;
+ },
+
+ _glView: null,
+
+ /**
+ * @function
+ * @param {Array} touches
+ */
+ handleTouchesBegin: function (touches) {
+ var selTouch, index, curTouch, touchID,
+ handleTouches = [], locTouchIntDict = this._touchesIntegerDict,
+ now = cc.sys.now();
+ for (var i = 0, len = touches.length; i < len; i++) {
+ selTouch = touches[i];
+ touchID = selTouch.getID();
+ index = locTouchIntDict[touchID];
+
+ if (index == null) {
+ var unusedIndex = this._getUnUsedIndex();
+ if (unusedIndex === -1) {
+ cc.log(cc._LogInfos.inputManager_handleTouchesBegin, unusedIndex);
+ continue;
+ }
+ //curTouch = this._touches[unusedIndex] = selTouch;
+ curTouch = this._touches[unusedIndex] = new cc.Touch(selTouch._point.x, selTouch._point.y, selTouch.getID());
+ curTouch._lastModified = now;
+ curTouch._setPrevPoint(selTouch._prevPoint);
+ locTouchIntDict[touchID] = unusedIndex;
+ handleTouches.push(curTouch);
+ }
+ }
+ if (handleTouches.length > 0) {
+ this._glView._convertTouchesWithScale(handleTouches);
+ var touchEvent = new cc.EventTouch(handleTouches);
+ touchEvent._eventCode = cc.EventTouch.EventCode.BEGAN;
+ cc.eventManager.dispatchEvent(touchEvent);
+ }
+ },
+
+ /**
+ * @function
+ * @param {Array} touches
+ */
+ handleTouchesMove: function (touches) {
+ var selTouch, index, touchID,
+ handleTouches = [], locTouches = this._touches,
+ now = cc.sys.now();
+ for (var i = 0, len = touches.length; i < len; i++) {
+ selTouch = touches[i];
+ touchID = selTouch.getID();
+ index = this._touchesIntegerDict[touchID];
+
+ if (index == null) {
+ //cc.log("if the index doesn't exist, it is an error");
+ continue;
+ }
+ if (locTouches[index]) {
+ locTouches[index]._setPoint(selTouch._point);
+ locTouches[index]._setPrevPoint(selTouch._prevPoint);
+ locTouches[index]._lastModified = now;
+ handleTouches.push(locTouches[index]);
+ }
+ }
+ if (handleTouches.length > 0) {
+ this._glView._convertTouchesWithScale(handleTouches);
+ var touchEvent = new cc.EventTouch(handleTouches);
+ touchEvent._eventCode = cc.EventTouch.EventCode.MOVED;
+ cc.eventManager.dispatchEvent(touchEvent);
+ }
+ },
+
+ /**
+ * @function
+ * @param {Array} touches
+ */
+ handleTouchesEnd: function (touches) {
+ var handleTouches = this.getSetOfTouchesEndOrCancel(touches);
+ if (handleTouches.length > 0) {
+ this._glView._convertTouchesWithScale(handleTouches);
+ var touchEvent = new cc.EventTouch(handleTouches);
+ touchEvent._eventCode = cc.EventTouch.EventCode.ENDED;
+ cc.eventManager.dispatchEvent(touchEvent);
+ }
+ },
+
+ /**
+ * @function
+ * @param {Array} touches
+ */
+ handleTouchesCancel: function (touches) {
+ var handleTouches = this.getSetOfTouchesEndOrCancel(touches);
+ if (handleTouches.length > 0) {
+ this._glView._convertTouchesWithScale(handleTouches);
+ var touchEvent = new cc.EventTouch(handleTouches);
+ touchEvent._eventCode = cc.EventTouch.EventCode.CANCELLED;
+ cc.eventManager.dispatchEvent(touchEvent);
+ }
+ },
+
+ /**
+ * @function
+ * @param {Array} touches
+ * @returns {Array}
+ */
+ getSetOfTouchesEndOrCancel: function (touches) {
+ var selTouch, index, touchID, handleTouches = [], locTouches = this._touches, locTouchesIntDict = this._touchesIntegerDict;
+ for (var i = 0, len = touches.length; i < len; i++) {
+ selTouch = touches[i];
+ touchID = selTouch.getID();
+ index = locTouchesIntDict[touchID];
+
+ if (index == null) {
+ continue; //cc.log("if the index doesn't exist, it is an error");
+ }
+ if (locTouches[index]) {
+ locTouches[index]._setPoint(selTouch._point);
+ locTouches[index]._setPrevPoint(selTouch._prevPoint);
+ handleTouches.push(locTouches[index]);
+ this._removeUsedIndexBit(index);
+ delete locTouchesIntDict[touchID];
+ }
+ }
+ return handleTouches;
+ },
+
+ /**
+ * @function
+ * @param {HTMLElement} element
+ * @return {Object}
+ */
+ getHTMLElementPosition: function (element) {
+ var docElem = document.documentElement;
+ var win = window;
+ var box = null;
+ if (cc.isFunction(element.getBoundingClientRect)) {
+ box = element.getBoundingClientRect();
+ } else {
+ box = {
+ left: 0,
+ top: 0,
+ width: parseInt(element.style.width),
+ height: parseInt(element.style.height)
+ };
+ }
+ return {
+ left: box.left + win.pageXOffset - docElem.clientLeft,
+ top: box.top + win.pageYOffset - docElem.clientTop,
+ width: box.width,
+ height: box.height
+ };
+ },
+
+ /**
+ * @function
+ * @param {cc.Touch} touch
+ * @return {cc.Touch}
+ */
+ getPreTouch: function (touch) {
+ var preTouch = null;
+ var locPreTouchPool = this._preTouchPool;
+ var id = touch.getID();
+ for (var i = locPreTouchPool.length - 1; i >= 0; i--) {
+ if (locPreTouchPool[i].getID() === id) {
+ preTouch = locPreTouchPool[i];
+ break;
+ }
+ }
+ if (!preTouch)
+ preTouch = touch;
+ return preTouch;
+ },
+
+ /**
+ * @function
+ * @param {cc.Touch} touch
+ */
+ setPreTouch: function (touch) {
+ var find = false;
+ var locPreTouchPool = this._preTouchPool;
+ var id = touch.getID();
+ for (var i = locPreTouchPool.length - 1; i >= 0; i--) {
+ if (locPreTouchPool[i].getID() === id) {
+ locPreTouchPool[i] = touch;
+ find = true;
+ break;
+ }
+ }
+ if (!find) {
+ if (locPreTouchPool.length <= 50) {
+ locPreTouchPool.push(touch);
+ } else {
+ locPreTouchPool[this._preTouchPoolPointer] = touch;
+ this._preTouchPoolPointer = (this._preTouchPoolPointer + 1) % 50;
+ }
+ }
+ },
+
+ /**
+ * @function
+ * @param {Number} tx
+ * @param {Number} ty
+ * @param {cc.Point} pos
+ * @return {cc.Touch}
+ */
+ getTouchByXY: function (tx, ty, pos) {
+ var locPreTouch = this._preTouchPoint;
+ var location = this._glView.convertToLocationInView(tx, ty, pos);
+ var touch = new cc.Touch(location.x, location.y);
+ touch._setPrevPoint(locPreTouch.x, locPreTouch.y);
+ locPreTouch.x = location.x;
+ locPreTouch.y = location.y;
+ return touch;
+ },
+
+ /**
+ * @function
+ * @param {cc.Point} location
+ * @param {cc.Point} pos
+ * @param {Number} eventType
+ * @returns {cc.EventMouse}
+ */
+ getMouseEvent: function (location, pos, eventType) {
+ var locPreMouse = this._prevMousePoint;
+ this._glView._convertMouseToLocationInView(location, pos);
+ var mouseEvent = new cc.EventMouse(eventType);
+ mouseEvent.setLocation(location.x, location.y);
+ mouseEvent._setPrevCursor(locPreMouse.x, locPreMouse.y);
+ locPreMouse.x = location.x;
+ locPreMouse.y = location.y;
+ return mouseEvent;
+ },
+
+ /**
+ * @function
+ * @param {Touch} event
+ * @param {cc.Point} pos
+ * @return {cc.Point}
+ */
+ getPointByEvent: function (event, pos) {
+ if (event.pageX != null) //not available in <= IE8
+ return {x: event.pageX, y: event.pageY};
+
+ pos.left -= document.body.scrollLeft;
+ pos.top -= document.body.scrollTop;
+ return {x: event.clientX, y: event.clientY};
+ },
+
+ /**
+ * @function
+ * @param {Touch} event
+ * @param {cc.Point} pos
+ * @returns {Array}
+ */
+ getTouchesByEvent: function (event, pos) {
+ var touchArr = [], locView = this._glView;
+ var touch_event, touch, preLocation;
+ var locPreTouch = this._preTouchPoint;
+
+ var length = event.changedTouches.length;
+ for (var i = 0; i < length; i++) {
+ touch_event = event.changedTouches[i];
+ if (touch_event) {
+ var location;
+ if (cc.sys.BROWSER_TYPE_FIREFOX === cc.sys.browserType)
+ location = locView.convertToLocationInView(touch_event.pageX, touch_event.pageY, pos);
+ else
+ location = locView.convertToLocationInView(touch_event.clientX, touch_event.clientY, pos);
+ if (touch_event.identifier != null) {
+ touch = new cc.Touch(location.x, location.y, touch_event.identifier);
+ //use Touch Pool
+ preLocation = this.getPreTouch(touch).getLocation();
+ touch._setPrevPoint(preLocation.x, preLocation.y);
+ this.setPreTouch(touch);
+ } else {
+ touch = new cc.Touch(location.x, location.y);
+ touch._setPrevPoint(locPreTouch.x, locPreTouch.y);
+ }
+ locPreTouch.x = location.x;
+ locPreTouch.y = location.y;
+ touchArr.push(touch);
+ }
+ }
+ return touchArr;
+ },
+
+ /**
+ * @function
+ * @param {HTMLElement} element
+ */
+ registerSystemEvent: function (element) {
+ if (this._isRegisterEvent) return;
+
+ var locView = this._glView = cc.view;
+ var selfPointer = this;
+ var supportMouse = ('mouse' in cc.sys.capabilities), supportTouches = ('touches' in cc.sys.capabilities);
+
+ //HACK
+ // - At the same time to trigger the ontouch event and onmouse event
+ // - The function will execute 2 times
+ //The known browser:
+ // liebiao
+ // miui
+ // WECHAT
+ var prohibition = false;
+ if (cc.sys.isMobile)
+ prohibition = true;
+
+ //register touch event
+ if (supportMouse) {
+ window.addEventListener('mousedown', function () {
+ selfPointer._mousePressed = true;
+ }, false);
+
+ window.addEventListener('mouseup', function (event) {
+ if (prohibition) return;
+ var savePressed = selfPointer._mousePressed;
+ selfPointer._mousePressed = false;
+
+ if (!savePressed)
+ return;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ var location = selfPointer.getPointByEvent(event, pos);
+ if (!cc.rectContainsPoint(new cc.Rect(pos.left, pos.top, pos.width, pos.height), location)) {
+ selfPointer.handleTouchesEnd([selfPointer.getTouchByXY(location.x, location.y, pos)]);
+
+ var mouseEvent = selfPointer.getMouseEvent(location, pos, cc.EventMouse.UP);
+ mouseEvent.setButton(event.button);
+ cc.eventManager.dispatchEvent(mouseEvent);
+ }
+ }, false);
+
+ //register canvas mouse event
+ element.addEventListener("mousedown", function (event) {
+ if (prohibition) return;
+ selfPointer._mousePressed = true;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ var location = selfPointer.getPointByEvent(event, pos);
+
+ selfPointer.handleTouchesBegin([selfPointer.getTouchByXY(location.x, location.y, pos)]);
+
+ var mouseEvent = selfPointer.getMouseEvent(location, pos, cc.EventMouse.DOWN);
+ mouseEvent.setButton(event.button);
+ cc.eventManager.dispatchEvent(mouseEvent);
+
+ event.stopPropagation();
+ event.preventDefault();
+ element.focus();
+ }, false);
+
+ element.addEventListener("mouseup", function (event) {
+ if (prohibition) return;
+ selfPointer._mousePressed = false;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ var location = selfPointer.getPointByEvent(event, pos);
+
+ selfPointer.handleTouchesEnd([selfPointer.getTouchByXY(location.x, location.y, pos)]);
+
+ var mouseEvent = selfPointer.getMouseEvent(location, pos, cc.EventMouse.UP);
+ mouseEvent.setButton(event.button);
+ cc.eventManager.dispatchEvent(mouseEvent);
+
+ event.stopPropagation();
+ event.preventDefault();
+ }, false);
+
+ element.addEventListener("mousemove", function (event) {
+ if (prohibition) return;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ var location = selfPointer.getPointByEvent(event, pos);
+
+ selfPointer.handleTouchesMove([selfPointer.getTouchByXY(location.x, location.y, pos)]);
+
+ var mouseEvent = selfPointer.getMouseEvent(location, pos, cc.EventMouse.MOVE);
+ if (selfPointer._mousePressed)
+ mouseEvent.setButton(event.button);
+ else
+ mouseEvent.setButton(null);
+ cc.eventManager.dispatchEvent(mouseEvent);
+
+ event.stopPropagation();
+ event.preventDefault();
+ }, false);
+
+ element.addEventListener("mousewheel", function (event) {
+ var pos = selfPointer.getHTMLElementPosition(element);
+ var location = selfPointer.getPointByEvent(event, pos);
+
+ var mouseEvent = selfPointer.getMouseEvent(location, pos, cc.EventMouse.SCROLL);
+ mouseEvent.setButton(event.button);
+ mouseEvent.setScrollData(0, event.wheelDelta);
+ cc.eventManager.dispatchEvent(mouseEvent);
+
+ event.stopPropagation();
+ event.preventDefault();
+ }, false);
+
+ /* firefox fix */
+ element.addEventListener("DOMMouseScroll", function (event) {
+ var pos = selfPointer.getHTMLElementPosition(element);
+ var location = selfPointer.getPointByEvent(event, pos);
+
+ var mouseEvent = selfPointer.getMouseEvent(location, pos, cc.EventMouse.SCROLL);
+ mouseEvent.setButton(event.button);
+ mouseEvent.setScrollData(0, event.detail * -120);
+ cc.eventManager.dispatchEvent(mouseEvent);
+
+ event.stopPropagation();
+ event.preventDefault();
+ }, false);
+ }
+
+ if (window.navigator.msPointerEnabled) {
+ var _pointerEventsMap = {
+ "MSPointerDown": selfPointer.handleTouchesBegin,
+ "MSPointerMove": selfPointer.handleTouchesMove,
+ "MSPointerUp": selfPointer.handleTouchesEnd,
+ "MSPointerCancel": selfPointer.handleTouchesCancel
+ };
+
+ for (var eventName in _pointerEventsMap) {
+ (function (_pointerEvent, _touchEvent) {
+ element.addEventListener(_pointerEvent, function (event) {
+ var pos = selfPointer.getHTMLElementPosition(element);
+ pos.left -= document.documentElement.scrollLeft;
+ pos.top -= document.documentElement.scrollTop;
+
+ _touchEvent.call(selfPointer, [selfPointer.getTouchByXY(event.clientX, event.clientY, pos)]);
+ event.stopPropagation();
+ }, false);
+ })(eventName, _pointerEventsMap[eventName]);
+ }
+ }
+
+ if (supportTouches) {
+ //register canvas touch event
+ element.addEventListener("touchstart", function (event) {
+ if (!event.changedTouches) return;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ pos.left -= document.body.scrollLeft;
+ pos.top -= document.body.scrollTop;
+ selfPointer.handleTouchesBegin(selfPointer.getTouchesByEvent(event, pos));
+ event.stopPropagation();
+ event.preventDefault();
+ element.focus();
+ }, false);
+
+ element.addEventListener("touchmove", function (event) {
+ if (!event.changedTouches) return;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ pos.left -= document.body.scrollLeft;
+ pos.top -= document.body.scrollTop;
+ selfPointer.handleTouchesMove(selfPointer.getTouchesByEvent(event, pos));
+ event.stopPropagation();
+ event.preventDefault();
+ }, false);
+
+ element.addEventListener("touchend", function (event) {
+ if (!event.changedTouches) return;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ pos.left -= document.body.scrollLeft;
+ pos.top -= document.body.scrollTop;
+ selfPointer.handleTouchesEnd(selfPointer.getTouchesByEvent(event, pos));
+ event.stopPropagation();
+ event.preventDefault();
+ }, false);
+
+ element.addEventListener("touchcancel", function (event) {
+ if (!event.changedTouches) return;
+
+ var pos = selfPointer.getHTMLElementPosition(element);
+ pos.left -= document.body.scrollLeft;
+ pos.top -= document.body.scrollTop;
+ selfPointer.handleTouchesCancel(selfPointer.getTouchesByEvent(event, pos));
+ event.stopPropagation();
+ event.preventDefault();
+ }, false);
+ }
+
+ //register keyboard event
+ this._registerKeyboardEvent();
+
+ //register Accelerometer event
+ // this._registerAccelerometerEvent();
+
+ this._isRegisterEvent = true;
+ },
+
+ _registerKeyboardEvent: function () {
+ },
+
+ /**
+ * Register Accelerometer event
+ * @function
+ */
+ _registerAccelerometerEvent: function () {
+ },
+
+ /**
+ * @function
+ * @param {Number} dt
+ */
+ update: function (dt) {
+ if (this._accelCurTime > this._accelInterval) {
+ this._accelCurTime -= this._accelInterval;
+ cc.eventManager.dispatchEvent(new cc.EventAcceleration(this._acceleration));
+ }
+ this._accelCurTime += dt;
+ }
+};
diff --git a/cocos2d/core/platform/CCLoaders.js b/cocos2d/core/platform/CCLoaders.js
new file mode 100644
index 0000000000..16749a0949
--- /dev/null
+++ b/cocos2d/core/platform/CCLoaders.js
@@ -0,0 +1,163 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc._txtLoader = {
+ load: function (realUrl, url, res, cb) {
+ cc.loader.loadTxt(realUrl, cb);
+ }
+};
+cc.loader.register(["txt", "xml", "vsh", "fsh", "atlas"], cc._txtLoader);
+
+cc._jsonLoader = {
+ load: function (realUrl, url, res, cb) {
+ cc.loader.loadJson(realUrl, cb);
+ }
+};
+cc.loader.register(["json", "ExportJson"], cc._jsonLoader);
+
+cc._jsLoader = {
+ load: function (realUrl, url, res, cb) {
+ cc.loader.loadJs(realUrl, cb);
+ }
+};
+cc.loader.register(["js"], cc._jsLoader);
+
+cc._imgLoader = {
+ load: function (realUrl, url, res, cb) {
+ var callback;
+ if (cc.loader.isLoading(realUrl)) {
+ callback = function (err, img) {
+ if (err)
+ return cb(err);
+ var tex = cc.textureCache.getTextureForKey(url) || cc.textureCache.handleLoadedTexture(url, img);
+ cb(null, tex);
+ };
+ }
+ else {
+ callback = function (err, img) {
+ if (err)
+ return cb(err);
+ var tex = cc.textureCache.handleLoadedTexture(url, img);
+ cb(null, tex);
+ };
+ }
+ cc.loader.loadImg(realUrl, callback);
+ }
+};
+cc.loader.register(["png", "jpg", "bmp", "jpeg", "gif", "ico", "tiff", "webp"], cc._imgLoader);
+cc._serverImgLoader = {
+ load: function (realUrl, url, res, cb) {
+ cc._imgLoader.load(res.src, url, res, cb);
+ }
+};
+cc.loader.register(["serverImg"], cc._serverImgLoader);
+
+cc._plistLoader = {
+ load: function (realUrl, url, res, cb) {
+ cc.loader.loadTxt(realUrl, function (err, txt) {
+ if (err)
+ return cb(err);
+ cb(null, cc.plistParser.parse(txt));
+ });
+ }
+};
+cc.loader.register(["plist"], cc._plistLoader);
+
+cc._fontLoader = {
+ TYPE: {
+ ".eot": "embedded-opentype",
+ ".ttf": "truetype",
+ ".ttc": "truetype",
+ ".woff": "woff",
+ ".svg": "svg"
+ },
+ _loadFont: function (name, srcs, type) {
+ var doc = document, path = cc.path, TYPE = this.TYPE, fontStyle = document.createElement("style");
+ fontStyle.type = "text/css";
+ doc.body.appendChild(fontStyle);
+
+ var fontStr = "";
+ if (isNaN(name - 0))
+ fontStr += "@font-face { font-family:" + name + "; src:";
+ else
+ fontStr += "@font-face { font-family:'" + name + "'; src:";
+ if (srcs instanceof Array) {
+ for (var i = 0, li = srcs.length; i < li; i++) {
+ var src = srcs[i];
+ type = path.extname(src).toLowerCase();
+ fontStr += "url('" + srcs[i] + "') format('" + TYPE[type] + "')";
+ fontStr += (i === li - 1) ? ";" : ",";
+ }
+ } else {
+ type = type.toLowerCase();
+ fontStr += "url('" + srcs + "') format('" + TYPE[type] + "');";
+ }
+ fontStyle.textContent += fontStr + "}";
+
+ //.
+ var preloadDiv = document.createElement("div");
+ var _divStyle = preloadDiv.style;
+ _divStyle.fontFamily = name;
+ preloadDiv.innerHTML = ".";
+ _divStyle.position = "absolute";
+ _divStyle.left = "-100px";
+ _divStyle.top = "-100px";
+ doc.body.appendChild(preloadDiv);
+ },
+ load: function (realUrl, url, res, cb) {
+ var self = this;
+ var type = res.type, name = res.name, srcs = res.srcs;
+ if (cc.isString(res)) {
+ type = cc.path.extname(res);
+ name = cc.path.basename(res, type);
+ self._loadFont(name, res, type);
+ } else {
+ self._loadFont(name, srcs);
+ }
+ if (document.fonts) {
+ document.fonts.load("1em " + name).then(function () {
+ cb(null, true);
+ }, function (err) {
+ cb(err);
+ });
+ } else {
+ cb(null, true);
+ }
+ }
+};
+cc.loader.register(["font", "eot", "ttf", "woff", "svg", "ttc"], cc._fontLoader);
+
+cc._binaryLoader = {
+ load: function (realUrl, url, res, cb) {
+ cc.loader.loadBinary(realUrl, cb);
+ }
+};
+
+cc._csbLoader = {
+ load: function(realUrl, url, res, cb){
+ cc.loader.loadCsb(realUrl, cb);
+ }
+};
+cc.loader.register(["csb"], cc._csbLoader);
diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js
new file mode 100644
index 0000000000..a52958c3dc
--- /dev/null
+++ b/cocos2d/core/platform/CCMacro.js
@@ -0,0 +1,857 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.INVALID_INDEX = -1;
+
+/**
+ * PI is the ratio of a circle's circumference to its diameter.
+ * @constant
+ * @type Number
+ */
+cc.PI = Math.PI;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.FLT_MAX = parseFloat('3.402823466e+38F');
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.FLT_MIN = parseFloat("1.175494351e-38F");
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.RAD = cc.PI / 180;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.DEG = 180 / cc.PI;
+
+/**
+ * maximum unsigned int value
+ * @constant
+ * @type Number
+ */
+cc.UINT_MAX = 0xffffffff;
+
+/**
+ *
+ * simple macro that swaps 2 variables
+ * modified from c++ macro, you need to pass in the x and y variables names in string,
+ * and then a reference to the whole object as third variable
+ *
+ * @param {String} x
+ * @param {String} y
+ * @param {Object} ref
+ * @function
+ * @deprecated since v3.0
+ */
+cc.swap = function (x, y, ref) {
+ if (cc.isObject(ref) && !cc.isUndefined(ref.x) && !cc.isUndefined(ref.y)) {
+ var tmp = ref[x];
+ ref[x] = ref[y];
+ ref[y] = tmp;
+ } else
+ cc.log(cc._LogInfos.swap);
+};
+
+/**
+ *
+ * Linear interpolation between 2 numbers, the ratio sets how much it is biased to each end
+ *
+ * @param {Number} a number A
+ * @param {Number} b number B
+ * @param {Number} r ratio between 0 and 1
+ * @function
+ * @example
+ * cc.lerp(2,10,0.5)//returns 6
+ * cc.lerp(2,10,0.2)//returns 3.6
+ */
+cc.lerp = function (a, b, r) {
+ return a + (b - a) * r;
+};
+
+/**
+ * get a random number from 0 to 0xffffff
+ * @function
+ * @returns {number}
+ */
+cc.rand = function () {
+ return Math.random() * 0xffffff;
+};
+
+/**
+ * returns a random float between -1 and 1
+ * @return {Number}
+ * @function
+ */
+cc.randomMinus1To1 = function () {
+ return (Math.random() - 0.5) * 2;
+};
+
+/**
+ * returns a random float between 0 and 1
+ * @return {Number}
+ * @function
+ */
+cc.random0To1 = Math.random;
+
+/**
+ * converts degrees to radians
+ * @param {Number} angle
+ * @return {Number}
+ * @function
+ */
+cc.degreesToRadians = function (angle) {
+ return angle * cc.RAD;
+};
+
+/**
+ * converts radians to degrees
+ * @param {Number} angle
+ * @return {Number}
+ * @function
+ */
+cc.radiansToDegrees = function (angle) {
+ return angle * cc.DEG;
+};
+/**
+ * converts radians to degrees
+ * @param {Number} angle
+ * @return {Number}
+ * @function
+ */
+cc.radiansToDegress = function (angle) {
+ cc.log(cc._LogInfos.radiansToDegress);
+ return angle * cc.DEG;
+};
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.REPEAT_FOREVER = Number.MAX_VALUE - 1;
+
+/**
+ * Helpful macro that setups the GL server state, the correct GL program and sets the Model View Projection matrix
+ * @param {cc.Node} node setup node
+ * @function
+ */
+cc.nodeDrawSetup = function (node) {
+ //cc.glEnable(node._glServerState);
+ if (node._shaderProgram) {
+ //cc._renderContext.useProgram(node._shaderProgram._programObj);
+ node._glProgramState.apply();
+ node._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
+ }
+};
+
+/**
+ *
+ * GL states that are enabled:
+ * - GL_TEXTURE_2D
+ * - GL_VERTEX_ARRAY
+ * - GL_TEXTURE_COORD_ARRAY
+ * - GL_COLOR_ARRAY
+ *
+ * @function
+ */
+cc.enableDefaultGLStates = function () {
+ //TODO OPENGL STUFF
+ /*
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);*/
+};
+
+/**
+ *
+ * Disable default GL states:
+ * - GL_TEXTURE_2D
+ * - GL_TEXTURE_COORD_ARRAY
+ * - GL_COLOR_ARRAY
+ *
+ * @function
+ */
+cc.disableDefaultGLStates = function () {
+ //TODO OPENGL
+ /*
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ */
+};
+
+/**
+ *
+ * Increments the GL Draws counts by one.
+ * The number of calls per frame are displayed on the screen when the CCDirector's stats are enabled.
+ *
+ * @param {Number} addNumber
+ * @function
+ */
+cc.incrementGLDraws = function (addNumber) {
+ cc.g_NumberOfDraws += addNumber;
+};
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.FLT_EPSILON = 0.0000001192092896;
+
+/**
+ *
+ * On Mac it returns 1;
+ * On iPhone it returns 2 if RetinaDisplay is On. Otherwise it returns 1
+ *
+ * @return {Number}
+ * @function
+ */
+cc.contentScaleFactor = function () {
+ return cc.director._contentScaleFactor;
+};
+
+/**
+ * Converts a Point in points to pixels
+ * @param {cc.Point} points
+ * @return {cc.Point}
+ * @function
+ */
+cc.pointPointsToPixels = function (points) {
+ var scale = cc.contentScaleFactor();
+ return cc.p(points.x * scale, points.y * scale);
+};
+
+/**
+ * Converts a Point in pixels to points
+ * @param {cc.Rect} pixels
+ * @return {cc.Point}
+ * @function
+ */
+cc.pointPixelsToPoints = function (pixels) {
+ var scale = cc.contentScaleFactor();
+ return cc.p(pixels.x / scale, pixels.y / scale);
+};
+
+cc._pointPixelsToPointsOut = function(pixels, outPoint){
+ var scale = cc.contentScaleFactor();
+ outPoint.x = pixels.x / scale;
+ outPoint.y = pixels.y / scale;
+};
+
+/**
+ * Converts a Size in points to pixels
+ * @param {cc.Size} sizeInPoints
+ * @return {cc.Size}
+ * @function
+ */
+cc.sizePointsToPixels = function (sizeInPoints) {
+ var scale = cc.contentScaleFactor();
+ return cc.size(sizeInPoints.width * scale, sizeInPoints.height * scale);
+};
+
+/**
+ * Converts a size in pixels to points
+ * @param {cc.Size} sizeInPixels
+ * @return {cc.Size}
+ * @function
+ */
+cc.sizePixelsToPoints = function (sizeInPixels) {
+ var scale = cc.contentScaleFactor();
+ return cc.size(sizeInPixels.width / scale, sizeInPixels.height / scale);
+};
+
+cc._sizePixelsToPointsOut = function (sizeInPixels, outSize) {
+ var scale = cc.contentScaleFactor();
+ outSize.width = sizeInPixels.width / scale;
+ outSize.height = sizeInPixels.height / scale;
+};
+
+/**
+ * Converts a rect in pixels to points
+ * @param {cc.Rect} pixel
+ * @return {cc.Rect}
+ * @function
+ */
+cc.rectPixelsToPoints = function (pixel) {
+ var scale = cc.contentScaleFactor();
+ return cc.rect(pixel.x / scale, pixel.y / scale,
+ pixel.width / scale, pixel.height / scale);
+};
+
+/**
+ * Converts a rect in points to pixels
+ * @param {cc.Rect} point
+ * @return {cc.Rect}
+ * @function
+ */
+cc.rectPointsToPixels = function (point) {
+ var scale = cc.contentScaleFactor();
+ return cc.rect(point.x * scale, point.y * scale,
+ point.width * scale, point.height * scale);
+};
+
+//some gl constant variable
+/**
+ * @constant
+ * @type Number
+ */
+cc.ONE = 1;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ZERO = 0;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.SRC_ALPHA = 0x0302;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.SRC_ALPHA_SATURATE = 0x308;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.SRC_COLOR = 0x300;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.DST_ALPHA = 0x304;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.DST_COLOR = 0x306;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ONE_MINUS_SRC_ALPHA = 0x0303;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ONE_MINUS_SRC_COLOR = 0x301;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ONE_MINUS_DST_ALPHA = 0x305;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ONE_MINUS_DST_COLOR = 0x0307;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ONE_MINUS_CONSTANT_ALPHA = 0x8004;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ONE_MINUS_CONSTANT_COLOR = 0x8002;
+
+/**
+ * the constant variable equals gl.LINEAR for texture
+ * @constant
+ * @type Number
+ */
+cc.LINEAR = 0x2601;
+
+/**
+ * the constant variable equals gl.REPEAT for texture
+ * @constant
+ * @type Number
+ */
+cc.REPEAT = 0x2901;
+
+/**
+ * the constant variable equals gl.CLAMP_TO_EDGE for texture
+ * @constant
+ * @type Number
+ */
+cc.CLAMP_TO_EDGE = 0x812f;
+
+/**
+ * the constant variable equals gl.MIRRORED_REPEAT for texture
+ * @constant
+ * @type Number
+ */
+cc.MIRRORED_REPEAT = 0x8370;
+
+/**
+ * default gl blend src function. Compatible with premultiplied alpha images.
+ * @constant
+ * @name cc.BLEND_SRC
+ * @type Number
+ */
+cc.BLEND_SRC = cc.SRC_ALPHA;
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL
+ && cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA) {
+ cc.BLEND_SRC = cc.ONE;
+ }
+});
+
+/**
+ * default gl blend dst function. Compatible with premultiplied alpha images.
+ * @constant
+ * @type Number
+ */
+cc.BLEND_DST = cc.ONE_MINUS_SRC_ALPHA;
+
+/**
+ * Check webgl error.Error will be shown in console if exists.
+ * @function
+ */
+cc.checkGLErrorDebug = function () {
+ if (cc.renderMode === cc.game.RENDER_TYPE_WEBGL) {
+ var _error = cc._renderContext.getError();
+ if (_error) {
+ cc.log(cc._LogInfos.checkGLErrorDebug, _error);
+ }
+ }
+};
+
+//Possible device orientations
+/**
+ * Device oriented vertically, home button on the bottom (UIDeviceOrientationPortrait)
+ * @constant
+ * @type Number
+ */
+cc.ORIENTATION_PORTRAIT = 1;
+
+/**
+ * Device oriented horizontally, home button on the right (UIDeviceOrientationLandscapeLeft)
+ * @constant
+ * @type Number
+ */
+cc.ORIENTATION_LANDSCAPE = 2;
+
+/**
+ * Device oriented vertically, home button on the top (UIDeviceOrientationPortraitUpsideDown)
+ * @constant
+ * @type Number
+ */
+cc.ORIENTATION_AUTO = 3;
+
+/**
+ * The limit count for concurrency http request, useful in some mobile browsers
+ * Adjust its value with the test results based on your game, the preset value is just a placeholder
+ * @constant
+ * @type Number
+ */
+cc.CONCURRENCY_HTTP_REQUEST_COUNT = cc.sys.isMobile ? 20 : 0;
+
+/**
+ * The maximum vertex count for a single batched draw call.
+ * @constant
+ * @type Number
+ */
+cc.BATCH_VERTEX_COUNT = 2000;
+
+
+// ------------------- vertex attrib flags -----------------------------
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_FLAG_NONE = 0;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_FLAG_POSITION = 1 << 0;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_FLAG_COLOR = 1 << 1;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_FLAG_TEX_COORDS = 1 << 2;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX = ( cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS );
+
+/**
+ * GL server side states
+ * @constant
+ * @type {Number}
+ */
+cc.GL_ALL = 0;
+
+//-------------Vertex Attributes-----------
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_POSITION = 0;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_COLOR = 1;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_TEX_COORDS = 2;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.VERTEX_ATTRIB_MAX = 7;
+
+//------------Uniforms------------------
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_PMATRIX = 0;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_MVMATRIX = 1;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_MVPMATRIX = 2;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_TIME = 3;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_SINTIME = 4;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_COSTIME = 5;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_RANDOM01 = 6;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_SAMPLER = 7;
+/**
+ * @constant
+ * @type {Number}
+ */
+cc.UNIFORM_MAX = 8;
+
+//------------Shader Name---------------
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_TEXTURECOLOR = "ShaderPositionTextureColor";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_SPRITE_POSITION_TEXTURECOLOR = "ShaderSpritePositionTextureColor";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_SPRITE_POSITION_TEXTURECOLOR_GRAY = "ShaderSpritePositionTextureColorGray";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_TEXTURECOLORALPHATEST = "ShaderPositionTextureColorAlphaTest";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST = "ShaderSpritePositionTextureColorAlphaTest";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_COLOR = "ShaderPositionColor";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_SPRITE_POSITION_COLOR = "ShaderSpritePositionColor";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_TEXTURE = "ShaderPositionTexture";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_TEXTURE_UCOLOR = "ShaderPositionTextureUColor";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_TEXTUREA8COLOR = "ShaderPositionTextureA8Color";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_UCOLOR = "ShaderPositionUColor";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_POSITION_LENGTHTEXTURECOLOR = "ShaderPositionLengthTextureColor";
+
+//------------uniform names----------------
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_PMATRIX_S = "CC_PMatrix";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_MVMATRIX_S = "CC_MVMatrix";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_MVPMATRIX_S = "CC_MVPMatrix";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_TIME_S = "CC_Time";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_SINTIME_S = "CC_SinTime";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_COSTIME_S = "CC_CosTime";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_RANDOM01_S = "CC_Random01";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_SAMPLER_S = "CC_Texture0";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.UNIFORM_ALPHA_TEST_VALUE_S = "CC_alpha_value";
+
+//------------Attribute names--------------
+/**
+ * @constant
+ * @type {String}
+ */
+cc.ATTRIBUTE_NAME_COLOR = "a_color";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.ATTRIBUTE_NAME_POSITION = "a_position";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.ATTRIBUTE_NAME_TEX_COORD = "a_texCoord";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.ATTRIBUTE_NAME_MVMAT = "a_mvMatrix";
+
+
+/**
+ * default size for font size
+ * @constant
+ * @type Number
+ */
+cc.ITEM_SIZE = 32;
+
+/**
+ * default tag for current item
+ * @constant
+ * @type Number
+ */
+cc.CURRENT_ITEM = 0xc0c05001;
+/**
+ * default tag for zoom action tag
+ * @constant
+ * @type Number
+ */
+cc.ZOOM_ACTION_TAG = 0xc0c05002;
+/**
+ * default tag for normal
+ * @constant
+ * @type Number
+ */
+cc.NORMAL_TAG = 8801;
+
+/**
+ * default selected tag
+ * @constant
+ * @type Number
+ */
+cc.SELECTED_TAG = 8802;
+
+/**
+ * default disabled tag
+ * @constant
+ * @type Number
+ */
+cc.DISABLE_TAG = 8803;
+
+
+// Array utils
+
+/**
+ * Verify Array's Type
+ * @param {Array} arr
+ * @param {function} type
+ * @return {Boolean}
+ * @function
+ */
+cc.arrayVerifyType = function (arr, type) {
+ if (arr && arr.length > 0) {
+ for (var i = 0; i < arr.length; i++) {
+ if (!(arr[i] instanceof type)) {
+ cc.log("element type is wrong!");
+ return false;
+ }
+ }
+ }
+ return true;
+};
+
+/**
+ * Searches for the first occurrence of object and removes it. If object is not found the function has no effect.
+ * @function
+ * @param {Array} arr Source Array
+ * @param {*} delObj remove object
+ */
+cc.arrayRemoveObject = function (arr, delObj) {
+ for (var i = 0, l = arr.length; i < l; i++) {
+ if (arr[i] === delObj) {
+ arr.splice(i, 1);
+ break;
+ }
+ }
+};
+
+/**
+ * Removes from arr all values in minusArr. For each Value in minusArr, the first matching instance in arr will be removed.
+ * @function
+ * @param {Array} arr Source Array
+ * @param {Array} minusArr minus Array
+ */
+cc.arrayRemoveArray = function (arr, minusArr) {
+ for (var i = 0, l = minusArr.length; i < l; i++) {
+ cc.arrayRemoveObject(arr, minusArr[i]);
+ }
+};
+
+/**
+ * Inserts some objects at index
+ * @function
+ * @param {Array} arr
+ * @param {Array} addObjs
+ * @param {Number} index
+ * @return {Array}
+ */
+cc.arrayAppendObjectsToIndex = function(arr, addObjs,index){
+ arr.splice.apply(arr, [index, 0].concat(addObjs));
+ return arr;
+};
+
+/**
+ * Copy an array's item to a new array (its performance is better than Array.slice)
+ * @param {Array} arr
+ * @return {Array}
+ */
+cc.copyArray = function(arr){
+ var i, len = arr.length, arr_clone = new Array(len);
+ for (i = 0; i < len; i += 1)
+ arr_clone[i] = arr[i];
+ return arr_clone;
+};
diff --git a/cocos2d/core/platform/CCSAXParser.js b/cocos2d/core/platform/CCSAXParser.js
new file mode 100644
index 0000000000..f5049623f5
--- /dev/null
+++ b/cocos2d/core/platform/CCSAXParser.js
@@ -0,0 +1,170 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * A SAX Parser
+ * @class
+ * @name cc.saxParser
+ * @extends cc.Class
+ */
+cc.SAXParser = cc.Class.extend(/** @lends cc.saxParser# */{
+ _parser: null,
+ _isSupportDOMParser: null,
+
+ /**
+ * Constructor of cc.SAXParser
+ */
+ ctor: function () {
+ if (window.DOMParser) {
+ this._isSupportDOMParser = true;
+ this._parser = new DOMParser();
+ } else {
+ this._isSupportDOMParser = false;
+ }
+ },
+
+ /**
+ * @function
+ * @param {String} xmlTxt
+ * @return {Document}
+ */
+ parse : function(xmlTxt){
+ return this._parseXML(xmlTxt);
+ },
+
+ _parseXML: function (textxml) {
+ // get a reference to the requested corresponding xml file
+ var xmlDoc;
+ if (this._isSupportDOMParser) {
+ xmlDoc = this._parser.parseFromString(textxml, "text/xml");
+ } else {
+ // Internet Explorer (untested!)
+ xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.async = "false";
+ xmlDoc.loadXML(textxml);
+ }
+ return xmlDoc;
+ }
+
+});
+
+/**
+ *
+ * cc.plistParser is a singleton object for parsing plist files
+ * @class
+ * @name cc.plistParser
+ * @extends cc.SAXParser
+ */
+cc.PlistParser = cc.SAXParser.extend(/** @lends cc.plistParser# */{
+
+ /**
+ * parse a xml string as plist object.
+ * @param {String} xmlTxt plist xml contents
+ * @return {*} plist object
+ */
+ parse : function (xmlTxt) {
+ var xmlDoc = this._parseXML(xmlTxt);
+ var plist = xmlDoc.documentElement;
+ if (plist.tagName !== 'plist') {
+ cc.warn("Not a plist file!");
+ return {};
+ }
+
+ // Get first real node
+ var node = null;
+ for (var i = 0, len = plist.childNodes.length; i < len; i++) {
+ node = plist.childNodes[i];
+ if (node.nodeType === 1)
+ break;
+ }
+ xmlDoc = null;
+ return this._parseNode(node);
+ },
+
+ _parseNode: function (node) {
+ var data = null, tagName = node.tagName;
+ if(tagName === "dict"){
+ data = this._parseDict(node);
+ }else if(tagName === "array"){
+ data = this._parseArray(node);
+ }else if(tagName === "string"){
+ if (node.childNodes.length === 1)
+ data = node.firstChild.nodeValue;
+ else {
+ //handle Firefox's 4KB nodeValue limit
+ data = "";
+ for (var i = 0; i < node.childNodes.length; i++)
+ data += node.childNodes[i].nodeValue;
+ }
+ }else if(tagName === "false"){
+ data = false;
+ }else if(tagName === "true"){
+ data = true;
+ }else if(tagName === "real"){
+ data = parseFloat(node.firstChild.nodeValue);
+ }else if(tagName === "integer"){
+ data = parseInt(node.firstChild.nodeValue, 10);
+ }
+ return data;
+ },
+
+ _parseArray: function (node) {
+ var data = [];
+ for (var i = 0, len = node.childNodes.length; i < len; i++) {
+ var child = node.childNodes[i];
+ if (child.nodeType !== 1)
+ continue;
+ data.push(this._parseNode(child));
+ }
+ return data;
+ },
+
+ _parseDict: function (node) {
+ var data = {};
+ var key = null;
+ for (var i = 0, len = node.childNodes.length; i < len; i++) {
+ var child = node.childNodes[i];
+ if (child.nodeType !== 1)
+ continue;
+
+ // Grab the key, next noe should be the value
+ if (child.tagName === 'key')
+ key = child.firstChild.nodeValue;
+ else
+ data[key] = this._parseNode(child); // Parse the value node
+ }
+ return data;
+ }
+});
+
+cc.saxParser = new cc.SAXParser();
+/**
+ * A Plist Parser
+ * @type {cc.PlistParser}
+ * @name plistParser
+ * @memberof cc
+ */
+cc.plistParser = new cc.PlistParser();
diff --git a/cocos2d/core/platform/CCScreen.js b/cocos2d/core/platform/CCScreen.js
new file mode 100644
index 0000000000..8bc1e4d758
--- /dev/null
+++ b/cocos2d/core/platform/CCScreen.js
@@ -0,0 +1,161 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The fullscreen API provides an easy way for web content to be presented using the user's entire screen.
+ * It's invalid on safari, QQbrowser and android browser
+ * @class
+ * @name cc.screen
+ */
+cc.screen = /** @lends cc.screen# */{
+ _supportsFullScreen: false,
+ // the pre fullscreenchange function
+ _preOnFullScreenChange: null,
+ _touchEvent: "",
+ _fn: null,
+ // Function mapping for cross browser support
+ _fnMap: [
+ [
+ 'requestFullscreen',
+ 'exitFullscreen',
+ 'fullscreenchange',
+ 'fullscreenEnabled',
+ 'fullscreenElement'
+ ],
+ [
+ 'requestFullScreen',
+ 'exitFullScreen',
+ 'fullScreenchange',
+ 'fullScreenEnabled',
+ 'fullScreenElement'
+ ],
+ [
+ 'webkitRequestFullScreen',
+ 'webkitCancelFullScreen',
+ 'webkitfullscreenchange',
+ 'webkitIsFullScreen',
+ 'webkitCurrentFullScreenElement'
+ ],
+ [
+ 'mozRequestFullScreen',
+ 'mozCancelFullScreen',
+ 'mozfullscreenchange',
+ 'mozFullScreen',
+ 'mozFullScreenElement'
+ ],
+ [
+ 'msRequestFullscreen',
+ 'msExitFullscreen',
+ 'MSFullscreenChange',
+ 'msFullscreenEnabled',
+ 'msFullscreenElement'
+ ]
+ ],
+
+ /**
+ * initialize
+ * @function
+ */
+ init: function () {
+ this._fn = {};
+ var i, val, map = this._fnMap, valL;
+ for (i = 0, l = map.length; i < l; i++) {
+ val = map[i];
+ if (val && val[1] in document) {
+ for (i = 0, valL = val.length; i < valL; i++) {
+ this._fn[map[0][i]] = val[i];
+ }
+ break;
+ }
+ }
+
+ this._supportsFullScreen = (typeof this._fn.requestFullscreen !== 'undefined');
+ this._touchEvent = ('ontouchstart' in window) ? 'touchstart' : 'mousedown';
+ },
+
+ /**
+ * return true if it's full now.
+ * @returns {Boolean}
+ */
+ fullScreen: function () {
+ if(!this._supportsFullScreen) return false;
+ else if( document[this._fn.fullscreenElement] === undefined || document[this._fn.fullscreenElement] === null )
+ return false;
+ else
+ return true;
+ },
+
+ /**
+ * change the screen to full mode.
+ * @param {Element} element
+ * @param {Function} onFullScreenChange
+ */
+ requestFullScreen: function (element, onFullScreenChange) {
+ if (!this._supportsFullScreen) {
+ return;
+ }
+
+ element = element || document.documentElement;
+
+ if (onFullScreenChange) {
+ var eventName = this._fn.fullscreenchange;
+ if (this._preOnFullScreenChange) {
+ document.removeEventListener(eventName, this._preOnFullScreenChange);
+ }
+ this._preOnFullScreenChange = onFullScreenChange;
+ document.addEventListener(eventName, onFullScreenChange, false);
+ }
+
+ return element[this._fn.requestFullscreen]();
+ },
+
+ /**
+ * exit the full mode.
+ * @return {Boolean}
+ */
+ exitFullScreen: function () {
+ return this._supportsFullScreen ? document[this._fn.exitFullscreen]() : true;
+ },
+
+ /**
+ * Automatically request full screen with a touch/click event
+ * @param {Element} element
+ * @param {Function} onFullScreenChange
+ */
+ autoFullScreen: function (element, onFullScreenChange) {
+ element = element || document.body;
+ var touchTarget = cc.game.canvas || element;
+ var theScreen = this;
+ // Function bind will be too complicated here because we need the callback function's reference to remove the listener
+ function callback() {
+ touchTarget.removeEventListener(theScreen._touchEvent, callback);
+ theScreen.requestFullScreen(element, onFullScreenChange);
+ }
+ this.requestFullScreen(element, onFullScreenChange);
+ touchTarget.addEventListener(this._touchEvent, callback);
+ }
+};
+cc.screen.init();
diff --git a/cocos2d/core/platform/CCTypes.js b/cocos2d/core/platform/CCTypes.js
new file mode 100644
index 0000000000..e076fe2ae4
--- /dev/null
+++ b/cocos2d/core/platform/CCTypes.js
@@ -0,0 +1,1178 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * Color class, please use cc.color() to construct a color
+ * @class cc.Color
+ * @param {Number} r
+ * @param {Number} g
+ * @param {Number} b
+ * @param {Number} a
+ * @see cc.color
+ */
+cc.Color = function (r, g, b, a) {
+ r = r || 0;
+ g = g || 0;
+ b = b || 0;
+ a = typeof a === 'number' ? a : 255;
+ this._val = ((r << 24) >>> 0) + (g << 16) + (b << 8) + a;
+};
+
+var _p = cc.Color.prototype;
+_p._getR = function () {
+ return (this._val & 0xff000000) >>> 24;
+};
+_p._setR = function (value) {
+ this._val = (this._val & 0x00ffffff) | ((value << 24) >>> 0);
+};
+_p._getG = function () {
+ return (this._val & 0x00ff0000) >> 16;
+};
+_p._setG = function (value) {
+ this._val = (this._val & 0xff00ffff) | (value << 16);
+};
+_p._getB = function () {
+ return (this._val & 0x0000ff00) >> 8;
+};
+_p._setB = function (value) {
+ this._val = (this._val & 0xffff00ff) | (value << 8);
+};
+_p._getA = function () {
+ return this._val & 0x000000ff;
+};
+_p._setA = function (value) {
+ this._val = (this._val & 0xffffff00) | value;
+};
+
+
+/** @expose */
+_p.r;
+cc.defineGetterSetter(_p, "r", _p._getR, _p._setR);
+/** @expose */
+_p.g;
+cc.defineGetterSetter(_p, "g", _p._getG, _p._setG);
+/** @expose */
+_p.b;
+cc.defineGetterSetter(_p, "b", _p._getB, _p._setB);
+/** @expose */
+_p.a;
+cc.defineGetterSetter(_p, "a", _p._getA, _p._setA);
+
+/**
+ * Generate a color object based on multiple forms of parameters
+ * @example
+ *
+ * // 1. All channels separately as parameters
+ * var color1 = cc.color(255, 255, 255, 255);
+ *
+ * // 2. Convert a hex string to a color
+ * var color2 = cc.color("#000000");
+ *
+ * // 3. An color object as parameter
+ * var color3 = cc.color({r: 255, g: 255, b: 255, a: 255});
+ *
+ * Alpha channel is optional. Default value is 255
+ *
+ * @param {Number|String|cc.Color} r
+ * @param {Number} [g]
+ * @param {Number} [b]
+ * @param {Number} [a=255]
+ * @return {cc.Color}
+ */
+cc.color = function (r, g, b, a) {
+ if (r === undefined)
+ return new cc.Color(0, 0, 0, 255);
+ if (typeof r === 'object')
+ return new cc.Color(r.r, r.g, r.b, (r.a == null) ? 255 : r.a);
+ if (typeof r === 'string')
+ return cc.hexToColor(r);
+ return new cc.Color(r, g, b, (a == null ? 255 : a));
+};
+
+/**
+ * returns true if both ccColor3B are equal. Otherwise it returns false.
+ * @function
+ * @param {cc.Color} color1
+ * @param {cc.Color} color2
+ * @return {Boolean} true if both ccColor3B are equal. Otherwise it returns false.
+ */
+cc.colorEqual = function (color1, color2) {
+ return color1.r === color2.r && color1.g === color2.g && color1.b === color2.b;
+};
+
+/**
+ * the device accelerometer reports values for each axis in units of g-force
+ * @class cc.Acceleration
+ * @constructor
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @param {Number} timestamp
+ */
+cc.Acceleration = function (x, y, z, timestamp) {
+ this.x = x || 0;
+ this.y = y || 0;
+ this.z = z || 0;
+ this.timestamp = timestamp || 0;
+};
+
+/**
+ * @class cc.Vertex2F
+ * @param {Number} x
+ * @param {Number}y
+ * @param {Array} arrayBuffer
+ * @param {Number}offset
+ * @constructor
+ */
+cc.Vertex2F = function (x, y, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Vertex2F.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ this._view = new Float32Array(this._arrayBuffer, this._offset, 2);
+ this._view[0] = x || 0;
+ this._view[1] = y || 0;
+};
+/**
+ * @constant
+ * @type {number}
+ */
+cc.Vertex2F.BYTES_PER_ELEMENT = 8;
+
+_p = cc.Vertex2F.prototype;
+_p._getX = function () {
+ return this._view[0];
+};
+_p._setX = function (xValue) {
+ this._view[0] = xValue;
+};
+_p._getY = function () {
+ return this._view[1];
+};
+_p._setY = function (yValue) {
+ this._view[1] = yValue;
+};
+/** @expose */
+_p.x;
+cc.defineGetterSetter(_p, "x", _p._getX, _p._setX);
+/** @expose */
+_p.y;
+cc.defineGetterSetter(_p, "y", _p._getY, _p._setY);
+
+/**
+ * @class cc.Vertex3F
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number}z
+ * @param {Array} arrayBuffer
+ * @param {Number} offset
+ * @constructor
+ */
+cc.Vertex3F = function (x, y, z, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Vertex3F.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
+ this._view = new Float32Array(locArrayBuffer, locOffset, 3);
+ this._view[0] = x || 0;
+ this._view[1] = y || 0;
+ this._view[2] = z || 0;
+};
+/**
+ * @constant
+ * @type {number}
+ */
+cc.Vertex3F.BYTES_PER_ELEMENT = 12;
+
+_p = cc.Vertex3F.prototype;
+_p._getX = function () {
+ return this._view[0];
+};
+_p._setX = function (xValue) {
+ this._view[0] = xValue;
+};
+_p._getY = function () {
+ return this._view[1];
+};
+_p._setY = function (yValue) {
+ this._view[1] = yValue;
+};
+_p._getZ = function () {
+ return this._view[2];
+};
+_p._setZ = function (zValue) {
+ this._view[2] = zValue;
+};
+/** @expose */
+_p.x;
+cc.defineGetterSetter(_p, "x", _p._getX, _p._setX);
+/** @expose */
+_p.y;
+cc.defineGetterSetter(_p, "y", _p._getY, _p._setY);
+/** @expose */
+_p.z;
+cc.defineGetterSetter(_p, "z", _p._getZ, _p._setZ);
+
+/**
+ * @class cc.Tex2F
+ * @param {Number} u
+ * @param {Number} v
+ * @param {Array} arrayBuffer
+ * @param {Number} offset
+ * @constructor
+ */
+cc.Tex2F = function (u, v, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Tex2F.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ this._view = new Float32Array(this._arrayBuffer, this._offset, 2);
+ this._view[0] = u || 0;
+ this._view[1] = v || 0;
+};
+/**
+ * @constants
+ * @type {number}
+ */
+cc.Tex2F.BYTES_PER_ELEMENT = 8;
+
+_p = cc.Tex2F.prototype;
+_p._getU = function () {
+ return this._view[0];
+};
+_p._setU = function (xValue) {
+ this._view[0] = xValue;
+};
+_p._getV = function () {
+ return this._view[1];
+};
+_p._setV = function (yValue) {
+ this._view[1] = yValue;
+};
+/** @expose */
+_p.u;
+cc.defineGetterSetter(_p, "u", _p._getU, _p._setU);
+/** @expose */
+_p.v;
+cc.defineGetterSetter(_p, "v", _p._getV, _p._setV);
+
+/**
+ * @class cc.Quad2
+ * @param {cc.Vertex2F} tl
+ * @param {cc.Vertex2F} tr
+ * @param {cc.Vertex2F} bl
+ * @param {cc.Vertex2F} br
+ * @param {Array} arrayBuffer
+ * @param {Number} offset
+ * @constructor
+ */
+cc.Quad2 = function (tl, tr, bl, br, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Quad2.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex2F.BYTES_PER_ELEMENT;
+ this._tl = tl ? new cc.Vertex2F(tl.x, tl.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._tr = tr ? new cc.Vertex2F(tr.x, tr.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._bl = bl ? new cc.Vertex2F(bl.x, bl.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._br = br ? new cc.Vertex2F(br.x, br.y, locArrayBuffer, locOffset) : new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
+};
+/**
+ * @constant
+ * @type {number}
+ */
+cc.Quad2.BYTES_PER_ELEMENT = 32;
+
+_p = cc.Quad2.prototype;
+_p._getTL = function () {
+ return this._tl;
+};
+_p._setTL = function (tlValue) {
+ this._tl._view[0] = tlValue.x;
+ this._tl._view[1] = tlValue.y;
+};
+_p._getTR = function () {
+ return this._tr;
+};
+_p._setTR = function (trValue) {
+ this._tr._view[0] = trValue.x;
+ this._tr._view[1] = trValue.y;
+};
+_p._getBL = function () {
+ return this._bl;
+};
+_p._setBL = function (blValue) {
+ this._bl._view[0] = blValue.x;
+ this._bl._view[1] = blValue.y;
+};
+_p._getBR = function () {
+ return this._br;
+};
+_p._setBR = function (brValue) {
+ this._br._view[0] = brValue.x;
+ this._br._view[1] = brValue.y;
+};
+
+/** @expose */
+_p.tl;
+cc.defineGetterSetter(_p, "tl", _p._getTL, _p._setTL);
+/** @expose */
+_p.tr;
+cc.defineGetterSetter(_p, "tr", _p._getTR, _p._setTR);
+/** @expose */
+_p.bl;
+cc.defineGetterSetter(_p, "bl", _p._getBL, _p._setBL);
+/** @expose */
+_p.br;
+cc.defineGetterSetter(_p, "br", _p._getBR, _p._setBR);
+
+/**
+ * A 3D Quad. 4 * 3 floats
+ * @Class cc.Quad3
+ * @Construct
+ * @param {cc.Vertex3F} bl
+ * @param {cc.Vertex3F} br
+ * @param {cc.Vertex3F} tl
+ * @param {cc.Vertex3F} tr
+ */
+cc.Quad3 = function (bl, br, tl, tr, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Quad3.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex3F.BYTES_PER_ELEMENT;
+ this.bl = bl ? new cc.Vertex3F(bl.x, bl.y, bl.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this.br = br ? new cc.Vertex3F(br.x, br.y, br.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this.tl = tl ? new cc.Vertex3F(tl.x, tl.y, tl.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this.tr = tr ? new cc.Vertex3F(tr.x, tr.y, tr.z, locArrayBuffer, locOffset) : new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
+};
+/**
+ * @constant
+ * @type {number}
+ */
+cc.Quad3.BYTES_PER_ELEMENT = 48;
+
+/**
+ * @class cc.V3F_C4B_T2F
+ * @param {cc.Vertex3F} vertices
+ * @param {cc.Color} colors
+ * @param {cc.Tex2F} texCoords
+ * @param {Array} arrayBuffer
+ * @param {Number} offset
+ * @constructor
+ */
+cc.V3F_C4B_T2F = function (vertices, colors, texCoords, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
+ this._vertices = vertices ? new cc.Vertex3F(vertices.x, vertices.y, vertices.z, locArrayBuffer, locOffset) :
+ new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
+
+ locOffset += cc.Vertex3F.BYTES_PER_ELEMENT;
+ this._colors = colors ? new cc._WebGLColor(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset) :
+ new cc._WebGLColor(0, 0, 0, 0, locArrayBuffer, locOffset);
+
+ locOffset += cc._WebGLColor.BYTES_PER_ELEMENT;
+ this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset) :
+ new cc.Tex2F(0, 0, locArrayBuffer, locOffset);
+};
+/**
+ * @constant
+ * @type {number}
+ */
+cc.V3F_C4B_T2F.BYTES_PER_ELEMENT = 24;
+
+_p = cc.V3F_C4B_T2F.prototype;
+_p._getVertices = function () {
+ return this._vertices;
+};
+_p._setVertices = function (verticesValue) {
+ var locVertices = this._vertices;
+ locVertices._view[0] = verticesValue.x;
+ locVertices._view[1] = verticesValue.y;
+ locVertices._view[2] = verticesValue.z;
+};
+_p._getColor = function () {
+ return this._colors;
+};
+_p._setColor = function (colorValue) {
+ var locColors = this._colors;
+ locColors._view[0] = colorValue.r;
+ locColors._view[1] = colorValue.g;
+ locColors._view[2] = colorValue.b;
+ locColors._view[3] = colorValue.a;
+};
+_p._getTexCoords = function () {
+ return this._texCoords;
+};
+_p._setTexCoords = function (texValue) {
+ this._texCoords._view[0] = texValue.u;
+ this._texCoords._view[1] = texValue.v;
+};
+/** @expose */
+_p.vertices;
+cc.defineGetterSetter(_p, "vertices", _p._getVertices, _p._setVertices);
+/** @expose */
+_p.colors;
+cc.defineGetterSetter(_p, "colors", _p._getColor, _p._setColor);
+/** @expose */
+_p.texCoords;
+cc.defineGetterSetter(_p, "texCoords", _p._getTexCoords, _p._setTexCoords);
+
+/**
+ * @cc.class cc.V3F_C4B_T2F_Quad
+ * @param {cc.V3F_C4B_T2F} tl
+ * @param {cc.V3F_C4B_T2F} bl
+ * @param {cc.V3F_C4B_T2F} tr
+ * @param {cc.V3F_C4B_T2F} br
+ * @param {Array} arrayBuffer
+ * @param {Number} offset
+ * @constructor
+ */
+cc.V3F_C4B_T2F_Quad = function (tl, bl, tr, br, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT;
+ this._tl = tl ? new cc.V3F_C4B_T2F(tl.vertices, tl.colors, tl.texCoords, locArrayBuffer, locOffset) :
+ new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._bl = bl ? new cc.V3F_C4B_T2F(bl.vertices, bl.colors, bl.texCoords, locArrayBuffer, locOffset) :
+ new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._tr = tr ? new cc.V3F_C4B_T2F(tr.vertices, tr.colors, tr.texCoords, locArrayBuffer, locOffset) :
+ new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._br = br ? new cc.V3F_C4B_T2F(br.vertices, br.colors, br.texCoords, locArrayBuffer, locOffset) :
+ new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
+};
+/**
+ * @constant
+ * @type {number}
+ */
+cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT = 96;
+_p = cc.V3F_C4B_T2F_Quad.prototype;
+_p._getTL = function () {
+ return this._tl;
+};
+_p._setTL = function (tlValue) {
+ var locTl = this._tl;
+ locTl.vertices = tlValue.vertices;
+ locTl.colors = tlValue.colors;
+ locTl.texCoords = tlValue.texCoords;
+};
+_p._getBL = function () {
+ return this._bl;
+};
+_p._setBL = function (blValue) {
+ var locBl = this._bl;
+ locBl.vertices = blValue.vertices;
+ locBl.colors = blValue.colors;
+ locBl.texCoords = blValue.texCoords;
+};
+_p._getTR = function () {
+ return this._tr;
+};
+_p._setTR = function (trValue) {
+ var locTr = this._tr;
+ locTr.vertices = trValue.vertices;
+ locTr.colors = trValue.colors;
+ locTr.texCoords = trValue.texCoords;
+};
+_p._getBR = function () {
+ return this._br;
+};
+_p._setBR = function (brValue) {
+ var locBr = this._br;
+ locBr.vertices = brValue.vertices;
+ locBr.colors = brValue.colors;
+ locBr.texCoords = brValue.texCoords;
+};
+_p._getArrayBuffer = function () {
+ return this._arrayBuffer;
+};
+
+/** @expose */
+_p.tl;
+cc.defineGetterSetter(_p, "tl", _p._getTL, _p._setTL);
+/** @expose */
+_p.tr;
+cc.defineGetterSetter(_p, "tr", _p._getTR, _p._setTR);
+/** @expose */
+_p.bl;
+cc.defineGetterSetter(_p, "bl", _p._getBL, _p._setBL);
+/** @expose */
+_p.br;
+cc.defineGetterSetter(_p, "br", _p._getBR, _p._setBR);
+/** @expose */
+_p.arrayBuffer;
+cc.defineGetterSetter(_p, "arrayBuffer", _p._getArrayBuffer, null);
+
+/**
+ * @function
+ * @returns {cc.V3F_C4B_T2F_Quad}
+ */
+cc.V3F_C4B_T2F_QuadZero = function () {
+ return new cc.V3F_C4B_T2F_Quad();
+};
+
+/**
+ * @function
+ * @param {cc.V3F_C4B_T2F_Quad} sourceQuad
+ * @return {cc.V3F_C4B_T2F_Quad}
+ */
+cc.V3F_C4B_T2F_QuadCopy = function (sourceQuad) {
+ if (!sourceQuad)
+ return cc.V3F_C4B_T2F_QuadZero();
+
+ //return new cc.V3F_C4B_T2F_Quad(sourceQuad,tl,sourceQuad,bl,sourceQuad.tr,sourceQuad.br,null,0);
+ var srcTL = sourceQuad.tl, srcBL = sourceQuad.bl, srcTR = sourceQuad.tr, srcBR = sourceQuad.br;
+ return {
+ tl: {
+ vertices: {x: srcTL.vertices.x, y: srcTL.vertices.y, z: srcTL.vertices.z},
+ colors: {r: srcTL.colors.r, g: srcTL.colors.g, b: srcTL.colors.b, a: srcTL.colors.a},
+ texCoords: {u: srcTL.texCoords.u, v: srcTL.texCoords.v}
+ },
+ bl: {
+ vertices: {x: srcBL.vertices.x, y: srcBL.vertices.y, z: srcBL.vertices.z},
+ colors: {r: srcBL.colors.r, g: srcBL.colors.g, b: srcBL.colors.b, a: srcBL.colors.a},
+ texCoords: {u: srcBL.texCoords.u, v: srcBL.texCoords.v}
+ },
+ tr: {
+ vertices: {x: srcTR.vertices.x, y: srcTR.vertices.y, z: srcTR.vertices.z},
+ colors: {r: srcTR.colors.r, g: srcTR.colors.g, b: srcTR.colors.b, a: srcTR.colors.a},
+ texCoords: {u: srcTR.texCoords.u, v: srcTR.texCoords.v}
+ },
+ br: {
+ vertices: {x: srcBR.vertices.x, y: srcBR.vertices.y, z: srcBR.vertices.z},
+ colors: {r: srcBR.colors.r, g: srcBR.colors.g, b: srcBR.colors.b, a: srcBR.colors.a},
+ texCoords: {u: srcBR.texCoords.u, v: srcBR.texCoords.v}
+ }
+ };
+};
+
+/**
+ * @function
+ * @param {Array} sourceQuads
+ * @returns {Array}
+ */
+cc.V3F_C4B_T2F_QuadsCopy = function (sourceQuads) {
+ if (!sourceQuads)
+ return [];
+
+ var retArr = [];
+ for (var i = 0; i < sourceQuads.length; i++) {
+ retArr.push(cc.V3F_C4B_T2F_QuadCopy(sourceQuads[i]));
+ }
+ return retArr;
+};
+
+//redefine cc.V2F_C4B_T2F
+/**
+ * @class cc.V2F_C4B_T2F
+ * @param {cc.Vertex2F} vertices
+ * @param {cc.Color} colors
+ * @param {cc.Tex2F} texCoords
+ * @param {Array} arrayBuffer
+ * @param {Number} offset
+ * @constructor
+ */
+cc.V2F_C4B_T2F = function (vertices, colors, texCoords, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
+ this._vertices = vertices ? new cc.Vertex2F(vertices.x, vertices.y, locArrayBuffer, locOffset) :
+ new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
+ locOffset += cc.Vertex2F.BYTES_PER_ELEMENT;
+ this._colors = colors ? new cc._WebGLColor(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset) :
+ new cc._WebGLColor(0, 0, 0, 0, locArrayBuffer, locOffset);
+ locOffset += cc._WebGLColor.BYTES_PER_ELEMENT;
+ this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset) :
+ new cc.Tex2F(0, 0, locArrayBuffer, locOffset);
+};
+
+/**
+ * @constant
+ * @type {number}
+ */
+cc.V2F_C4B_T2F.BYTES_PER_ELEMENT = 20;
+_p = cc.V2F_C4B_T2F.prototype;
+_p._getVertices = function () {
+ return this._vertices;
+};
+_p._setVertices = function (verticesValue) {
+ this._vertices._view[0] = verticesValue.x;
+ this._vertices._view[1] = verticesValue.y;
+};
+_p._getColor = function () {
+ return this._colors;
+};
+_p._setColor = function (colorValue) {
+ var locColors = this._colors;
+ locColors._view[0] = colorValue.r;
+ locColors._view[1] = colorValue.g;
+ locColors._view[2] = colorValue.b;
+ locColors._view[3] = colorValue.a;
+};
+_p._getTexCoords = function () {
+ return this._texCoords;
+};
+_p._setTexCoords = function (texValue) {
+ this._texCoords._view[0] = texValue.u;
+ this._texCoords._view[1] = texValue.v;
+};
+
+/** @expose */
+_p.vertices;
+cc.defineGetterSetter(_p, "vertices", _p._getVertices, _p._setVertices);
+/** @expose */
+_p.colors;
+cc.defineGetterSetter(_p, "colors", _p._getColor, _p._setColor);
+/** @expose */
+_p.texCoords;
+cc.defineGetterSetter(_p, "texCoords", _p._getTexCoords, _p._setTexCoords);
+
+//redefine cc.V2F_C4B_T2F_Triangle
+/**
+ * @class cc.V2F_C4B_T2F_Triangle
+ * @param {cc.V2F_C4B_T2F} a
+ * @param {cc.V2F_C4B_T2F} b
+ * @param {cc.V2F_C4B_T2F} c
+ * @param {Array} arrayBuffer
+ * @param {Number} offset
+ * @constructor
+ */
+cc.V2F_C4B_T2F_Triangle = function (a, b, c, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
+ this._a = a ? new cc.V2F_C4B_T2F(a.vertices, a.colors, a.texCoords, locArrayBuffer, locOffset) :
+ new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._b = b ? new cc.V2F_C4B_T2F(b.vertices, b.colors, b.texCoords, locArrayBuffer, locOffset) :
+ new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
+ locOffset += locElementLen;
+ this._c = c ? new cc.V2F_C4B_T2F(c.vertices, c.colors, c.texCoords, locArrayBuffer, locOffset) :
+ new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
+};
+/**
+ * @constant
+ * @type {number}
+ */
+cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT = 60;
+_p = cc.V2F_C4B_T2F_Triangle.prototype;
+_p._getA = function () {
+ return this._a;
+};
+_p._setA = function (aValue) {
+ var locA = this._a;
+ locA.vertices = aValue.vertices;
+ locA.colors = aValue.colors;
+ locA.texCoords = aValue.texCoords;
+};
+_p._getB = function () {
+ return this._b;
+};
+_p._setB = function (bValue) {
+ var locB = this._b;
+ locB.vertices = bValue.vertices;
+ locB.colors = bValue.colors;
+ locB.texCoords = bValue.texCoords;
+};
+_p._getC = function () {
+ return this._c;
+};
+_p._setC = function (cValue) {
+ var locC = this._c;
+ locC.vertices = cValue.vertices;
+ locC.colors = cValue.colors;
+ locC.texCoords = cValue.texCoords;
+};
+
+/** @expose */
+_p.a;
+cc.defineGetterSetter(_p, "a", _p._getA, _p._setA);
+/** @expose */
+_p.b;
+cc.defineGetterSetter(_p, "b", _p._getB, _p._setB);
+/** @expose */
+_p.c;
+cc.defineGetterSetter(_p, "c", _p._getC, _p._setC);
+
+/**
+ * Helper macro that creates an Vertex2F type composed of 2 floats: x, y
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @return {cc.Vertex2F}
+ */
+cc.vertex2 = function (x, y) {
+ return new cc.Vertex2F(x, y);
+};
+
+/**
+ * Helper macro that creates an Vertex3F type composed of 3 floats: x, y, z
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @return {cc.Vertex3F}
+ */
+cc.vertex3 = function (x, y, z) {
+ return new cc.Vertex3F(x, y, z);
+};
+
+/**
+ * Helper macro that creates an Tex2F type: A texcoord composed of 2 floats: u, y
+ * @function
+ * @param {Number} u
+ * @param {Number} v
+ * @return {cc.Tex2F}
+ */
+cc.tex2 = function (u, v) {
+ return new cc.Tex2F(u, v);
+};
+
+/**
+ * Blend Function used for textures
+ * @Class cc.BlendFunc
+ * @Constructor
+ * @param {Number} src1 source blend function
+ * @param {Number} dst1 destination blend function
+ */
+cc.BlendFunc = function (src1, dst1) {
+ this.src = src1;
+ this.dst = dst1;
+};
+
+/**
+ * @function
+ * @returns {cc.BlendFunc}
+ */
+cc.blendFuncDisable = function () {
+ return new cc.BlendFunc(cc.ONE, cc.ZERO);
+};
+
+/**
+ * convert a string of color for style to Color.
+ * e.g. "#ff06ff" to : cc.color(255,6,255)
+ * @function
+ * @param {String} hex
+ * @return {cc.Color}
+ */
+cc.hexToColor = function (hex) {
+ hex = hex.replace(/^#?/, "0x");
+ var c = parseInt(hex);
+ var r = c >> 16;
+ var g = (c >> 8) % 256;
+ var b = c % 256;
+ return new cc.Color(r, g, b);
+};
+
+/**
+ * convert Color to a string of color for style.
+ * e.g. cc.color(255,6,255) to : "#ff06ff"
+ * @function
+ * @param {cc.Color} color
+ * @return {String}
+ */
+cc.colorToHex = function (color) {
+ var hR = color.r.toString(16), hG = color.g.toString(16), hB = color.b.toString(16);
+ return "#" + (color.r < 16 ? ("0" + hR) : hR) + (color.g < 16 ? ("0" + hG) : hG) + (color.b < 16 ? ("0" + hB) : hB);
+};
+
+/**
+ * text alignment : left
+ * @constant
+ * @type Number
+ */
+cc.TEXT_ALIGNMENT_LEFT = 0;
+
+/**
+ * text alignment : center
+ * @constant
+ * @type Number
+ */
+cc.TEXT_ALIGNMENT_CENTER = 1;
+
+/**
+ * text alignment : right
+ * @constant
+ * @type Number
+ */
+cc.TEXT_ALIGNMENT_RIGHT = 2;
+
+/**
+ * text alignment : top
+ * @constant
+ * @type Number
+ */
+cc.VERTICAL_TEXT_ALIGNMENT_TOP = 0;
+
+/**
+ * text alignment : center
+ * @constant
+ * @type Number
+ */
+cc.VERTICAL_TEXT_ALIGNMENT_CENTER = 1;
+
+/**
+ * text alignment : bottom
+ * @constant
+ * @type Number
+ */
+cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM = 2;
+
+cc._Dictionary = cc.Class.extend({
+ _keyMapTb: null,
+ _valueMapTb: null,
+ __currId: 0,
+
+ ctor: function () {
+ this._keyMapTb = {};
+ this._valueMapTb = {};
+ this.__currId = 2 << (0 | (Math.random() * 10));
+ },
+
+ __getKey: function () {
+ this.__currId++;
+ return "key_" + this.__currId;
+ },
+
+ setObject: function (value, key) {
+ if (key == null)
+ return;
+
+ var keyId = this.__getKey();
+ this._keyMapTb[keyId] = key;
+ this._valueMapTb[keyId] = value;
+ },
+
+ objectForKey: function (key) {
+ if (key == null)
+ return null;
+
+ var locKeyMapTb = this._keyMapTb;
+ for (var keyId in locKeyMapTb) {
+ if (locKeyMapTb[keyId] === key)
+ return this._valueMapTb[keyId];
+ }
+ return null;
+ },
+
+ valueForKey: function (key) {
+ return this.objectForKey(key);
+ },
+
+ removeObjectForKey: function (key) {
+ if (key == null)
+ return;
+
+ var locKeyMapTb = this._keyMapTb;
+ for (var keyId in locKeyMapTb) {
+ if (locKeyMapTb[keyId] === key) {
+ delete this._valueMapTb[keyId];
+ delete locKeyMapTb[keyId];
+ return;
+ }
+ }
+ },
+
+ removeObjectsForKeys: function (keys) {
+ if (keys == null)
+ return;
+
+ for (var i = 0; i < keys.length; i++)
+ this.removeObjectForKey(keys[i]);
+ },
+
+ allKeys: function () {
+ var keyArr = [], locKeyMapTb = this._keyMapTb;
+ for (var key in locKeyMapTb)
+ keyArr.push(locKeyMapTb[key]);
+ return keyArr;
+ },
+
+ removeAllObjects: function () {
+ this._keyMapTb = {};
+ this._valueMapTb = {};
+ },
+
+ count: function () {
+ return this.allKeys().length;
+ }
+});
+
+/**
+ * Common usage:
+ *
+ * var fontDef = new cc.FontDefinition();
+ * fontDef.fontName = "Arial";
+ * fontDef.fontSize = 12;
+ * ...
+ *
+ * OR using inline definition useful for constructor injection
+ *
+ * var fontDef = new cc.FontDefinition({
+ * fontName: "Arial",
+ * fontSize: 12
+ * });
+ *
+ *
+ *
+ * @class cc.FontDefinition
+ * @param {Object} properties - (OPTIONAL) Allow inline FontDefinition
+ * @constructor
+ */
+cc.FontDefinition = function (properties) {
+ var _t = this;
+ _t.fontName = "Arial";
+ _t.fontSize = 12;
+ _t.textAlign = cc.TEXT_ALIGNMENT_CENTER;
+ _t.verticalAlign = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
+ _t.fillStyle = cc.color(255, 255, 255, 255);
+ _t.boundingWidth = 0;
+ _t.boundingHeight = 0;
+
+ _t.strokeEnabled = false;
+ _t.strokeStyle = cc.color(255, 255, 255, 255);
+ _t.lineWidth = 1;
+ _t.lineHeight = "normal";
+ _t.fontStyle = "normal";
+ _t.fontWeight = "normal";
+
+ _t.shadowEnabled = false;
+ _t.shadowOffsetX = 0;
+ _t.shadowOffsetY = 0;
+ _t.shadowBlur = 0;
+ _t.shadowOpacity = 1.0;
+
+ //properties mapping:
+ if (properties && properties instanceof Object) {
+ for (var key in properties) {
+ _t[key] = properties[key];
+ }
+ }
+};
+/**
+ * Web ONLY
+ * */
+cc.FontDefinition.prototype._getCanvasFontStr = function () {
+ var lineHeight = !this.lineHeight.charAt ? this.lineHeight + "px" : this.lineHeight;
+ return this.fontStyle + " " + this.fontWeight + " " + this.fontSize + "px/" + lineHeight + " '" + this.fontName + "'";
+};
+
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ //redefine Color
+ cc._WebGLColor = function (r, g, b, a, arrayBuffer, offset) {
+ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc._WebGLColor.BYTES_PER_ELEMENT);
+ this._offset = offset || 0;
+
+ var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
+ this._view = new Uint8Array(locArrayBuffer, locOffset, 4);
+
+ this._view[0] = r || 0;
+ this._view[1] = g || 0;
+ this._view[2] = b || 0;
+ this._view[3] = (a == null) ? 255 : a;
+
+ if (a === undefined)
+ this.a_undefined = true;
+ };
+ cc._WebGLColor.BYTES_PER_ELEMENT = 4;
+ _p = cc._WebGLColor.prototype;
+ _p._getR = function () {
+ return this._view[0];
+ };
+ _p._setR = function (value) {
+ this._view[0] = value < 0 ? 0 : value;
+ };
+ _p._getG = function () {
+ return this._view[1];
+ };
+ _p._setG = function (value) {
+ this._view[1] = value < 0 ? 0 : value;
+ };
+ _p._getB = function () {
+ return this._view[2];
+ };
+ _p._setB = function (value) {
+ this._view[2] = value < 0 ? 0 : value;
+ };
+ _p._getA = function () {
+ return this._view[3];
+ };
+ _p._setA = function (value) {
+ this._view[3] = value < 0 ? 0 : value;
+ };
+ cc.defineGetterSetter(_p, "r", _p._getR, _p._setR);
+ cc.defineGetterSetter(_p, "g", _p._getG, _p._setG);
+ cc.defineGetterSetter(_p, "b", _p._getB, _p._setB);
+ cc.defineGetterSetter(_p, "a", _p._getA, _p._setA);
+ }
+});
+
+_p = cc.color;
+/**
+ * White color (255, 255, 255, 255)
+ * @returns {cc.Color}
+ * @private
+ */
+_p._getWhite = function () {
+ return cc.color(255, 255, 255);
+};
+
+/**
+ * Yellow color (255, 255, 0, 255)
+ * @returns {cc.Color}
+ * @private
+ */
+_p._getYellow = function () {
+ return cc.color(255, 255, 0);
+};
+
+/**
+ * Blue color (0, 0, 255, 255)
+ * @type {cc.Color}
+ * @private
+ */
+_p._getBlue = function () {
+ return cc.color(0, 0, 255);
+};
+
+/**
+ * Green Color (0, 255, 0, 255)
+ * @type {cc.Color}
+ * @private
+ */
+_p._getGreen = function () {
+ return cc.color(0, 255, 0);
+};
+
+/**
+ * Red Color (255, 0, 0, 255)
+ * @type {cc.Color}
+ * @private
+ */
+_p._getRed = function () {
+ return cc.color(255, 0, 0);
+};
+
+/**
+ * Magenta Color (255, 0, 255, 255)
+ * @type {cc.Color}
+ * @private
+ */
+_p._getMagenta = function () {
+ return cc.color(255, 0, 255);
+};
+
+/**
+ * Black Color (0, 0, 0, 255)
+ * @type {cc.Color}
+ * @private
+ */
+_p._getBlack = function () {
+ return cc.color(0, 0, 0);
+};
+
+/**
+ * Orange Color (255, 127, 0, 255)
+ * @type {_p}
+ * @private
+ */
+_p._getOrange = function () {
+ return cc.color(255, 127, 0);
+};
+
+/**
+ * Gray Color (166, 166, 166, 255)
+ * @type {_p}
+ * @private
+ */
+_p._getGray = function () {
+ return cc.color(166, 166, 166);
+};
+
+/** @expose */
+_p.WHITE;
+cc.defineGetterSetter(_p, "WHITE", _p._getWhite);
+/** @expose */
+_p.YELLOW;
+cc.defineGetterSetter(_p, "YELLOW", _p._getYellow);
+/** @expose */
+_p.BLUE;
+cc.defineGetterSetter(_p, "BLUE", _p._getBlue);
+/** @expose */
+_p.GREEN;
+cc.defineGetterSetter(_p, "GREEN", _p._getGreen);
+/** @expose */
+_p.RED;
+cc.defineGetterSetter(_p, "RED", _p._getRed);
+/** @expose */
+_p.MAGENTA;
+cc.defineGetterSetter(_p, "MAGENTA", _p._getMagenta);
+/** @expose */
+_p.BLACK;
+cc.defineGetterSetter(_p, "BLACK", _p._getBlack);
+/** @expose */
+_p.ORANGE;
+cc.defineGetterSetter(_p, "ORANGE", _p._getOrange);
+/** @expose */
+_p.GRAY;
+cc.defineGetterSetter(_p, "GRAY", _p._getGray);
+
+cc.BlendFunc._disable = function(){
+ return new cc.BlendFunc(cc.ONE, cc.ZERO);
+};
+cc.BlendFunc._alphaPremultiplied = function(){
+ return new cc.BlendFunc(cc.ONE, cc.ONE_MINUS_SRC_ALPHA);
+};
+cc.BlendFunc._alphaNonPremultiplied = function(){
+ return new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
+};
+cc.BlendFunc._additive = function(){
+ return new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE);
+};
+
+/** @expose */
+cc.BlendFunc.DISABLE;
+cc.defineGetterSetter(cc.BlendFunc, "DISABLE", cc.BlendFunc._disable);
+/** @expose */
+cc.BlendFunc.ALPHA_PREMULTIPLIED;
+cc.defineGetterSetter(cc.BlendFunc, "ALPHA_PREMULTIPLIED", cc.BlendFunc._alphaPremultiplied);
+/** @expose */
+cc.BlendFunc.ALPHA_NON_PREMULTIPLIED;
+cc.defineGetterSetter(cc.BlendFunc, "ALPHA_NON_PREMULTIPLIED", cc.BlendFunc._alphaNonPremultiplied);
+/** @expose */
+cc.BlendFunc.ADDITIVE;
+cc.defineGetterSetter(cc.BlendFunc, "ADDITIVE", cc.BlendFunc._additive);
diff --git a/cocos2d/core/platform/CCVisibleRect.js b/cocos2d/core/platform/CCVisibleRect.js
new file mode 100644
index 0000000000..c6545e9f72
--- /dev/null
+++ b/cocos2d/core/platform/CCVisibleRect.js
@@ -0,0 +1,100 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.visibleRect is a singleton object which defines the actual visible rect of the current view,
+ * it should represent the same rect as cc.view.getViewportRect()
+ *
+ * @property {cc.Point} topLeft - Top left coordinate of the screen related to the game scene
+ * @property {cc.Point} topRight - Top right coordinate of the screen related to the game scene
+ * @property {cc.Point} top - Top center coordinate of the screen related to the game scene
+ * @property {cc.Point} bottomLeft - Bottom left coordinate of the screen related to the game scene
+ * @property {cc.Point} bottomRight - Bottom right coordinate of the screen related to the game scene
+ * @property {cc.Point} bottom - Bottom center coordinate of the screen related to the game scene
+ * @property {cc.Point} center - Center coordinate of the screen related to the game scene
+ * @property {cc.Point} left - Left center coordinate of the screen related to the game scene
+ * @property {cc.Point} right - Right center coordinate of the screen related to the game scene
+ * @property {Number} width - Width of the screen
+ * @property {Number} height - Height of the screen
+ *
+ * @class
+ * @name cc.visibleRect
+ */
+cc.visibleRect = {
+ topLeft:cc.p(0,0),
+ topRight:cc.p(0,0),
+ top:cc.p(0,0),
+ bottomLeft:cc.p(0,0),
+ bottomRight:cc.p(0,0),
+ bottom:cc.p(0,0),
+ center:cc.p(0,0),
+ left:cc.p(0,0),
+ right:cc.p(0,0),
+ width:0,
+ height:0,
+
+ /**
+ * initialize
+ * @param {cc.Rect} visibleRect
+ */
+ init:function(visibleRect){
+
+ var w = this.width = visibleRect.width;
+ var h = this.height = visibleRect.height;
+ var l = visibleRect.x,
+ b = visibleRect.y,
+ t = b + h,
+ r = l + w;
+
+ //top
+ this.topLeft.x = l;
+ this.topLeft.y = t;
+ this.topRight.x = r;
+ this.topRight.y = t;
+ this.top.x = l + w/2;
+ this.top.y = t;
+
+ //bottom
+ this.bottomLeft.x = l;
+ this.bottomLeft.y = b;
+ this.bottomRight.x = r;
+ this.bottomRight.y = b;
+ this.bottom.x = l + w/2;
+ this.bottom.y = b;
+
+ //center
+ this.center.x = l + w/2;
+ this.center.y = b + h/2;
+
+ //left
+ this.left.x = l;
+ this.left.y = b + h/2;
+
+ //right
+ this.right.x = r;
+ this.right.y = b + h/2;
+ }
+};
\ No newline at end of file
diff --git a/cocos2d/core/platform/miniFramework.js b/cocos2d/core/platform/miniFramework.js
new file mode 100644
index 0000000000..048a2db325
--- /dev/null
+++ b/cocos2d/core/platform/miniFramework.js
@@ -0,0 +1,264 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * the dollar sign, classic like jquery, this selector add extra methods to HTMLElement without touching its prototype
+ * it is also chainable like jquery
+ * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement
+ * @function
+ * @return {cc.$}
+ */
+cc.$ = function (x) {
+ /** @lends cc.$# */
+ var parent = (this === cc) ? document : this;
+
+ var el = (x instanceof HTMLElement) ? x : parent.querySelector(x);
+
+ if (el) {
+ /**
+ * find and return the child wth css selector (same as jquery.find)
+ * @lends cc.$#
+ * @function
+ * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement
+ * @return {cc.$}
+ */
+ el.find = el.find || cc.$;
+ /**
+ * check if a DOMNode has a specific class
+ * @lends cc.$#
+ * @function
+ * @param {String} cls
+ * @return {Boolean}
+ */
+ el.hasClass = el.hasClass || function (cls) {
+ return this.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
+ };
+ /**
+ * add a class to a DOMNode, returns self to allow chaining
+ * @lends cc.$#
+ * @function
+ * @param {String} cls
+ * @return {cc.$}
+ */
+ el.addClass = el.addClass || function (cls) {
+ if (!this.hasClass(cls)) {
+ if (this.className) {
+ this.className += " ";
+ }
+ this.className += cls;
+ }
+ return this;
+ };
+ /**
+ * remove a specific class from a DOMNode, returns self to allow chaining
+ * @lends cc.$#
+ * @function
+ * @param {String} cls
+ * @return {cc.$}
+ */
+ el.removeClass = el.removeClass || function (cls) {
+ if (this.hasClass(cls)) {
+ this.className = this.className.replace(cls, '');
+ }
+ return this;
+ };
+ /**
+ * detach it self from parent
+ * @lends cc.$#
+ * @function
+ */
+ el.remove = el.remove || function () {
+ if (this.parentNode)
+ this.parentNode.removeChild(this);
+ return this;
+ };
+
+ /**
+ * add to another element as a child
+ * @lends cc.$#
+ * @function
+ * @param {HTMLElement|cc.$} x
+ * @return {cc.$}
+ */
+ el.appendTo = el.appendTo || function (x) {
+ x.appendChild(this);
+ return this;
+ };
+
+ /**
+ * add to another element as a child and place on the top of the children list
+ * @lends cc.$#
+ * @function
+ * @param {HTMLElement|cc.$} x
+ * @return {cc.$}
+ */
+ el.prependTo = el.prependTo || function (x) {
+ ( x.childNodes[0]) ? x.insertBefore(this, x.childNodes[0]) : x.appendChild(this);
+ return this;
+ };
+
+ /**
+ * helper function for updating the css transform
+ * @lends cc.$#
+ * @function
+ * @return {cc.$}
+ */
+ el.transforms = el.transforms || function () {
+ this.style[cc.$.trans] = cc.$.translate(this.position) + cc.$.rotate(this.rotation) + cc.$.scale(this.scale) + cc.$.skew(this.skew);
+ return this;
+ };
+
+ el.position = el.position || {x: 0, y: 0};
+ el.rotation = el.rotation || 0;
+ el.scale = el.scale || {x: 1, y: 1};
+ el.skew = el.skew || {x: 0, y: 0};
+
+ /**
+ * move the element
+ * @memberOf cc.$#
+ * @name translates
+ * @function
+ * @param {Number} x in pixel
+ * @param {Number} y in pixel
+ * @return {cc.$}
+ */
+ el.translates = function (x, y) {
+ this.position.x = x;
+ this.position.y = y;
+ this.transforms();
+ return this
+ };
+
+ /**
+ * rotate the element
+ * @memberOf cc.$#
+ * @name rotate
+ * @function
+ * @param {Number} x in degrees
+ * @return {cc.$}
+ */
+ el.rotate = function (x) {
+ this.rotation = x;
+ this.transforms();
+ return this
+ };
+
+ /**
+ * resize the element
+ * @memberOf cc.$#
+ * @name resize
+ * @function
+ * @param {Number} x
+ * @param {Number} y
+ * @return {cc.$}
+ */
+ el.resize = function (x, y) {
+ this.scale.x = x;
+ this.scale.y = y;
+ this.transforms();
+ return this
+ };
+
+ /**
+ * skews the element
+ * @memberOf cc.$#
+ * @name setSkew
+ * @function
+ * @param {Number} x in degrees
+ * @param {Number} y
+ * @return {cc.$}
+ */
+ el.setSkew = function (x, y) {
+ this.skew.x = x;
+ this.skew.y = y;
+ this.transforms();
+ return this
+ };
+ }
+ return el;
+};
+//getting the prefix and css3 3d support
+switch (cc.sys.browserType) {
+ case cc.sys.BROWSER_TYPE_FIREFOX:
+ cc.$.pfx = "Moz";
+ cc.$.hd = true;
+ break;
+ case cc.sys.BROWSER_TYPE_CHROME:
+ case cc.sys.BROWSER_TYPE_SAFARI:
+ cc.$.pfx = "webkit";
+ cc.$.hd = true;
+ break;
+ case cc.sys.BROWSER_TYPE_OPERA:
+ cc.$.pfx = "O";
+ cc.$.hd = false;
+ break;
+ case cc.sys.BROWSER_TYPE_IE:
+ cc.$.pfx = "ms";
+ cc.$.hd = false;
+ break;
+ default:
+ cc.$.pfx = "webkit";
+ cc.$.hd = true;
+}
+//cache for prefixed transform
+cc.$.trans = cc.$.pfx + "Transform";
+//helper function for constructing transform strings
+cc.$.translate = (cc.$.hd) ? function (a) {
+ return "translate3d(" + a.x + "px, " + a.y + "px, 0) "
+} : function (a) {
+ return "translate(" + a.x + "px, " + a.y + "px) "
+};
+cc.$.rotate = (cc.$.hd) ? function (a) {
+ return "rotateZ(" + a + "deg) ";
+} : function (a) {
+ return "rotate(" + a + "deg) ";
+};
+cc.$.scale = function (a) {
+ return "scale(" + a.x + ", " + a.y + ") "
+};
+cc.$.skew = function (a) {
+ return "skewX(" + -a.x + "deg) skewY(" + a.y + "deg)";
+};
+
+
+/**
+ * Creates a new element, and adds cc.$ methods
+ * @param {String} x name of the element tag to create
+ * @return {cc.$}
+ */
+cc.$new = function (x) {
+ return cc.$(document.createElement(x))
+};
+cc.$.findpos = function (obj) {
+ var curleft = 0;
+ var curtop = 0;
+ do {
+ curleft += obj.offsetLeft;
+ curtop += obj.offsetTop;
+ } while (obj = obj.offsetParent);
+ return {x: curleft, y: curtop};
+};
+
diff --git a/cocos2d/core/renderer/DirtyRegion.js b/cocos2d/core/renderer/DirtyRegion.js
new file mode 100644
index 0000000000..161d1d1d69
--- /dev/null
+++ b/cocos2d/core/renderer/DirtyRegion.js
@@ -0,0 +1,337 @@
+//Region is used to label a rect which world axis aligned.
+var Region = function () {
+ this._minX = 0;
+ this._minY = 0;
+ this._maxX = 0;
+ this._maxY = 0;
+
+ this._width = 0;
+ this._height = 0;
+ this._area = 0;
+ //this.moved = false;
+};
+
+var regionProto = Region.prototype;
+
+var regionPool = [];
+
+function regionCreate() {
+ var region = regionPool.pop();
+ if (!region) {
+ region = new Region();
+ }
+ return region;
+}
+
+function regionRelease(region) {
+ regionPool.push(region);
+}
+
+regionProto.setTo = function (minX, minY, maxX, maxY) {
+ this._minX = minX;
+ this._minY = minY;
+ this._maxX = maxX;
+ this._maxY = maxY;
+ this.updateArea();
+ return this;
+};
+
+//convert region to int values which is fast for clipping
+regionProto.intValues = function () {
+ this._minX = Math.floor(this._minX);
+ this._minY = Math.floor(this._minY);
+ this._maxX = Math.ceil(this._maxX);
+ this._maxY = Math.ceil(this._maxY);
+ this.updateArea();
+};
+
+//update the area of region
+regionProto.updateArea = function () {
+ this._width = this._maxX - this._minX;
+ this._height = this._maxY - this._minY;
+ this._area = this._width * this._height;
+};
+
+//merge two region into one
+regionProto.union = function (target) {
+ if(this._width <= 0 || this._height <= 0) {
+ this.setTo(target._minX, target._minY, target._maxX, target._maxY);
+ return;
+ }
+ if (this._minX > target._minX) {
+ this._minX = target._minX;
+ }
+ if (this._minY > target._minY) {
+ this._minY = target._minY;
+ }
+ if (this._maxX < target._maxX) {
+ this._maxX = target._maxX;
+ }
+ if (this._maxY < target._maxY) {
+ this._maxY = target._maxY;
+ }
+ this.updateArea();
+};
+
+//regionProto.intersect = function (target) {
+// if (this._minX < target._minX) {
+// this._minX = target._minX;
+// }
+// if (this._maxX > target._maxX) {
+// this._maxX = target._maxX;
+// }
+// if (this._minX >= this._maxX) {
+// this.setEmpty();
+// return;
+// }
+// if (this._minY < target._minY) {
+// this._minY = target._minY;
+// }
+//
+// if (this._maxY > target._maxY) {
+// this._maxY = target._maxY;
+// }
+// if (this._minY >= this._maxY) {
+// this.setEmpty();
+// return;
+// }
+// this.updateArea();
+//};
+
+//set region to empty
+regionProto.setEmpty = function () {
+ this._minX = 0;
+ this._minY = 0;
+ this._maxX = 0;
+ this._maxY = 0;
+ this._width = 0;
+ this._height = 0;
+ this._area = 0;
+};
+
+regionProto.isEmpty = function () {
+ return this._width <= 0 || this._height <= 0;
+};
+
+//check whether two region is intersects or not
+regionProto.intersects = function (target) {
+ if (this._width <= 0 || this._height <= 0 || target._width <= 0 || target._height <= 0) {
+ return false;
+ }
+ var max = this._minX > target._minX ? this._minX : target._minX;
+ var min = this._maxX < target._maxX ? this._maxX : target._maxX;
+ if (max > min) {
+ return false;
+ }
+
+ max = this._minY > target._minY ? this._minY : target._minY;
+ min = this._maxY < target._maxY ? this._maxY : target._maxY;
+ return max <= min;
+};
+
+//update region by a rotated bounds
+regionProto.updateRegion = function (bounds, matrix) {
+ if (bounds.width == 0 || bounds.height == 0) {
+ this.setEmpty();
+ return;
+ }
+ var m = matrix;
+ var a = m.a;
+ var b = m.b;
+ var c = m.c;
+ var d = m.d;
+ var tx = m.tx;
+ var ty = m.ty;
+ var x = bounds.x;
+ var y = bounds.y;
+ var xMax = x + bounds.width;
+ var yMax = y + bounds.height;
+ var minX, minY, maxX, maxY;
+ if (a == 1.0 && b == 0.0 && c == 0.0 && d == 1.0) {
+ minX = x + tx - 1;
+ minY = y + ty - 1;
+ maxX = xMax + tx + 1;
+ maxY = yMax + ty + 1;
+ }
+ else {
+ var x0 = a * x + c * y + tx;
+ var y0 = b * x + d * y + ty;
+ var x1 = a * xMax + c * y + tx;
+ var y1 = b * xMax + d * y + ty;
+ var x2 = a * xMax + c * yMax + tx;
+ var y2 = b * xMax + d * yMax + ty;
+ var x3 = a * x + c * yMax + tx;
+ var y3 = b * x + d * yMax + ty;
+
+ var tmp = 0;
+
+ if (x0 > x1) {
+ tmp = x0;
+ x0 = x1;
+ x1 = tmp;
+ }
+ if (x2 > x3) {
+ tmp = x2;
+ x2 = x3;
+ x3 = tmp;
+ }
+
+ minX = (x0 < x2 ? x0 : x2) - 1;
+ maxX = (x1 > x3 ? x1 : x3) + 1;
+
+ if (y0 > y1) {
+ tmp = y0;
+ y0 = y1;
+ y1 = tmp;
+ }
+ if (y2 > y3) {
+ tmp = y2;
+ y2 = y3;
+ y3 = tmp;
+ }
+
+ minY = (y0 < y2 ? y0 : y2) - 1;
+ maxY = (y1 > y3 ? y1 : y3) + 1;
+ }
+ this._minX = minX;
+ this._minY = minY;
+ this._maxX = maxX;
+ this._maxY = maxY;
+ this._width = maxX - minX;
+ this._height = maxY - minY;
+ this._area = this._width * this._height;
+};
+
+//get the area of the unioned region of r1 and r2
+function unionArea(r1, r2) {
+ var minX = r1._minX < r2._minX ? r1._minX : r2._minX;
+ var minY = r1._minY < r2._minY ? r1._minY : r2._minY;
+ var maxX = r1._maxX > r2._maxX ? r1._maxX : r2._maxX;
+ var maxY = r1._maxY > r2._maxY ? r1._maxY : r2._maxY;
+ return (maxX - minX) * (maxY - minY);
+}
+
+//DirtyRegion is used to collect the dirty area which need to be rerendered in canvas
+//there may be many small regions which is dirty, the dirty region will merge it into several big one to optimise performance
+var DirtyRegion = function() {
+ this.dirtyList = [];
+ this.hasClipRect = false;
+ this.clipWidth = 0;
+ this.clipHeight = 0;
+ this.clipArea = 0;
+ this.clipRectChanged = false;
+};
+var dirtyRegionProto = DirtyRegion.prototype;
+
+//clip rect, regions will not be considered if it is outside
+dirtyRegionProto.setClipRect = function(width, height) {
+ this.hasClipRect = true;
+ this.clipRectChanged = true;
+ this.clipWidth = Math.ceil(width);
+ this.clipHeight = Math.ceil(height);
+ this.clipArea = this.clipWidth * this.clipHeight;
+};
+
+//add a new region which is dirty (need to be rendered)
+dirtyRegionProto.addRegion = function(target) {
+ var minX = target._minX, minY = target._minY, maxX = target._maxX, maxY = target._maxY;
+
+ if (this.hasClipRect) {
+ if (minX < 0) {
+ minX = 0;
+ }
+ if (minY < 0) {
+ minY = 0;
+ }
+ if (maxX > this.clipWidth) {
+ maxX = this.clipWidth;
+ }
+ if (maxY > this.clipHeight) {
+ maxY = this.clipHeight;
+ }
+ }
+ if (minX >= maxX || minY >= maxY) {
+ return false;
+ }
+ if (this.clipRectChanged) {
+ return true;
+ }
+ var dirtyList = this.dirtyList;
+ var region = regionCreate();
+ dirtyList.push(region.setTo(minX, minY, maxX, maxY));
+ this.mergeDirtyList(dirtyList);
+ return true;
+};
+
+//clear all the dirty regions
+dirtyRegionProto.clear = function() {
+ var dirtyList = this.dirtyList;
+ var length = dirtyList.length;
+ for (var i = 0; i < length; i++) {
+ regionRelease(dirtyList[i]);
+ }
+ dirtyList.length = 0;
+};
+
+//get the merged dirty regions
+dirtyRegionProto.getDirtyRegions = function() {
+ var dirtyList = this.dirtyList;
+ if (this.clipRectChanged) {
+ this.clipRectChanged = false;
+ this.clear();
+ var region = regionCreate();
+ dirtyList.push(region.setTo(0, 0, this.clipWidth, this.clipHeight));
+ }
+ else {
+ while (this.mergeDirtyList(dirtyList)) {
+ }
+ }
+ var numDirty = this.dirtyList.length;
+ if (numDirty > 0) {
+ for (var i = 0; i < numDirty; i++) {
+ this.dirtyList[i].intValues();
+ }
+ }
+ return this.dirtyList;
+};
+
+//merge the small dirty regions into bigger region, to improve the performance of dirty regions
+dirtyRegionProto.mergeDirtyList = function(dirtyList) {
+ var length = dirtyList.length;
+ if (length < 2) {
+ return false;
+ }
+ var hasClipRect = this.hasClipRect;
+ var bestDelta = length > 3 ? Number.POSITIVE_INFINITY : 0;
+ var mergeA = 0;
+ var mergeB = 0;
+ var totalArea = 0;
+ for (var i = 0; i < length - 1; i++) {
+ var regionA = dirtyList[i];
+ hasClipRect && (totalArea += regionA.area);
+ for (var j = i + 1; j < length; j++) {
+ var regionB = dirtyList[j];
+ var delta = unionArea(regionA, regionB) - regionA.area - regionB.area;
+ if (bestDelta > delta) {
+ mergeA = i;
+ mergeB = j;
+ bestDelta = delta;
+ }
+ }
+ }
+ //if the area of dirty region exceed 95% of the screen, skip the following dirty regions merge
+ if (hasClipRect && (totalArea / this.clipArea) > 0.95) {
+ this.clipRectChanged = true;
+ }
+ if (mergeA != mergeB) {
+ var region = dirtyList[mergeB];
+ dirtyList[mergeA].union(region);
+ regionRelease(region);
+ dirtyList.splice(mergeB, 1);
+ return true;
+ }
+ return false;
+};
+
+cc.Region = Region;
+cc.DirtyRegion = DirtyRegion;
diff --git a/cocos2d/core/renderer/GlobalVertexBuffer.js b/cocos2d/core/renderer/GlobalVertexBuffer.js
new file mode 100644
index 0000000000..e81c95a133
--- /dev/null
+++ b/cocos2d/core/renderer/GlobalVertexBuffer.js
@@ -0,0 +1,139 @@
+/****************************************************************************
+ Copyright (c) 2016 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+var GlobalVertexBuffer = (function () {
+
+var VERTICES_SIZE = 888;
+
+var GlobalVertexBuffer = function (gl, byteLength) {
+ // WebGL buffer
+ this.gl = gl;
+ this.vertexBuffer = gl.createBuffer();
+
+ this.size = VERTICES_SIZE;
+ this.byteLength = byteLength || VERTICES_SIZE * 4 * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
+
+ // buffer data and views
+ this.data = new ArrayBuffer(this.byteLength);
+ this.dataArray = new Float32Array(this.data);
+
+ // Init buffer data
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, this.dataArray, gl.DYNAMIC_DRAW);
+
+ this._dirty = false;
+ this._spaces = {
+ 0: this.byteLength
+ };
+};
+GlobalVertexBuffer.prototype = {
+ constructor: GlobalVertexBuffer,
+
+ allocBuffer: function (offset, size) {
+ var space = this._spaces[offset];
+ if (space && space >= size) {
+ // Remove the space
+ delete this._spaces[offset];
+ if (space > size) {
+ var newOffset = offset + size;
+ this._spaces[newOffset] = space - size;
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+
+ requestBuffer: function (size) {
+ var key, offset, available;
+ for (key in this._spaces) {
+ offset = parseInt(key);
+ available = this._spaces[key];
+ if (available >= size && this.allocBuffer(offset, size)) {
+ return offset;
+ }
+ }
+ return -1;
+ },
+
+ freeBuffer: function (offset, size) {
+ var spaces = this._spaces;
+ var i, key, end;
+ // Merge with previous space
+ for (key in spaces) {
+ i = parseInt(key);
+ if (i > offset) {
+ break;
+ }
+ if (i + spaces[key] >= offset) {
+ size = size + offset - i;
+ offset = i;
+ break;
+ }
+ }
+
+ end = offset + size;
+ // Merge with next space
+ if (this._spaces[end]) {
+ size += this._spaces[end];
+ delete this._spaces[end];
+ }
+
+ this._spaces[offset] = size;
+ },
+
+ setDirty: function () {
+ this._dirty = true;
+ },
+
+ update: function () {
+ if (this._dirty) {
+ this.gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
+ // Note: Can memorize different dirty zones and update them separately, maybe faster
+ this.gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.dataArray);
+ this._dirty = false;
+ }
+ },
+
+ updateSubData: function (offset, dataArray) {
+ this.gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
+ this.gl.bufferSubData(gl.ARRAY_BUFFER, offset, dataArray);
+ },
+
+ destroy: function () {
+ this.gl.deleteBuffer(this.vertexBuffer);
+
+ this.data = null;
+ this.positions = null;
+ this.colors = null;
+ this.texCoords = null;
+
+ this.vertexBuffer = null;
+ }
+};
+
+return GlobalVertexBuffer;
+
+})();
\ No newline at end of file
diff --git a/cocos2d/core/renderer/RendererCanvas.js b/cocos2d/core/renderer/RendererCanvas.js
new file mode 100644
index 0000000000..57e569cd81
--- /dev/null
+++ b/cocos2d/core/renderer/RendererCanvas.js
@@ -0,0 +1,438 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc.rendererCanvas = {
+ childrenOrderDirty: true,
+ assignedZ: 0,
+ assignedZStep: 1 / 10000,
+
+ _transformNodePool: [], //save nodes transform dirty
+ _renderCmds: [], //save renderer commands
+
+ _isCacheToCanvasOn: false, //a switch that whether cache the rendererCmd to cacheToCanvasCmds
+ _cacheToCanvasCmds: {}, // an array saves the renderer commands need for cache to other canvas
+ _cacheInstanceIds: [],
+ _currentID: 0,
+ _clearColor: cc.color(), //background color,default BLACK
+ _clearFillStyle: "rgb(0, 0, 0)",
+
+ _dirtyRegion: null,
+ _allNeedDraw: true,
+ _enableDirtyRegion: false,
+ _debugDirtyRegion: false,
+ _canUseDirtyRegion: false,
+ //max dirty Region count, default is 10
+ _dirtyRegionCountThreshold: 10,
+
+ getRenderCmd: function (renderableObject) {
+ //TODO Add renderCmd pool here
+ return renderableObject._createRenderCmd();
+ },
+
+ enableDirtyRegion: function (enabled) {
+ this._enableDirtyRegion = enabled;
+ },
+
+ isDirtyRegionEnabled: function () {
+ return this._enableDirtyRegion;
+ },
+
+ setDirtyRegionCountThreshold: function(threshold) {
+ this._dirtyRegionCountThreshold = threshold;
+ },
+
+ _collectDirtyRegion: function () {
+ //collect dirtyList
+ var locCmds = this._renderCmds, i, len;
+ var dirtyRegion = this._dirtyRegion;
+ var dirtryRegionCount = 0;
+ var result = true;
+ var localStatus = cc.Node.CanvasRenderCmd.RegionStatus;
+ for (i = 0, len = locCmds.length; i < len; i++) {
+ var cmd = locCmds[i];
+ var regionFlag = cmd._regionFlag;
+ var oldRegion = cmd._oldRegion;
+ var currentRegion = cmd._currentRegion;
+ if (regionFlag > localStatus.NotDirty) {
+ ++dirtryRegionCount;
+ if(dirtryRegionCount > this._dirtyRegionCountThreshold)
+ result = false;
+ //add
+ if(result) {
+ (!currentRegion.isEmpty()) && dirtyRegion.addRegion(currentRegion);
+ if (cmd._regionFlag > localStatus.Dirty) {
+ (!oldRegion.isEmpty()) && dirtyRegion.addRegion(oldRegion);
+ }
+ }
+ cmd._regionFlag = localStatus.NotDirty;
+ }
+
+ }
+
+ return result;
+ },
+
+ _beginDrawDirtyRegion: function (ctxWrapper) {
+ var ctx = ctxWrapper.getContext();
+ var dirtyList = this._dirtyRegion.getDirtyRegions();
+ ctx.save();
+ //add clip
+ var scaleX = ctxWrapper._scaleX;
+ var scaleY = ctxWrapper._scaleY;
+ ctxWrapper.setTransform({a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0}, scaleX, scaleY);
+ ctx.beginPath();
+ for (var index = 0, count = dirtyList.length; index < count; ++index) {
+ var region = dirtyList[index];
+ ctx.rect(region._minX , -region._maxY , region._width , region._height );
+ }
+ ctx.clip();
+ //end add clip
+ },
+
+ _endDrawDirtyRegion: function (ctx) {
+ ctx.restore();
+ },
+
+ _debugDrawDirtyRegion: function (ctxWrapper) {
+ if (!this._debugDirtyRegion) return;
+ var ctx = ctxWrapper.getContext();
+ var dirtyList = this._dirtyRegion.getDirtyRegions();
+ //add clip
+ var scaleX = ctxWrapper._scaleX;
+ var scaleY = ctxWrapper._scaleY;
+ ctxWrapper.setTransform({a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0}, scaleX, scaleY);
+ ctx.beginPath();
+ for (var index = 0, count = dirtyList.length; index < count; ++index) {
+ var region = dirtyList[index];
+ ctx.rect(region._minX, -region._maxY , region._width , region._height );
+ }
+ var oldstyle = ctx.fillStyle;
+ ctx.fillStyle = 'green';
+ ctx.fill();
+ ctx.fillStyle = oldstyle;
+ //end add clip
+ },
+ /**
+ * drawing all renderer command to context (default is cc._renderContext)
+ * @param {cc.CanvasContextWrapper} [ctx=cc._renderContext]
+ */
+ rendering: function (ctxWrapper) {
+ var dirtyRegion = this._dirtyRegion = this._dirtyRegion || new cc.DirtyRegion();
+ var viewport = cc._canvas;
+ var wrapper = ctxWrapper || cc._renderContext;
+ var ctx = wrapper.getContext();
+
+ var scaleX = cc.view.getScaleX(),
+ scaleY = cc.view.getScaleY();
+ wrapper.setViewScale(scaleX, scaleY);
+ wrapper.computeRealOffsetY();
+ var dirtyList = this._dirtyRegion.getDirtyRegions();
+ var locCmds = this._renderCmds, i, len;
+ var allNeedDraw = this._allNeedDraw || !this._enableDirtyRegion || !this._canUseDirtyRegion;
+ var collectResult = true;
+ if (!allNeedDraw) {
+ collectResult = this._collectDirtyRegion();
+ }
+
+ allNeedDraw = allNeedDraw || (!collectResult);
+
+ if(!allNeedDraw) {
+ this._beginDrawDirtyRegion(wrapper);
+ }
+
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ ctx.clearRect(0, 0, viewport.width, viewport.height);
+ if (this._clearColor.r !== 255 ||
+ this._clearColor.g !== 255 ||
+ this._clearColor.b !== 255) {
+ wrapper.setFillStyle(this._clearFillStyle);
+ wrapper.setGlobalAlpha(this._clearColor.a);
+ ctx.fillRect(0, 0, viewport.width, viewport.height);
+ }
+
+ for (i = 0, len = locCmds.length; i < len; i++) {
+ var cmd = locCmds[i];
+ var needRendering = false;
+ var cmdRegion = cmd._currentRegion;
+ if (!cmdRegion || allNeedDraw) {
+ needRendering = true;
+ } else {
+ for (var index = 0, count = dirtyList.length; index < count; ++index) {
+ if (dirtyList[index].intersects(cmdRegion)) {
+ needRendering = true;
+ break;
+ }
+ }
+ }
+ if (needRendering) {
+ cmd.rendering(wrapper, scaleX, scaleY);
+ }
+ }
+
+ if (!allNeedDraw) {
+ //draw debug info for dirty region if it is needed
+ this._debugDrawDirtyRegion(wrapper);
+ this._endDrawDirtyRegion(ctx);
+ }
+
+ dirtyRegion.clear();
+ this._allNeedDraw = false;
+ },
+
+ /**
+ * drawing all renderer command to cache canvas' context
+ * @param {cc.CanvasContextWrapper} ctx
+ * @param {Number} [instanceID]
+ * @param {Number} [scaleX]
+ * @param {Number} [scaleY]
+ */
+ _renderingToCacheCanvas: function (ctx, instanceID, scaleX, scaleY) {
+ if (!ctx)
+ cc.log("The context of RenderTexture is invalid.");
+ scaleX = cc.isUndefined(scaleX) ? 1 : scaleX;
+ scaleY = cc.isUndefined(scaleY) ? 1 : scaleY;
+ instanceID = instanceID || this._currentID;
+ var i, locCmds = this._cacheToCanvasCmds[instanceID], len;
+ ctx.computeRealOffsetY();
+ for (i = 0, len = locCmds.length; i < len; i++) {
+ locCmds[i].rendering(ctx, scaleX, scaleY);
+ }
+ this._removeCache(instanceID);
+
+ var locIDs = this._cacheInstanceIds;
+ if (locIDs.length === 0)
+ this._isCacheToCanvasOn = false;
+ else
+ this._currentID = locIDs[locIDs.length - 1];
+ },
+
+ _turnToCacheMode: function (renderTextureID) {
+ this._isCacheToCanvasOn = true;
+ renderTextureID = renderTextureID || 0;
+ this._cacheToCanvasCmds[renderTextureID] = [];
+ if (this._cacheInstanceIds.indexOf(renderTextureID) === -1)
+ this._cacheInstanceIds.push(renderTextureID);
+ this._currentID = renderTextureID;
+ },
+
+ _turnToNormalMode: function () {
+ this._isCacheToCanvasOn = false;
+ },
+
+ _removeCache: function (instanceID) {
+ instanceID = instanceID || this._currentID;
+ var cmds = this._cacheToCanvasCmds[instanceID];
+ if (cmds) {
+ cmds.length = 0;
+ delete this._cacheToCanvasCmds[instanceID];
+ }
+
+ var locIDs = this._cacheInstanceIds;
+ cc.arrayRemoveObject(locIDs, instanceID);
+ },
+
+ resetFlag: function () {
+ this.childrenOrderDirty = false;
+ this._transformNodePool.length = 0;
+ },
+
+ transform: function () {
+ var locPool = this._transformNodePool;
+ //sort the pool
+ locPool.sort(this._sortNodeByLevelAsc);
+
+ //transform node
+ for (var i = 0, len = locPool.length; i < len; i++) {
+ if (locPool[i]._dirtyFlag !== 0)
+ locPool[i].updateStatus();
+ }
+ locPool.length = 0;
+ },
+
+ transformDirty: function () {
+ return this._transformNodePool.length > 0;
+ },
+
+ _sortNodeByLevelAsc: function (n1, n2) {
+ return n1._curLevel - n2._curLevel;
+ },
+
+ pushDirtyNode: function (node) {
+ this._transformNodePool.push(node);
+ },
+
+ clear: function () {
+ },
+
+ clearRenderCommands: function () {
+ this._renderCmds.length = 0;
+ this._cacheInstanceIds.length = 0;
+ this._isCacheToCanvasOn = false;
+ this._allNeedDraw = true;
+ this._canUseDirtyRegion = true;
+ },
+
+ pushRenderCommand: function (cmd) {
+ if (!cmd.needDraw())
+ return;
+ if (!cmd._canUseDirtyRegion) {
+ this._canUseDirtyRegion = false;
+ }
+ if (this._isCacheToCanvasOn) {
+ var currentId = this._currentID, locCmdBuffer = this._cacheToCanvasCmds;
+ var cmdList = locCmdBuffer[currentId];
+ if (cmdList.indexOf(cmd) === -1)
+ cmdList.push(cmd);
+ } else {
+ if (this._renderCmds.indexOf(cmd) === -1)
+ this._renderCmds.push(cmd);
+ }
+ }
+};
+
+(function () {
+ cc.CanvasContextWrapper = function (context) {
+ this._context = context;
+
+ this._saveCount = 0;
+ this._currentAlpha = context.globalAlpha;
+ this._currentCompositeOperation = context.globalCompositeOperation;
+ this._currentFillStyle = context.fillStyle;
+ this._currentStrokeStyle = context.strokeStyle;
+
+ this._offsetX = 0;
+ this._offsetY = 0;
+ this._realOffsetY = this.height;
+ this._armatureMode = 0;
+ };
+
+ var proto = cc.CanvasContextWrapper.prototype;
+
+ proto.resetCache = function () {
+ var context = this._context;
+ //call it after resize cc._canvas, because context will reset.
+ this._currentAlpha = context.globalAlpha;
+ this._currentCompositeOperation = context.globalCompositeOperation;
+ this._currentFillStyle = context.fillStyle;
+ this._currentStrokeStyle = context.strokeStyle;
+ this._realOffsetY = this._context.canvas.height + this._offsetY;
+ };
+
+ proto.setOffset = function (x, y) {
+ this._offsetX = x;
+ this._offsetY = y;
+ this._realOffsetY = this._context.canvas.height + this._offsetY;
+ };
+
+ proto.computeRealOffsetY = function () {
+ this._realOffsetY = this._context.canvas.height + this._offsetY;
+ };
+
+ proto.setViewScale = function (scaleX, scaleY) {
+ //call it at cc.renderCanvas.rendering
+ this._scaleX = scaleX;
+ this._scaleY = scaleY;
+ };
+
+ proto.getContext = function () {
+ return this._context;
+ };
+
+ proto.save = function () {
+ this._context.save();
+ this._saveCount++;
+ };
+
+ proto.restore = function () {
+ this._context.restore();
+ this._saveCount--;
+ };
+
+ proto.setGlobalAlpha = function (alpha) {
+ if (this._saveCount > 0) {
+ this._context.globalAlpha = alpha;
+ } else {
+ if (this._currentAlpha !== alpha) {
+ this._currentAlpha = alpha;
+ this._context.globalAlpha = alpha;
+ }
+ }
+ };
+
+ proto.setCompositeOperation = function (compositionOperation) {
+ if (this._saveCount > 0) {
+ this._context.globalCompositeOperation = compositionOperation;
+ } else {
+ if (this._currentCompositeOperation !== compositionOperation) {
+ this._currentCompositeOperation = compositionOperation;
+ this._context.globalCompositeOperation = compositionOperation;
+ }
+ }
+ };
+
+ proto.setFillStyle = function (fillStyle) {
+ if (this._saveCount > 0) {
+ this._context.fillStyle = fillStyle;
+ } else {
+ if (this._currentFillStyle !== fillStyle) {
+ this._currentFillStyle = fillStyle;
+ this._context.fillStyle = fillStyle;
+ }
+ }
+ };
+
+ proto.setStrokeStyle = function (strokeStyle) {
+ if (this._saveCount > 0) {
+ this._context.strokeStyle = strokeStyle;
+ } else {
+ if (this._currentStrokeStyle !== strokeStyle) {
+ this._currentStrokeStyle = strokeStyle;
+ this._context.strokeStyle = strokeStyle;
+ }
+ }
+ };
+
+ proto.setTransform = function (t, scaleX, scaleY) {
+ if (this._armatureMode > 0) {
+ //ugly for armature
+ this.restore();
+ this.save();
+ this._context.transform(t.a * scaleX, -t.b * scaleY, -t.c * scaleX, t.d * scaleY, t.tx * scaleX, -(t.ty * scaleY));
+ } else {
+ this._context.setTransform(t.a * scaleX, -t.b * scaleY, -t.c * scaleX, t.d * scaleY, this._offsetX + t.tx * scaleX, this._realOffsetY - (t.ty * scaleY));
+ }
+ };
+
+ proto._switchToArmatureMode = function (enable, t, scaleX, scaleY) {
+ if (enable) {
+ this._armatureMode++;
+ this._context.setTransform(t.a, t.c, t.b, t.d, this._offsetX + t.tx * scaleX, this._realOffsetY - (t.ty * scaleY));
+ this.save();
+ } else {
+ this._armatureMode--;
+ this.restore();
+ }
+ };
+})();
+
diff --git a/cocos2d/core/renderer/RendererWebGL.js b/cocos2d/core/renderer/RendererWebGL.js
new file mode 100644
index 0000000000..d0655f6f28
--- /dev/null
+++ b/cocos2d/core/renderer/RendererWebGL.js
@@ -0,0 +1,462 @@
+/****************************************************************************
+ Copyright (c) 2013-2016 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc.rendererWebGL = (function () {
+
+// Internal variables
+ // Batching general informations
+var _batchedInfo = {
+ // The batched texture, all batching element should have the same texture
+ texture: null,
+ // The batched blend source, all batching element should have the same blend source
+ blendSrc: null,
+ // The batched blend destination, all batching element should have the same blend destination
+ blendDst: null,
+ // The batched gl program state, all batching element should have the same state
+ glProgramState: null
+ },
+
+ _batchBroken = false,
+ _indexBuffer = null,
+ _vertexBuffer = null,
+ // Total vertex size
+ _maxVertexSize = 0,
+ // Current batching vertex size
+ _batchingSize = 0,
+ // Current batching index size
+ _indexSize = 0,
+ // Float size per vertex
+ _sizePerVertex = 6,
+ // buffer data and views
+ _vertexData = null,
+ _vertexDataSize = 0,
+ _vertexDataF32 = null,
+ _vertexDataUI32 = null,
+ _indexData = null,
+ _prevIndexSize = 0,
+ _pureQuad = true,
+ _IS_IOS = false;
+
+
+// Inspired from @Heishe's gotta-batch-them-all branch
+// https://github.com/Talisca/cocos2d-html5/commit/de731f16414eb9bcaa20480006897ca6576d362c
+function updateBuffer (numVertex) {
+ var gl = cc._renderContext;
+ // Update index buffer size
+ if (_indexBuffer) {
+ var indexCount = Math.ceil(numVertex / 4) * 6;
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _indexBuffer);
+ _indexData = new Uint16Array(indexCount);
+ var currentQuad = 0;
+ for (var i = 0, len = indexCount; i < len; i += 6) {
+ _indexData[i] = currentQuad + 0;
+ _indexData[i + 1] = currentQuad + 1;
+ _indexData[i + 2] = currentQuad + 2;
+ _indexData[i + 3] = currentQuad + 1;
+ _indexData[i + 4] = currentQuad + 2;
+ _indexData[i + 5] = currentQuad + 3;
+ currentQuad += 4;
+ }
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, _indexData, gl.DYNAMIC_DRAW);
+ }
+ // Update vertex buffer size
+ if (_vertexBuffer) {
+ _vertexDataSize = numVertex * _sizePerVertex;
+ var byteLength = _vertexDataSize * 4;
+ _vertexData = new ArrayBuffer(byteLength);
+ _vertexDataF32 = new Float32Array(_vertexData);
+ _vertexDataUI32 = new Uint32Array(_vertexData);
+ // Init buffer data
+ gl.bindBuffer(gl.ARRAY_BUFFER, _vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, _vertexDataF32, gl.DYNAMIC_DRAW);
+ }
+ // Downsize by 200 to avoid vertex data overflow
+ _maxVertexSize = numVertex - 200;
+}
+
+// Inspired from @Heishe's gotta-batch-them-all branch
+// https://github.com/Talisca/cocos2d-html5/commit/de731f16414eb9bcaa20480006897ca6576d362c
+function initQuadBuffer (numVertex) {
+ var gl = cc._renderContext;
+ if (_indexBuffer === null) {
+ // TODO do user need to release the memory ?
+ _vertexBuffer = gl.createBuffer();
+ _indexBuffer = gl.createBuffer();
+ }
+ updateBuffer(numVertex);
+}
+
+var VertexType = {
+ QUAD : 0,
+ TRIANGLE : 1,
+ CUSTOM: 2
+};
+
+return {
+ mat4Identity: null,
+
+ childrenOrderDirty: true,
+ assignedZ: 0,
+ assignedZStep: 1 / 100,
+
+ VertexType: VertexType,
+
+ _transformNodePool: [], //save nodes transform dirty
+ _renderCmds: [], //save renderer commands
+
+ _isCacheToBufferOn: false, //a switch that whether cache the rendererCmd to cacheToCanvasCmds
+ _cacheToBufferCmds: {}, // an array saves the renderer commands need for cache to other canvas
+ _cacheInstanceIds: [],
+ _currentID: 0,
+ _clearColor: cc.color(0, 0, 0, 255), //background color,default BLACK
+
+ init: function () {
+ var gl = cc._renderContext;
+ gl.disable(gl.CULL_FACE);
+ gl.disable(gl.DEPTH_TEST);
+
+ this.mat4Identity = new cc.math.Matrix4();
+ this.mat4Identity.identity();
+ initQuadBuffer(cc.BATCH_VERTEX_COUNT);
+ if (cc.sys.os === cc.sys.OS_IOS) {
+ _IS_IOS = true;
+ }
+ },
+
+ getVertexSize: function () {
+ return _maxVertexSize;
+ },
+
+ getRenderCmd: function (renderableObject) {
+ //TODO Add renderCmd pool here
+ return renderableObject._createRenderCmd();
+ },
+
+ _turnToCacheMode: function (renderTextureID) {
+ this._isCacheToBufferOn = true;
+ renderTextureID = renderTextureID || 0;
+ if (!this._cacheToBufferCmds[renderTextureID]) {
+ this._cacheToBufferCmds[renderTextureID] = [];
+ }
+ else {
+ this._cacheToBufferCmds[renderTextureID].length = 0;
+ }
+ if (this._cacheInstanceIds.indexOf(renderTextureID) === -1) {
+ this._cacheInstanceIds.push(renderTextureID);
+ }
+ this._currentID = renderTextureID;
+ },
+
+ _turnToNormalMode: function () {
+ this._isCacheToBufferOn = false;
+ },
+
+ _removeCache: function (instanceID) {
+ instanceID = instanceID || this._currentID;
+ var cmds = this._cacheToBufferCmds[instanceID];
+ if (cmds) {
+ cmds.length = 0;
+ delete this._cacheToBufferCmds[instanceID];
+ }
+
+ var locIDs = this._cacheInstanceIds;
+ cc.arrayRemoveObject(locIDs, instanceID);
+ },
+
+ /**
+ * drawing all renderer command to cache canvas' context
+ * @param {Number} [renderTextureId]
+ */
+ _renderingToBuffer: function (renderTextureId) {
+ renderTextureId = renderTextureId || this._currentID;
+ var locCmds = this._cacheToBufferCmds[renderTextureId];
+ var ctx = cc._renderContext;
+ this.rendering(ctx, locCmds);
+ this._removeCache(renderTextureId);
+
+ var locIDs = this._cacheInstanceIds;
+ if (locIDs.length === 0)
+ this._isCacheToBufferOn = false;
+ else
+ this._currentID = locIDs[locIDs.length - 1];
+ },
+
+ //reset renderer's flag
+ resetFlag: function () {
+ if (this.childrenOrderDirty) {
+ this.childrenOrderDirty = false;
+ }
+ this._transformNodePool.length = 0;
+ },
+
+ //update the transform data
+ transform: function () {
+ var locPool = this._transformNodePool;
+ //sort the pool
+ locPool.sort(this._sortNodeByLevelAsc);
+ //transform node
+ var i, len, cmd;
+ for (i = 0, len = locPool.length; i < len; i++) {
+ cmd = locPool[i];
+ cmd.updateStatus();
+ }
+ locPool.length = 0;
+ },
+
+ transformDirty: function () {
+ return this._transformNodePool.length > 0;
+ },
+
+ _sortNodeByLevelAsc: function (n1, n2) {
+ return n1._curLevel - n2._curLevel;
+ },
+
+ pushDirtyNode: function (node) {
+ //if (this._transformNodePool.indexOf(node) === -1)
+ this._transformNodePool.push(node);
+ },
+
+ clearRenderCommands: function () {
+ // Copy previous command list for late check in rendering
+ this._renderCmds.length = 0;
+ },
+
+ clear: function () {
+ var gl = cc._renderContext;
+ gl.clearColor(this._clearColor.r / 255, this._clearColor.g / 255, this._clearColor.b / 255, this._clearColor.a / 255);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ },
+
+ setDepthTest: function (enable) {
+ var gl = cc._renderContext;
+ if (enable) {
+ gl.clearDepth(1.0);
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LEQUAL);
+ }
+ else {
+ gl.disable(gl.DEPTH_TEST);
+ }
+ },
+
+ pushRenderCommand: function (cmd) {
+ if (!cmd.rendering && !cmd.uploadData)
+ return;
+ if (this._isCacheToBufferOn) {
+ var currentId = this._currentID, locCmdBuffer = this._cacheToBufferCmds;
+ var cmdList = locCmdBuffer[currentId];
+ if (cmdList.indexOf(cmd) === -1)
+ cmdList.push(cmd);
+ } else {
+ if (this._renderCmds.indexOf(cmd) === -1) {
+ this._renderCmds.push(cmd);
+ }
+ }
+ },
+
+ _increaseBatchingSize: function (increment, vertexType, indices) {
+ vertexType = vertexType || VertexType.QUAD;
+ var i, curr;
+ switch (vertexType) {
+ case VertexType.QUAD:
+ for (i = 0; i < increment; i += 4) {
+ curr = _batchingSize + i;
+ _indexData[_indexSize++] = curr + 0;
+ _indexData[_indexSize++] = curr + 1;
+ _indexData[_indexSize++] = curr + 2;
+ _indexData[_indexSize++] = curr + 1;
+ _indexData[_indexSize++] = curr + 2;
+ _indexData[_indexSize++] = curr + 3;
+ }
+ break;
+ case VertexType.TRIANGLE:
+ _pureQuad = false;
+ for (i = 0; i < increment; i += 3) {
+ curr = _batchingSize + i;
+ _indexData[_indexSize++] = curr + 0;
+ _indexData[_indexSize++] = curr + 1;
+ _indexData[_indexSize++] = curr + 2;
+ }
+ break;
+ case VertexType.CUSTOM:
+ // CUSTOM type increase the indices data
+ _pureQuad = false;
+ var len = indices.length;
+ for (i = 0; i < len; i++) {
+ _indexData[_indexSize++] = _batchingSize + indices[i];
+ }
+ break;
+ default:
+ return;
+ }
+ _batchingSize += increment;
+ },
+
+ _updateBatchedInfo: function (texture, blendFunc, glProgramState) {
+ if (texture !== _batchedInfo.texture ||
+ blendFunc.src !== _batchedInfo.blendSrc ||
+ blendFunc.dst !== _batchedInfo.blendDst ||
+ glProgramState !== _batchedInfo.glProgramState) {
+ // Draw batched elements
+ this._batchRendering();
+ // Update _batchedInfo
+ _batchedInfo.texture = texture;
+ _batchedInfo.blendSrc = blendFunc.src;
+ _batchedInfo.blendDst = blendFunc.dst;
+ _batchedInfo.glProgramState = glProgramState;
+
+ return true;
+ }
+ else {
+ return false;
+ }
+ },
+
+ _breakBatch: function () {
+ _batchBroken = true;
+ },
+
+ _uploadBufferData: function (cmd) {
+ if (_batchingSize >= _maxVertexSize) {
+ this._batchRendering();
+ }
+
+ // Check batching
+ var node = cmd._node;
+ var texture = node._texture || (node._spriteFrame && node._spriteFrame._texture);
+ var blendSrc = node._blendFunc.src;
+ var blendDst = node._blendFunc.dst;
+ var glProgramState = cmd._glProgramState;
+ if (_batchBroken ||
+ _batchedInfo.texture !== texture ||
+ _batchedInfo.blendSrc !== blendSrc ||
+ _batchedInfo.blendDst !== blendDst ||
+ _batchedInfo.glProgramState !== glProgramState) {
+ // Draw batched elements
+ this._batchRendering();
+ // Update _batchedInfo
+ _batchedInfo.texture = texture;
+ _batchedInfo.blendSrc = blendSrc;
+ _batchedInfo.blendDst = blendDst;
+ _batchedInfo.glProgramState = glProgramState;
+ _batchBroken = false;
+ }
+
+ // Upload vertex data
+ var len = cmd.uploadData(_vertexDataF32, _vertexDataUI32, _batchingSize * _sizePerVertex);
+ if (len > 0) {
+ this._increaseBatchingSize(len, cmd.vertexType);
+ }
+ },
+
+ _batchRendering: function () {
+ if (_batchingSize === 0 || !_batchedInfo.texture) {
+ return;
+ }
+
+ var gl = cc._renderContext;
+ var texture = _batchedInfo.texture;
+ var glProgramState = _batchedInfo.glProgramState;
+ var uploadAll = _batchingSize > _maxVertexSize * 0.5;
+
+ if (glProgramState) {
+ glProgramState.apply();
+ glProgramState.getGLProgram()._updateProjectionUniform();
+ }
+
+ cc.glBlendFunc(_batchedInfo.blendSrc, _batchedInfo.blendDst);
+ cc.glBindTexture2DN(0, texture); // = cc.glBindTexture2D(texture);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, _vertexBuffer);
+ // upload the vertex data to the gl buffer
+ if (uploadAll) {
+ gl.bufferData(gl.ARRAY_BUFFER, _vertexDataF32, gl.DYNAMIC_DRAW);
+ }
+ else {
+ var view = _vertexDataF32.subarray(0, _batchingSize * _sizePerVertex);
+ gl.bufferData(gl.ARRAY_BUFFER, view, gl.DYNAMIC_DRAW);
+ }
+
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16);
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _indexBuffer);
+ if (!_prevIndexSize || !_pureQuad || _indexSize > _prevIndexSize) {
+ if (uploadAll) {
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, _indexData, gl.DYNAMIC_DRAW);
+ }
+ else {
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, _indexData.subarray(0, _indexSize), gl.DYNAMIC_DRAW);
+ }
+ }
+ gl.drawElements(gl.TRIANGLES, _indexSize, gl.UNSIGNED_SHORT, 0);
+
+ cc.g_NumberOfDraws++;
+
+ if (_pureQuad) {
+ _prevIndexSize = _indexSize;
+ }
+ else {
+ _prevIndexSize = 0;
+ _pureQuad = true;
+ }
+ _batchingSize = 0;
+ _indexSize = 0;
+ },
+
+ /**
+ * drawing all renderer command to context (default is cc._renderContext)
+ * @param {WebGLRenderingContext} [ctx=cc._renderContext]
+ */
+ rendering: function (ctx, cmds) {
+ var locCmds = cmds || this._renderCmds,
+ i, len, cmd,
+ context = ctx || cc._renderContext;
+
+ // Reset buffer for rendering
+ context.bindBuffer(gl.ARRAY_BUFFER, null);
+
+ for (i = 0, len = locCmds.length; i < len; ++i) {
+ cmd = locCmds[i];
+ if (!cmd.needDraw()) continue;
+
+ if (cmd.uploadData) {
+ this._uploadBufferData(cmd);
+ }
+ else {
+ if (_batchingSize > 0) {
+ this._batchRendering();
+ }
+ cmd.rendering(context);
+ }
+ }
+ this._batchRendering();
+ _batchedInfo.texture = null;
+ }
+};
+})();
diff --git a/cocos2d/core/scenes/CCLoaderScene.js b/cocos2d/core/scenes/CCLoaderScene.js
new file mode 100644
index 0000000000..2f051811b1
--- /dev/null
+++ b/cocos2d/core/scenes/CCLoaderScene.js
@@ -0,0 +1,165 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+/**
+ * cc.LoaderScene is a scene that you can load it when you loading files
+ * cc.LoaderScene can present thedownload progress
+ * @class
+ * @extends cc.Scene
+ * @example
+ * var lc = new cc.LoaderScene();
+ */
+cc.LoaderScene = cc.Scene.extend({
+ _interval : null,
+ _label : null,
+ _logo : null,
+ _className:"LoaderScene",
+ cb: null,
+ target: null,
+ /**
+ * Contructor of cc.LoaderScene
+ * @returns {boolean}
+ */
+ init : function(){
+ var self = this;
+
+ //logo
+ var logoWidth = 160;
+ var logoHeight = 200;
+
+ // bg
+ var bgLayer = self._bgLayer = new cc.LayerColor(cc.color(32, 32, 32, 255));
+ self.addChild(bgLayer, 0);
+
+ //image move to CCSceneFile.js
+ var fontSize = 24, lblHeight = -logoHeight / 2 + 100;
+ if(cc._loaderImage){
+ //loading logo
+ cc.loader.loadImg(cc._loaderImage, {isCrossOrigin : false }, function(err, img){
+ logoWidth = img.width;
+ logoHeight = img.height;
+ self._initStage(img, cc.visibleRect.center);
+ });
+ fontSize = 14;
+ lblHeight = -logoHeight / 2 - 10;
+ }
+ //loading percent
+ var label = self._label = new cc.LabelTTF("Loading... 0%", "Arial", fontSize);
+ label.setPosition(cc.pAdd(cc.visibleRect.center, cc.p(0, lblHeight)));
+ label.setColor(cc.color(180, 180, 180));
+ bgLayer.addChild(this._label, 10);
+ return true;
+ },
+
+ _initStage: function (img, centerPos) {
+ var self = this;
+ var texture2d = self._texture2d = new cc.Texture2D();
+ texture2d.initWithElement(img);
+ texture2d.handleLoadedTexture();
+ var logo = self._logo = new cc.Sprite(texture2d);
+ logo.setScale(cc.contentScaleFactor());
+ logo.x = centerPos.x;
+ logo.y = centerPos.y;
+ self._bgLayer.addChild(logo, 10);
+ },
+ /**
+ * custom onEnter
+ */
+ onEnter: function () {
+ var self = this;
+ cc.Node.prototype.onEnter.call(self);
+ self.schedule(self._startLoading, 0.3);
+ },
+ /**
+ * custom onExit
+ */
+ onExit: function () {
+ cc.Node.prototype.onExit.call(this);
+ var tmpStr = "Loading... 0%";
+ this._label.setString(tmpStr);
+ },
+
+ /**
+ * init with resources
+ * @param {Array} resources
+ * @param {Function|String} cb
+ * @param {Object} target
+ */
+ initWithResources: function (resources, cb, target) {
+ if(cc.isString(resources))
+ resources = [resources];
+ this.resources = resources || [];
+ this.cb = cb;
+ this.target = target;
+ },
+
+ _startLoading: function () {
+ var self = this;
+ self.unschedule(self._startLoading);
+ var res = self.resources;
+ cc.loader.load(res,
+ function (result, count, loadedCount) {
+ var percent = (loadedCount / count * 100) | 0;
+ percent = Math.min(percent, 100);
+ self._label.setString("Loading... " + percent + "%");
+ }, function () {
+ if (self.cb)
+ self.cb.call(self.target);
+ });
+ },
+
+ _updateTransform: function(){
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ this._bgLayer._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ this._label._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ this._logo && this._logo._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ }
+});
+/**
+ * cc.LoaderScene.preload can present a loaderScene with download progress.
+ * when all the resource are downloaded it will invoke call function
+ * @param resources
+ * @param cb
+ * @param target
+ * @returns {cc.LoaderScene|*}
+ * @example
+ * //Example
+ * cc.LoaderScene.preload(g_resources, function () {
+ cc.director.runScene(new HelloWorldScene());
+ }, this);
+ */
+cc.LoaderScene.preload = function(resources, cb, target){
+ var _cc = cc;
+ if(!_cc.loaderScene) {
+ _cc.loaderScene = new cc.LoaderScene();
+ _cc.loaderScene.init();
+ cc.eventManager.addCustomListener(cc.Director.EVENT_PROJECTION_CHANGED, function(){
+ _cc.loaderScene._updateTransform();
+ });
+ }
+ _cc.loaderScene.initWithResources(resources, cb, target);
+
+ cc.director.runScene(_cc.loaderScene);
+ return _cc.loaderScene;
+};
\ No newline at end of file
diff --git a/cocos2d/layers_scenes_transitions_nodes/CCScene.js b/cocos2d/core/scenes/CCScene.js
similarity index 86%
rename from cocos2d/layers_scenes_transitions_nodes/CCScene.js
rename to cocos2d/core/scenes/CCScene.js
index 8c85dd53b4..a54a179dcd 100644
--- a/cocos2d/layers_scenes_transitions_nodes/CCScene.js
+++ b/cocos2d/core/scenes/CCScene.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -36,27 +36,26 @@
* It is a good practice to use and cc.Scene as the parent of all your nodes.
* @class
* @extends cc.Node
+ * @example
+ * var scene = new cc.Scene();
*/
cc.Scene = cc.Node.extend(/** @lends cc.Scene# */{
/**
- * Constructor
+ * Constructor of cc.Scene
*/
+ _className:"Scene",
ctor:function () {
cc.Node.prototype.ctor.call(this);
this._ignoreAnchorPointForPosition = true;
- this.setAnchorPoint(cc.p(0.5, 0.5));
- this.setContentSize(cc.Director.getInstance().getWinSize());
+ this.setAnchorPoint(0.5, 0.5);
+ this.setContentSize(cc.director.getWinSize());
}
});
/**
* creates a scene
+ * @deprecated since v3.0,please use new cc.Scene() instead.
* @return {cc.Scene}
- * @example
- * // Example
- * var aScene = cc.Scene.create();
- * //OR
- * var aScene = new cc.Scene();
*/
cc.Scene.create = function () {
return new cc.Scene();
diff --git a/cocos2d/sprite_nodes/CCAnimation.js b/cocos2d/core/sprites/CCAnimation.js
similarity index 52%
rename from cocos2d/sprite_nodes/CCAnimation.js
rename to cocos2d/core/sprites/CCAnimation.js
index 912b042855..1c653a0bea 100644
--- a/cocos2d/sprite_nodes/CCAnimation.js
+++ b/cocos2d/core/sprites/CCAnimation.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -34,26 +34,44 @@
*
* @class
* @extends cc.Class
+ * @param spriteFrame
+ * @param delayUnits
+ * @param userInfo
+ * @returns {AnimationFrame}
*/
cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
_spriteFrame:null,
_delayPerUnit:0,
_userInfo:null,
- ctor:function () {
- this._delayPerUnit = 0;
+ ctor:function (spriteFrame, delayUnits, userInfo) {
+ this._spriteFrame = spriteFrame || null;
+ this._delayPerUnit = delayUnits || 0;
+ this._userInfo = userInfo || null;
},
+ /**
+ * Create a new animation frame and copy all contents into it
+ * @returns {AnimationFrame}
+ */
clone: function(){
var frame = new cc.AnimationFrame();
frame.initWithSpriteFrame(this._spriteFrame.clone(), this._delayPerUnit, this._userInfo);
return frame;
},
+ /**
+ * Create a new animation frame and copy all contents into it
+ * @returns {AnimationFrame}
+ */
copyWithZone:function (pZone) {
return cc.clone(this);
},
+ /**
+ * Create a new animation frame and copy all contents into it
+ * @returns {AnimationFrame}
+ */
copy:function (pZone) {
var newFrame = new cc.AnimationFrame();
newFrame.initWithSpriteFrame(this._spriteFrame.clone(), this._delayPerUnit, this._userInfo);
@@ -75,7 +93,7 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
},
/**
- * cc.SpriteFrameName to be used
+ * Returns sprite frame to be used
* @return {cc.SpriteFrame}
*/
getSpriteFrame:function () {
@@ -83,7 +101,7 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
},
/**
- * cc.SpriteFrameName to be used
+ * Sets sprite frame to be used
* @param {cc.SpriteFrame} spriteFrame
*/
setSpriteFrame:function (spriteFrame) {
@@ -91,7 +109,7 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
},
/**
- * how many units of time the frame takes getter
+ * Returns how many units of time the frame takes getter
* @return {Number}
*/
getDelayUnits:function () {
@@ -99,7 +117,7 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
},
/**
- * how many units of time the frame takes setter
+ * Sets how many units of time the frame takes setter
* @param delayUnits
*/
setDelayUnits:function (delayUnits) {
@@ -107,8 +125,7 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
},
/**
- * A cc.AnimationFrameDisplayedNotification notification will be broadcasted when the frame is displayed with this dictionary as UserInfo.
- * If UserInfo is nil, then no notification will be broadcasted.
+ * Returns the user custom information
* @return {object}
*/
getUserInfo:function () {
@@ -116,6 +133,7 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
},
/**
+ * Sets the user custom information
* @param {object} userInfo
*/
setUserInfo:function (userInfo) {
@@ -123,28 +141,56 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{
}
});
+/**
+ * Creates an animation frame.
+ * @deprecated since v3.0, please use the new construction instead
+ * @param {cc.SpriteFrame} spriteFrame
+ * @param {Number} delayUnits
+ * @param {object} userInfo
+ * @see cc.AnimationFrame
+ */
+cc.AnimationFrame.create = function(spriteFrame,delayUnits,userInfo){
+ return new cc.AnimationFrame(spriteFrame,delayUnits,userInfo);
+};
+
/**
*
* A cc.Animation object is used to perform animations on the cc.Sprite objects.
*
* The cc.Animation object contains cc.SpriteFrame objects, and a possible delay between the frames.
- * You can animate a cc.Animation object by using the cc.Animate action. Example:
+ * You can animate a cc.Animation object by using the cc.Animate action.
*
* @class
* @extends cc.Class
+ * @param {Array} frames
+ * @param {Number} delay
+ * @param {Number} [loops=1]
*
* @example
- * //create an animation object
- * var animation = cc.Animation.create();
+ * // 1. Creates an empty animation
+ * var animation1 = new cc.Animation();
*
- * //add a sprite frame to this animation
- * animation.addFrameWithFile("grossini_dance_01.png");
+ * // 2. Create an animation with sprite frames, delay and loops.
+ * var spriteFrames = [];
+ * var frame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png");
+ * spriteFrames.push(frame);
+ * var animation1 = new cc.Animation(spriteFrames);
+ * var animation2 = new cc.Animation(spriteFrames, 0.2);
+ * var animation2 = new cc.Animation(spriteFrames, 0.2, 2);
+ *
+ * // 3. Create an animation with animation frames, delay and loops.
+ * var animationFrames = [];
+ * var frame = new cc.AnimationFrame();
+ * animationFrames.push(frame);
+ * var animation1 = new cc.Animation(animationFrames);
+ * var animation2 = new cc.Animation(animationFrames, 0.2);
+ * var animation3 = new cc.Animation(animationFrames, 0.2, 2);
*
* //create an animate with this animation
- * var action = cc.Animate.create(animation);
+ * var action = cc.animate(animation1);
*
* //run animate
- * this._grossini.runAction(action);
+ * sprite.runAction(action);
*/
cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
_frames:null,
@@ -154,17 +200,29 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
_delayPerUnit:0,
_totalDelayUnits:0,
- /**
- * Constructor
- */
- ctor:function () {
+ ctor:function (frames, delay, loops) {
this._frames = [];
+
+ if (frames === undefined) {
+ this.initWithSpriteFrames(null, 0);
+ } else {
+ var frame0 = frames[0];
+ if(frame0){
+ if (frame0 instanceof cc.SpriteFrame) {
+ //init with sprite frames , delay and loops.
+ this.initWithSpriteFrames(frames, delay, loops);
+ }else if(frame0 instanceof cc.AnimationFrame) {
+ //init with sprite frames , delay and loops.
+ this.initWithAnimationFrames(frames, delay, loops);
+ }
+ }
+ }
},
// attributes
/**
- * return array of CCAnimationFrames
+ * Returns the array of animation frames
* @return {Array}
*/
getFrames:function () {
@@ -172,7 +230,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * array of CCAnimationFrames setter
+ * Sets array of animation frames
* @param {Array} frames
*/
setFrames:function (frames) {
@@ -180,7 +238,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * adds a frame to a cc.Animation The frame will be added with one "delay unit".
+ * Adds a frame to a cc.Animation, the frame will be added with one "delay unit".
* @param {cc.SpriteFrame} frame
*/
addSpriteFrame:function (frame) {
@@ -197,10 +255,11 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
* @param {String} fileName
*/
addSpriteFrameWithFile:function (fileName) {
- var texture = cc.TextureCache.getInstance().addImage(fileName);
- var rect = cc.RectZero();
- rect.size = texture.getContentSize();
- var frame = cc.SpriteFrame.createWithTexture(texture, rect);
+ var texture = cc.textureCache.addImage(fileName);
+ var rect = cc.rect(0, 0, 0, 0);
+ rect.width = texture.width;
+ rect.height = texture.height;
+ var frame = new cc.SpriteFrame(texture, rect);
this.addSpriteFrame(frame);
},
@@ -210,32 +269,38 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
* @param {cc.Rect} rect
*/
addSpriteFrameWithTexture:function (texture, rect) {
- var pFrame = cc.SpriteFrame.createWithTexture(texture, rect);
+ var pFrame = new cc.SpriteFrame(texture, rect);
this.addSpriteFrame(pFrame);
},
/**
- * Initializes a cc.Animation with cc.AnimationFrame
+ * Initializes a cc.Animation with cc.AnimationFrame, do not call this method yourself, please pass parameters to constructor to initialize.
* @param {Array} arrayOfAnimationFrames
* @param {Number} delayPerUnit
- * @param {Number} loops
+ * @param {Number} [loops=1]
*/
initWithAnimationFrames:function (arrayOfAnimationFrames, delayPerUnit, loops) {
- cc.ArrayVerifyType(arrayOfAnimationFrames, cc.AnimationFrame);
+ cc.arrayVerifyType(arrayOfAnimationFrames, cc.AnimationFrame);
this._delayPerUnit = delayPerUnit;
- this._loops = loops;
+ this._loops = loops === undefined ? 1 : loops;
+ this._totalDelayUnits = 0;
- this.setFrames([]);
+ var locFrames = this._frames;
+ locFrames.length = 0;
for (var i = 0; i < arrayOfAnimationFrames.length; i++) {
var animFrame = arrayOfAnimationFrames[i];
- this._frames.push(animFrame);
+ locFrames.push(animFrame);
this._totalDelayUnits += animFrame.getDelayUnits();
}
return true;
},
+ /**
+ * Clone the current animation
+ * @return {cc.Animation}
+ */
clone: function(){
var animation = new cc.Animation();
animation.initWithAnimationFrames(this._copyFrames(), this._delayPerUnit, this._loops);
@@ -244,7 +309,8 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * @param {cc.Animation} pZone
+ * Clone the current animation
+ * @return {cc.Animation}
*/
copyWithZone:function (pZone) {
var pCopy = new cc.Animation();
@@ -260,12 +326,17 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
return copyFrames;
},
+ /**
+ * Clone the current animation
+ * @param pZone
+ * @returns {cc.Animation}
+ */
copy:function (pZone) {
return this.copyWithZone(null);
},
/**
- * return how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ...
+ * Returns how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ...
* @return {Number}
*/
getLoops:function () {
@@ -273,7 +344,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * set how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ...
+ * Sets how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ...
* @param {Number} value
*/
setLoops:function (value) {
@@ -281,7 +352,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * whether or not it shall restore the original frame when the animation finishes
+ * Sets whether or not it shall restore the original frame when the animation finishes
* @param {Boolean} restOrigFrame
*/
setRestoreOriginalFrame:function (restOrigFrame) {
@@ -289,7 +360,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * return whether or not it shall restore the original frame when the animation finishes
+ * Returns whether or not it shall restore the original frame when the animation finishes
* @return {Boolean}
*/
getRestoreOriginalFrame:function () {
@@ -297,7 +368,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * return duration in seconds of the whole animation. It is the result of totalDelayUnits * delayPerUnit
+ * Returns duration in seconds of the whole animation. It is the result of totalDelayUnits * delayPerUnit
* @return {Number}
*/
getDuration:function () {
@@ -305,7 +376,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * return Delay in seconds of the "delay unit"
+ * Returns delay in seconds of the "delay unit"
* @return {Number}
*/
getDelayPerUnit:function () {
@@ -313,7 +384,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * set Delay in seconds of the "delay unit"
+ * Sets delay in seconds of the "delay unit"
* @param {Number} delayPerUnit
*/
setDelayPerUnit:function (delayPerUnit) {
@@ -321,7 +392,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * return total Delay units of the cc.Animation.
+ * Returns total delay units of the cc.Animation.
* @return {Number}
*/
getTotalDelayUnits:function () {
@@ -329,84 +400,78 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{
},
/**
- * Initializes a cc.Animation with frames and a delay between frames
+ * Initializes a cc.Animation with frames and a delay between frames, do not call this method yourself, please pass parameters to constructor to initialize.
* @param {Array} frames
* @param {Number} delay
+ * @param {Number} [loops=1]
*/
- initWithSpriteFrames:function (frames, delay) {
- cc.ArrayVerifyType(frames, cc.SpriteFrame);
- this._loops = 1;
- delay = delay || 0;
- this._delayPerUnit = delay;
-
- var tempFrames = [];
- this.setFrames(tempFrames);
+ initWithSpriteFrames:function (frames, delay, loops) {
+ cc.arrayVerifyType(frames, cc.SpriteFrame);
+ this._loops = loops === undefined ? 1 : loops;
+ this._delayPerUnit = delay || 0;
+ this._totalDelayUnits = 0;
+
+ var locFrames = this._frames;
+ locFrames.length = 0;
if (frames) {
for (var i = 0; i < frames.length; i++) {
var frame = frames[i];
var animFrame = new cc.AnimationFrame();
animFrame.initWithSpriteFrame(frame, 1, null);
- this._frames.push(animFrame);
- this._totalDelayUnits++;
+ locFrames.push(animFrame);
}
+ this._totalDelayUnits += frames.length;
}
return true;
},
/**
- * Currently JavaScript Bindigns (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
+ * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
* and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
- * This is a hack, and should be removed once JSB fixes the retain/release bug
+ * This is a hack, and should be removed once JSB fixes the retain/release bug
+ * You will need to retain an object if you created an engine object and haven't added it into the scene graph during the same frame.
+ * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,
+ * when you want to use it later, a "Invalid Native Object" error will be raised.
+ * The retain function can increase a reference count for the native object to avoid it being released,
+ * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.
+ * retain and release function call should be paired in developer's game code.
+ * @function
+ * @see cc.Animation#release
*/
retain:function () {
},
+ /**
+ * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
+ * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
+ * This is a hack, and should be removed once JSB fixes the retain/release bug
+ * You will need to retain an object if you created an engine object and haven't added it into the scene graph during the same frame.
+ * Otherwise, JSB's native autorelease pool will consider this object a useless one and release it directly,
+ * when you want to use it later, a "Invalid Native Object" error will be raised.
+ * The retain function can increase a reference count for the native object to avoid it being released,
+ * you need to manually invoke release function when you think this object is no longer needed, otherwise, there will be memory learks.
+ * retain and release function call should be paired in developer's game code.
+ * @function
+ * @see cc.Animation#retain
+ */
release:function () {
}
});
/**
* Creates an animation.
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.Animation
* @param {Array} frames
* @param {Number} delay
- * @param {Number} loops
+ * @param {Number} [loops=1]
* @return {cc.Animation}
- * @example
- * //Creates an animation
- * var animation1 = cc.Animation.create();
- *
- * //Create an animation with sprite frames
- * var animFrames = [];
- * var frame = cache.getSpriteFrame("grossini_dance_01.png");
- * animFrames.push(frame);
- * var animation2 = cc.Animation.create(animFrames);
- *
- * //Create an animation with sprite frames and delay
- * var animation3 = cc.Animation.create(animFrames, 0.2);
*/
cc.Animation.create = function (frames, delay, loops) {
- var len = arguments.length;
- var animation = new cc.Animation();
- if (len == 0) {
- animation.initWithSpriteFrames(null, 0);
- } else if (len == 2) {
- /** with frames and a delay between frames */
- delay = delay || 0;
- animation.initWithSpriteFrames(frames, delay);
- } else if (len == 3) {
- animation.initWithAnimationFrames(frames, delay, loops);
- }
- return animation;
+ return new cc.Animation(frames, delay, loops);
};
/**
- * Creates an animation with an array of cc.AnimationFrame, the delay per units in seconds and and how many times it should be executed.
- * @param {Array} arrayOfAnimationFrameNames
- * @param {Number} delayPerUnit
- * @param {Number} loops
- * @return {cc.Animation}
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.Animation
+ * @type {Function}
*/
-cc.Animation.createWithAnimationFrames = function (arrayOfAnimationFrameNames, delayPerUnit, loops) {
- var animation = new cc.Animation();
- animation.initWithAnimationFrames(arrayOfAnimationFrameNames, delayPerUnit, loops);
- return animation;
-};
-
+cc.Animation.createWithAnimationFrames = cc.Animation.create;
\ No newline at end of file
diff --git a/cocos2d/sprite_nodes/CCAnimationCache.js b/cocos2d/core/sprites/CCAnimationCache.js
similarity index 57%
rename from cocos2d/sprite_nodes/CCAnimationCache.js
rename to cocos2d/core/sprites/CCAnimationCache.js
index f6bcf49d30..d156393e26 100644
--- a/cocos2d/sprite_nodes/CCAnimationCache.js
+++ b/cocos2d/core/sprites/CCAnimationCache.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -26,16 +26,18 @@
/**
*
- * Singleton that manages the Animations.
+ * cc.animationCache is a singleton object that manages the Animations.
* It saves in a cache the animations. You should use this class if you want to save your animations in a cache.
+ *
+ * example
+ * cc.animationCache.addAnimation(animation,"animation1");
*
* @class
- * @extends cc.Class
- *
- * @example
- * cc.AnimationCache.getInstance().addAnimation(animation,"animation1");
+ * @name cc.animationCache
*/
-cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
+cc.animationCache = /** @lends cc.animationCache# */{
+ _animations: {},
+
/**
* Adds a cc.Animation with a name.
* @param {cc.Animation} animation
@@ -46,14 +48,14 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
},
/**
- * Deletes a cc.Animation from the cache.
- * @param {String} name
+ * Deletes a cc.Animation from the cache.
+ * @param {String} name
*/
removeAnimation:function (name) {
if (!name) {
return;
}
- if (this._animations.hasOwnProperty(name)) {
+ if (this._animations[name]) {
delete this._animations[name];
}
},
@@ -68,22 +70,15 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
* @return {cc.Animation}
*/
getAnimation:function (name) {
- if (this._animations.hasOwnProperty(name))
+ if (this._animations[name])
return this._animations[name];
return null;
},
- /**
- *
- * Adds an animation from an NSDictionary
- * Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
- *
- * @param {object} dictionary
- */
- addAnimationsWithDictionary:function (dictionary) {
+ _addAnimationsWithDictionary:function (dictionary,plist) {
var animations = dictionary["animations"];
if (!animations) {
- cc.log("cocos2d: cc.AnimationCache: No animations were found in provided dictionary.");
+ cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary);
return;
}
@@ -92,8 +87,10 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
if (properties) {
version = (properties["format"] != null) ? parseInt(properties["format"]) : version;
var spritesheets = properties["spritesheets"];
+ var spriteFrameCache = cc.spriteFrameCache;
+ var path = cc.path;
for (var i = 0; i < spritesheets.length; i++) {
- cc.SpriteFrameCache.getInstance().addSpriteFrames(spritesheets[i]);
+ spriteFrameCache.addSpriteFrames(path.changeBasename(plist, spritesheets[i]));
}
}
@@ -105,32 +102,34 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
this._parseVersion2(animations);
break;
default :
- cc.Assert(false, "Invalid animation format");
+ cc.log(cc._LogInfos.animationCache__addAnimationsWithDictionary_2);
break;
}
},
/**
*
- * Adds an animation from a plist file.
+ * Adds an animations from a plist file.
* Make sure that the frames were previously loaded in the cc.SpriteFrameCache.
*
* @param {String} plist
*/
addAnimations:function (plist) {
- cc.Assert(plist, "Invalid texture file name")
- var fileUtils = cc.FileUtils.getInstance();
- var path = fileUtils.fullPathForFilename(plist);
- var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(path);
+ cc.assert(plist, cc._LogInfos.animationCache_addAnimations_2);
- cc.Assert(dict, "cc.AnimationCache: File could not be found");
+ var dict = cc.loader.getRes(plist);
- this.addAnimationsWithDictionary(dict);
+ if(!dict){
+ cc.log(cc._LogInfos.animationCache_addAnimations);
+ return;
+ }
+
+ this._addAnimationsWithDictionary(dict,plist);
},
_parseVersion1:function (animations) {
- var frameCache = cc.SpriteFrameCache.getInstance();
+ var frameCache = cc.spriteFrameCache;
for (var key in animations) {
var animationDict = animations[key];
@@ -138,7 +137,7 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
var delay = parseFloat(animationDict["delay"]) || 0;
var animation = null;
if (!frameNames) {
- cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' found in dictionary without any frames - cannot add to animation cache.");
+ cc.log(cc._LogInfos.animationCache__parseVersion1, key);
continue;
}
@@ -146,8 +145,7 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
for (var i = 0; i < frameNames.length; i++) {
var spriteFrame = frameCache.getSpriteFrame(frameNames[i]);
if (!spriteFrame) {
- cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' refers to frame '" + frameNames[i]
- + "' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation.");
+ cc.log(cc._LogInfos.animationCache__parseVersion1_2, key, frameNames[i]);
continue;
}
var animFrame = new cc.AnimationFrame();
@@ -156,31 +154,30 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
}
if (frames.length === 0) {
- cc.log("cocos2d: cc.AnimationCache: None of the frames for animation '" + key
- + "' were found in the cc.SpriteFrameCache. Animation is not being added to the Animation Cache.");
+ cc.log(cc._LogInfos.animationCache__parseVersion1_3, key);
continue;
- } else if (frames.length != frameNames.length) {
- cc.log("cocos2d: cc.AnimationCache: An animation in your dictionary refers to a frame which is not in the cc.SpriteFrameCache." +
- " Some or all of the frames for the animation '" + key + "' may be missing.");
+ } else if (frames.length !== frameNames.length) {
+ cc.log(cc._LogInfos.animationCache__parseVersion1_4, key);
}
- animation = cc.Animation.createWithAnimationFrames(frames, delay, 1);
- cc.AnimationCache.getInstance().addAnimation(animation, key);
+ animation = new cc.Animation(frames, delay, 1);
+ cc.animationCache.addAnimation(animation, key);
}
},
_parseVersion2:function (animations) {
- var frameCache = cc.SpriteFrameCache.getInstance();
+ var frameCache = cc.spriteFrameCache;
for (var key in animations) {
var animationDict = animations[key];
+ var isLoop = animationDict["loop"];
var loopsTemp = parseInt(animationDict["loops"]);
- var loops = (isNaN(loopsTemp)) ? 1 : loopsTemp;
+ var loops = isLoop ? cc.REPEAT_FOREVER : ((isNaN(loopsTemp)) ? 1 : loopsTemp);
var restoreOriginalFrame = (animationDict["restoreOriginalFrame"] && animationDict["restoreOriginalFrame"] == true) ? true : false;
var frameArray = animationDict["frames"];
if (!frameArray) {
- cc.log("cocos2d: CCAnimationCache: Animation '" + key + "' found in dictionary without any frames - cannot add to animation cache.");
+ cc.log(cc._LogInfos.animationCache__parseVersion2, key);
continue;
}
@@ -191,8 +188,7 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
var spriteFrameName = entry["spriteframe"];
var spriteFrame = frameCache.getSpriteFrame(spriteFrameName);
if (!spriteFrame) {
- cc.log("cocos2d: cc.AnimationCache: Animation '" + key + "' refers to frame '" + spriteFrameName
- + "' which is not currently in the cc.SpriteFrameCache. This frame will not be added to the animation.");
+ cc.log(cc._LogInfos.animationCache__parseVersion2_2, key, spriteFrameName);
continue;
}
@@ -207,42 +203,11 @@ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{
var animation = new cc.Animation();
animation.initWithAnimationFrames(arr, delayPerUnit, loops);
animation.setRestoreOriginalFrame(restoreOriginalFrame);
- cc.AnimationCache.getInstance().addAnimation(animation, key);
+ cc.animationCache.addAnimation(animation, key);
}
},
- /**
- * initialize cc.AnimationCache
- * @return {Boolean}
- */
- init:function () {
- this._animations = {};
- return true;
- },
-
- _animations:null
-});
-
-/**
- * Purges the cache. It releases all the cc.Animation objects and the shared instance.
- */
-cc.AnimationCache.purgeSharedAnimationCache = function () {
- if (cc.s_sharedAnimationCache) {
- cc.s_sharedAnimationCache._animations = null;
- cc.s_sharedAnimationCache = null;
- }
+ _clear: function () {
+ this._animations = {};
+ }
};
-
-/**
- * Retruns ths shared instance of the Animation cache
- * @return {cc.AnimationCache}
- */
-cc.AnimationCache.getInstance = function () {
- if (cc.s_sharedAnimationCache === null) {
- cc.s_sharedAnimationCache = new cc.AnimationCache();
- cc.s_sharedAnimationCache.init();
- }
- return cc.s_sharedAnimationCache;
-};
-
-cc.s_sharedAnimationCache = null;
diff --git a/cocos2d/core/sprites/CCBakeSprite.js b/cocos2d/core/sprites/CCBakeSprite.js
new file mode 100644
index 0000000000..33e4ce2c0b
--- /dev/null
+++ b/cocos2d/core/sprites/CCBakeSprite.js
@@ -0,0 +1,78 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of _t 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.
+ ****************************************************************************/
+
+/**
+ * cc.BakeSprite is a type of sprite that will be cached.
+ * @class
+ * @extend cc.Sprite
+ */
+cc.BakeSprite = cc.Sprite.extend(/** @lends cc.BakeSprite# */{
+ _cacheCanvas: null,
+ _cacheContext: null,
+
+ ctor: function(){
+ cc.Sprite.prototype.ctor.call(this);
+ var canvasElement = document.createElement("canvas");
+ canvasElement.width = canvasElement.height = 10;
+ this._cacheCanvas = canvasElement;
+ this._cacheContext = new cc.CanvasContextWrapper(canvasElement.getContext("2d"));
+
+ var texture = new cc.Texture2D();
+ texture.initWithElement(canvasElement);
+ texture.handleLoadedTexture();
+ this.setTexture(texture);
+ },
+
+ getCacheContext: function(){
+ return this._cacheContext;
+ },
+
+ getCacheCanvas: function(){
+ return this._cacheCanvas;
+ },
+
+ /**
+ * reset the cache canvas size
+ * @param {cc.Size|Number} sizeOrWidth size or width
+ * @param {Number} [height]
+ */
+ resetCanvasSize: function(sizeOrWidth, height){
+ var locCanvas = this._cacheCanvas,
+ locContext = this._cacheContext,
+ strokeStyle = locContext._context.strokeStyle,
+ fillStyle = locContext._context.fillStyle;
+ if(height === undefined){
+ height = sizeOrWidth.height;
+ sizeOrWidth = sizeOrWidth.width;
+ }
+ locCanvas.width = sizeOrWidth;
+ locCanvas.height = height; //TODO note baidu browser reset the context after set width or height
+ if(strokeStyle !== locContext._context.strokeStyle)
+ locContext._context.strokeStyle = strokeStyle;
+ if(fillStyle !== locContext._context.fillStyle)
+ locContext._context.fillStyle = fillStyle;
+ this.getTexture().handleLoadedTexture();
+ this.setTextureRect(cc.rect(0,0, sizeOrWidth, height), false, null, false);
+ }
+});
diff --git a/cocos2d/core/sprites/CCSprite.js b/cocos2d/core/sprites/CCSprite.js
new file mode 100644
index 0000000000..d450424083
--- /dev/null
+++ b/cocos2d/core/sprites/CCSprite.js
@@ -0,0 +1,892 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) )
+ *
+ * cc.Sprite can be created with an image, or with a sub-rectangle of an image.
+ *
+ * If the parent or any of its ancestors is a cc.SpriteBatchNode then the following features/limitations are valid
+ * - Features when the parent is a cc.BatchNode:
+ * - MUCH faster rendering, specially if the cc.SpriteBatchNode has many children. All the children will be drawn in a single batch.
+ *
+ * - Limitations
+ * - Camera is not supported yet (eg: CCOrbitCamera action doesn't work)
+ * - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl)
+ * - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property.
+ * - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property.
+ * - Parallax scroller is not supported, but can be simulated with a "proxy" sprite.
+ *
+ * If the parent is an standard cc.Node, then cc.Sprite behaves like any other cc.Node:
+ * - It supports blending functions
+ * - It supports aliasing / antialiasing
+ * - But the rendering will be slower: 1 draw per children.
+ *
+ * The default anchorPoint in cc.Sprite is (0.5, 0.5).
+ * @class
+ * @extends cc.Node
+ *
+ * @param {String|cc.SpriteFrame|HTMLImageElement|cc.Texture2D} fileName The string which indicates a path to image file, e.g., "scene1/monster.png".
+ * @param {cc.Rect} [rect] Only the contents inside rect of pszFileName's texture will be applied for this sprite.
+ * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated.
+ * @example
+ *
+ * 1.Create a sprite with image path and rect
+ * var sprite1 = new cc.Sprite("res/HelloHTML5World.png");
+ * var sprite2 = new cc.Sprite("res/HelloHTML5World.png",cc.rect(0,0,480,320));
+ *
+ * 2.Create a sprite with a sprite frame name. Must add "#" before frame name.
+ * var sprite = new cc.Sprite('#grossini_dance_01.png');
+ *
+ * 3.Create a sprite with a sprite frame
+ * var spriteFrame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png");
+ * var sprite = new cc.Sprite(spriteFrame);
+ *
+ * 4.Create a sprite with an existing texture contained in a CCTexture2D object
+ * After creation, the rect will be the size of the texture, and the offset will be (0,0).
+ * var texture = cc.textureCache.addImage("HelloHTML5World.png");
+ * var sprite1 = new cc.Sprite(texture);
+ * var sprite2 = new cc.Sprite(texture, cc.rect(0,0,480,320));
+ *
+ * @property {Boolean} dirty - Indicates whether the sprite needs to be updated.
+ * @property {Boolean} flippedX - Indicates whether or not the sprite is flipped on x axis.
+ * @property {Boolean} flippedY - Indicates whether or not the sprite is flipped on y axis.
+ * @property {Number} offsetX - <@readonly> The offset position on x axis of the sprite in texture. Calculated automatically by editors like Zwoptex.
+ * @property {Number} offsetY - <@readonly> The offset position on x axis of the sprite in texture. Calculated automatically by editors like Zwoptex.
+ * @property {Number} atlasIndex - The index used on the TextureAtlas.
+ * @property {cc.Texture2D} texture - Texture used to render the sprite.
+ * @property {Boolean} textureRectRotated - <@readonly> Indicate whether the texture rectangle is rotated.
+ * @property {cc.TextureAtlas} textureAtlas - The weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode.
+ * @property {cc.SpriteBatchNode} batchNode - The batch node object if this sprite is rendered by cc.SpriteBatchNode.
+ * @property {cc.V3F_C4B_T2F_Quad} quad - <@readonly> The quad (tex coords, vertex coords and color) information.
+ */
+cc.Sprite = cc.Node.extend(/** @lends cc.Sprite# */{
+ dirty: false,
+ atlasIndex: 0,
+ textureAtlas: null,
+
+ _batchNode: null,
+ _recursiveDirty: null, //Whether all of the sprite's children needs to be updated
+ _hasChildren: null, //Whether the sprite contains children
+ _shouldBeHidden: false, //should not be drawn because one of the ancestors is not visible
+ _transformToBatch: null,
+
+ //
+ // Data used when the sprite is self-rendered
+ //
+ _blendFunc: null, //It's required for CCTextureProtocol inheritance
+ _texture: null, //cc.Texture2D object that is used to render the sprite
+
+ //
+ // Shared data
+ //
+ // texture
+ _rect: null, //Rectangle of cc.Texture2D
+ _rectRotated: false, //Whether the texture is rotated
+
+ // Offset Position (used by Zwoptex)
+ _offsetPosition: null, // absolute
+ _unflippedOffsetPositionFromCenter: null,
+
+ _opacityModifyRGB: false,
+
+ // image is flipped
+ _flippedX: false, //Whether the sprite is flipped horizontally or not.
+ _flippedY: false, //Whether the sprite is flipped vertically or not.
+
+ _textureLoaded: false,
+ _className: "Sprite",
+
+ ctor: function (fileName, rect, rotated) {
+ var self = this;
+ cc.Node.prototype.ctor.call(self);
+ // default transform anchor: center
+ this.setAnchorPoint(0.5, 0.5);
+
+ self._loader = new cc.Sprite.LoadManager();
+ self._shouldBeHidden = false;
+ self._offsetPosition = cc.p(0, 0);
+ self._unflippedOffsetPositionFromCenter = cc.p(0, 0);
+ self._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
+ self._rect = cc.rect(0, 0, 0, 0);
+
+ self._softInit(fileName, rect, rotated);
+ },
+
+ /**
+ * Returns whether the texture have been loaded
+ * @returns {boolean}
+ */
+ textureLoaded: function () {
+ return this._textureLoaded;
+ },
+
+ /**
+ * Add a event listener for texture loaded event.
+ * @param {Function} callback
+ * @param {Object} target
+ * @deprecated since 3.1, please use addEventListener instead
+ */
+ addLoadedEventListener: function (callback, target) {
+ this.addEventListener("load", callback, target);
+ },
+
+ /**
+ * Returns whether or not the Sprite needs to be updated in the Atlas
+ * @return {Boolean} True if the sprite needs to be updated in the Atlas, false otherwise.
+ */
+ isDirty: function () {
+ return this.dirty;
+ },
+
+ /**
+ * Makes the sprite to be updated in the Atlas.
+ * @param {Boolean} bDirty
+ */
+ setDirty: function (bDirty) {
+ this.dirty = bDirty;
+ },
+
+ /**
+ * Returns whether or not the texture rectangle is rotated.
+ * @return {Boolean}
+ */
+ isTextureRectRotated: function () {
+ return this._rectRotated;
+ },
+
+ /**
+ * Returns the index used on the TextureAtlas.
+ * @return {Number}
+ */
+ getAtlasIndex: function () {
+ return this.atlasIndex;
+ },
+
+ /**
+ * Sets the index used on the TextureAtlas.
+ * @warning Don't modify this value unless you know what you are doing
+ * @param {Number} atlasIndex
+ */
+ setAtlasIndex: function (atlasIndex) {
+ this.atlasIndex = atlasIndex;
+ },
+
+ /**
+ * Returns the rect of the cc.Sprite in points
+ * @return {cc.Rect}
+ */
+ getTextureRect: function () {
+ return cc.rect(this._rect);
+ },
+
+ /**
+ * Returns the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode
+ * @return {cc.TextureAtlas}
+ */
+ getTextureAtlas: function () {
+ return this.textureAtlas;
+ },
+
+ /**
+ * Sets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode
+ * @param {cc.TextureAtlas} textureAtlas
+ */
+ setTextureAtlas: function (textureAtlas) {
+ this.textureAtlas = textureAtlas;
+ },
+
+ /**
+ * Returns the offset position of the sprite. Calculated automatically by editors like Zwoptex.
+ * @return {cc.Point}
+ */
+ getOffsetPosition: function () {
+ return cc.p(this._offsetPosition);
+ },
+
+ _getOffsetX: function () {
+ return this._offsetPosition.x;
+ },
+ _getOffsetY: function () {
+ return this._offsetPosition.y;
+ },
+
+ /**
+ * Returns the blend function
+ * @return {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ return this._blendFunc;
+ },
+
+ /**
+ * Initializes a sprite with a SpriteFrame. The texture and rect in SpriteFrame will be applied on this sprite.
+ * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself,
+ * @param {cc.SpriteFrame} spriteFrame A CCSpriteFrame object. It should includes a valid texture and a rect
+ * @return {Boolean} true if the sprite is initialized properly, false otherwise.
+ */
+ initWithSpriteFrame: function (spriteFrame) {
+ cc.assert(spriteFrame, cc._LogInfos.Sprite_initWithSpriteFrame);
+ return this.setSpriteFrame(spriteFrame);
+ },
+
+ /**
+ * Initializes a sprite with a sprite frame name.
+ * A cc.SpriteFrame will be fetched from the cc.SpriteFrameCache by name.
+ * If the cc.SpriteFrame doesn't exist it will raise an exception.
+ * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
+ * @param {String} spriteFrameName A key string that can fected a valid cc.SpriteFrame from cc.SpriteFrameCache
+ * @return {Boolean} true if the sprite is initialized properly, false otherwise.
+ * @example
+ * var sprite = new cc.Sprite();
+ * sprite.initWithSpriteFrameName("grossini_dance_01.png");
+ */
+ initWithSpriteFrameName: function (spriteFrameName) {
+ cc.assert(spriteFrameName, cc._LogInfos.Sprite_initWithSpriteFrameName);
+ var frame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
+ cc.assert(frame, spriteFrameName + cc._LogInfos.Sprite_initWithSpriteFrameName1);
+ return this.initWithSpriteFrame(frame);
+ },
+
+ /**
+ * Tell the sprite to use batch node render.
+ * @param {cc.SpriteBatchNode} batchNode
+ */
+ useBatchNode: function (batchNode) {
+ },
+
+ /**
+ *
+ * set the vertex rect.
+ * It will be called internally by setTextureRect.
+ * Useful if you want to create 2x images from SD images in Retina Display.
+ * Do not call it manually. Use setTextureRect instead.
+ * (override this method to generate "double scale" sprites)
+ *
+ * @param {cc.Rect} rect
+ */
+ setVertexRect: function (rect) {
+ var locRect = this._rect;
+ locRect.x = rect.x;
+ locRect.y = rect.y;
+ locRect.width = rect.width;
+ locRect.height = rect.height;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ //
+ // cc.Node property overloads
+ //
+
+ /**
+ * Sets whether the sprite should be flipped horizontally or not.
+ * @param {Boolean} flippedX true if the sprite should be flipped horizontally, false otherwise.
+ */
+ setFlippedX: function (flippedX) {
+ if (this._flippedX !== flippedX) {
+ this._flippedX = flippedX;
+ this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
+ this.setNodeDirty(true);
+ }
+ },
+
+ /**
+ * Sets whether the sprite should be flipped vertically or not.
+ * @param {Boolean} flippedY true if the sprite should be flipped vertically, false otherwise.
+ */
+ setFlippedY: function (flippedY) {
+ if (this._flippedY !== flippedY) {
+ this._flippedY = flippedY;
+ this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
+ this.setNodeDirty(true);
+ }
+ },
+
+ /**
+ *
+ * Returns the flag which indicates whether the sprite is flipped horizontally or not.
+ *
+ * It only flips the texture of the sprite, and not the texture of the sprite's children.
+ * Also, flipping the texture doesn't alter the anchorPoint.
+ * If you want to flip the anchorPoint too, and/or to flip the children too use:
+ * sprite.setScaleX(sprite.getScaleX() * -1);
+ * @return {Boolean} true if the sprite is flipped horizontally, false otherwise.
+ */
+ isFlippedX: function () {
+ return this._flippedX;
+ },
+
+ /**
+ *
+ * Return the flag which indicates whether the sprite is flipped vertically or not.
+ *
+ * It only flips the texture of the sprite, and not the texture of the sprite's children.
+ * Also, flipping the texture doesn't alter the anchorPoint.
+ * If you want to flip the anchorPoint too, and/or to flip the children too use:
+ * sprite.setScaleY(sprite.getScaleY() * -1);
+ * @return {Boolean} true if the sprite is flipped vertically, false otherwise.
+ */
+ isFlippedY: function () {
+ return this._flippedY;
+ },
+
+ //
+ // RGBA protocol
+ //
+ /**
+ * Sets whether opacity modify color or not.
+ * @function
+ * @param {Boolean} modify
+ */
+ setOpacityModifyRGB: function (modify) {
+ if (this._opacityModifyRGB !== modify) {
+ this._opacityModifyRGB = modify;
+ this._renderCmd._setColorDirty();
+ }
+ },
+
+ /**
+ * Returns whether opacity modify color or not.
+ * @return {Boolean}
+ */
+ isOpacityModifyRGB: function () {
+ return this._opacityModifyRGB;
+ },
+
+ // Animation
+
+ /**
+ * Changes the display frame with animation name and index.
+ * The animation name will be get from the CCAnimationCache
+ * @param {String} animationName
+ * @param {Number} frameIndex
+ */
+ setDisplayFrameWithAnimationName: function (animationName, frameIndex) {
+ cc.assert(animationName, cc._LogInfos.Sprite_setDisplayFrameWithAnimationName_3);
+
+ var cache = cc.animationCache.getAnimation(animationName);
+ if (!cache) {
+ cc.log(cc._LogInfos.Sprite_setDisplayFrameWithAnimationName);
+ return;
+ }
+ var animFrame = cache.getFrames()[frameIndex];
+ if (!animFrame) {
+ cc.log(cc._LogInfos.Sprite_setDisplayFrameWithAnimationName_2);
+ return;
+ }
+ this.setSpriteFrame(animFrame.getSpriteFrame());
+ },
+
+ /**
+ * Returns the batch node object if this sprite is rendered by cc.SpriteBatchNode
+ * @returns {cc.SpriteBatchNode|null} The cc.SpriteBatchNode object if this sprite is rendered by cc.SpriteBatchNode, null if the sprite isn't used batch node.
+ */
+ getBatchNode: function () {
+ return this._batchNode;
+ },
+
+ // CCTextureProtocol
+ /**
+ * Returns the texture of the sprite node
+ * @returns {cc.Texture2D}
+ */
+ getTexture: function () {
+ return this._texture;
+ },
+
+ _softInit: function (fileName, rect, rotated) {
+ if (fileName === undefined)
+ cc.Sprite.prototype.init.call(this);
+ else if (typeof fileName === 'string') {
+ if (fileName[0] === "#") {
+ // Init with a sprite frame name
+ var frameName = fileName.substr(1, fileName.length - 1);
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(frameName);
+ if (spriteFrame)
+ this.initWithSpriteFrame(spriteFrame);
+ else
+ cc.log("%s does not exist", fileName);
+ } else {
+ // Init with filename and rect
+ cc.Sprite.prototype.init.call(this, fileName, rect);
+ }
+ } else if (typeof fileName === "object") {
+ if (fileName instanceof cc.Texture2D) {
+ // Init with texture and rect
+ this.initWithTexture(fileName, rect, rotated);
+ } else if (fileName instanceof cc.SpriteFrame) {
+ // Init with a sprite frame
+ this.initWithSpriteFrame(fileName);
+ } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) {
+ // Init with a canvas or image element
+ var texture2d = new cc.Texture2D();
+ texture2d.initWithElement(fileName);
+ texture2d.handleLoadedTexture();
+ this.initWithTexture(texture2d);
+ }
+ }
+ },
+
+ /**
+ * Returns the quad (tex coords, vertex coords and color) information.
+ * @return {cc.V3F_C4B_T2F_Quad|null} Returns a cc.V3F_C4B_T2F_Quad object when render mode is WebGL, returns null when render mode is Canvas.
+ */
+ getQuad: function () {
+ return null;
+ },
+
+ /**
+ * conforms to cc.TextureProtocol protocol
+ * @function
+ * @param {Number|cc.BlendFunc} src
+ * @param {Number} dst
+ */
+ setBlendFunc: function (src, dst) {
+ var locBlendFunc = this._blendFunc;
+ if (dst === undefined) {
+ locBlendFunc.src = src.src;
+ locBlendFunc.dst = src.dst;
+ } else {
+ locBlendFunc.src = src;
+ locBlendFunc.dst = dst;
+ }
+ this._renderCmd.updateBlendFunc(locBlendFunc);
+ },
+
+ /**
+ * Initializes an empty sprite with nothing init.
+ * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
+ * @function
+ * @return {Boolean}
+ */
+ init: function () {
+ var _t = this;
+ if (arguments.length > 0)
+ return _t.initWithFile(arguments[0], arguments[1]);
+
+ cc.Node.prototype.init.call(_t);
+ _t.dirty = _t._recursiveDirty = false;
+
+ _t._blendFunc.src = cc.BLEND_SRC;
+ _t._blendFunc.dst = cc.BLEND_DST;
+
+ _t.texture = null;
+ _t._flippedX = _t._flippedY = false;
+
+ // default transform anchor: center
+ _t.anchorX = 0.5;
+ _t.anchorY = 0.5;
+
+ // zwoptex default values
+ _t._offsetPosition.x = 0;
+ _t._offsetPosition.y = 0;
+ _t._hasChildren = false;
+
+ // updated in "useSelfRender"
+ // Atlas: TexCoords
+ _t.setTextureRect(cc.rect(0, 0, 0, 0), false, cc.size(0, 0));
+ return true;
+ },
+
+ /**
+ *
+ * Initializes a sprite with an image filename.
+ *
+ * This method will find pszFilename from local file system, load its content to CCTexture2D,
+ * then use CCTexture2D to create a sprite.
+ * After initialization, the rect used will be the size of the image. The offset will be (0,0).
+ * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
+ *
+ * @param {String} filename The path to an image file in local file system
+ * @param {cc.Rect} rect The rectangle assigned the content area from texture.
+ * @return {Boolean} true if the sprite is initialized properly, false otherwise.
+ */
+ initWithFile: function (filename, rect) {
+ cc.assert(filename, cc._LogInfos.Sprite_initWithFile);
+
+ var tex = cc.textureCache.getTextureForKey(filename);
+ if (!tex) {
+ tex = cc.textureCache.addImage(filename);
+ }
+
+ if (!tex.isLoaded()) {
+ this._loader.clear();
+ this._loader.once(tex, function () {
+ this.initWithFile(filename, rect);
+ this.dispatchEvent("load");
+ }, this);
+ return false;
+ }
+
+ if (!rect) {
+ var size = tex.getContentSize();
+ rect = cc.rect(0, 0, size.width, size.height);
+ }
+ return this.initWithTexture(tex, rect);
+ },
+
+ /**
+ * Initializes a sprite with a texture and a rect in points, optionally rotated.
+ * After initialization, the rect used will be the size of the texture, and the offset will be (0,0).
+ * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
+ * @function
+ * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites.
+ * @param {cc.Rect} [rect] Only the contents inside rect of this texture will be applied for this sprite.
+ * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated.
+ * @param {Boolean} [counterclockwise=true] Whether or not the texture rectangle rotation is counterclockwise (texture package is counterclockwise, spine is clockwise).
+ * @return {Boolean} true if the sprite is initialized properly, false otherwise.
+ */
+ initWithTexture: function (texture, rect, rotated, counterclockwise) {
+ var _t = this;
+ cc.assert(arguments.length !== 0, cc._LogInfos.CCSpriteBatchNode_initWithTexture);
+ this._loader.clear();
+
+ _t._textureLoaded = texture.isLoaded();
+ if (!_t._textureLoaded) {
+ this._loader.once(texture, function () {
+ this.initWithTexture(texture, rect, rotated, counterclockwise);
+ this.dispatchEvent("load");
+ }, this);
+ return false;
+ }
+
+ rotated = rotated || false;
+ texture = this._renderCmd._handleTextureForRotatedTexture(texture, rect, rotated, counterclockwise);
+
+ if (!cc.Node.prototype.init.call(_t))
+ return false;
+
+ _t._batchNode = null;
+ _t._recursiveDirty = false;
+ _t.dirty = false;
+ _t._opacityModifyRGB = true;
+
+ _t._blendFunc.src = cc.BLEND_SRC;
+ _t._blendFunc.dst = cc.BLEND_DST;
+
+ _t._flippedX = _t._flippedY = false;
+
+ // zwoptex default values
+ _t._offsetPosition.x = 0;
+ _t._offsetPosition.y = 0;
+ _t._hasChildren = false;
+
+ _t._rectRotated = rotated;
+ if (rect) {
+ _t._rect.x = rect.x;
+ _t._rect.y = rect.y;
+ _t._rect.width = rect.width;
+ _t._rect.height = rect.height;
+ }
+
+ if (!rect)
+ rect = cc.rect(0, 0, texture.width, texture.height);
+
+ this._renderCmd._checkTextureBoundary(texture, rect, rotated);
+
+ _t.setTexture(texture);
+ _t.setTextureRect(rect, rotated);
+
+ // by default use "Self Render".
+ // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
+ _t.setBatchNode(null);
+ return true;
+ },
+
+ /**
+ * Updates the texture rect of the CCSprite in points.
+ * @function
+ * @param {cc.Rect} rect a rect of texture
+ * @param {Boolean} [rotated] Whether or not the texture is rotated
+ * @param {cc.Size} [untrimmedSize] The original pixels size of the texture
+ * @param {Boolean} [needConvert] contentScaleFactor switch
+ */
+ setTextureRect: function (rect, rotated, untrimmedSize, needConvert) {
+ var _t = this;
+ _t._rectRotated = rotated || false;
+ _t.setContentSize(untrimmedSize || rect);
+
+ _t.setVertexRect(rect);
+ _t._renderCmd._setTextureCoords(rect, needConvert);
+
+ var relativeOffsetX = _t._unflippedOffsetPositionFromCenter.x, relativeOffsetY = _t._unflippedOffsetPositionFromCenter.y;
+ if (_t._flippedX)
+ relativeOffsetX = -relativeOffsetX;
+ if (_t._flippedY)
+ relativeOffsetY = -relativeOffsetY;
+ var locRect = _t._rect;
+ _t._offsetPosition.x = relativeOffsetX + (_t._contentSize.width - locRect.width) / 2;
+ _t._offsetPosition.y = relativeOffsetY + (_t._contentSize.height - locRect.height) / 2;
+ },
+
+ // BatchNode methods
+
+ /**
+ * Add child to sprite (override cc.Node)
+ * @function
+ * @param {cc.Sprite} child
+ * @param {Number} localZOrder child's zOrder
+ * @param {number|String} [tag] child's tag
+ * @override
+ */
+ addChild: function (child, localZOrder, tag) {
+ cc.assert(child, cc._LogInfos.CCSpriteBatchNode_addChild_2);
+
+ if (localZOrder == null)
+ localZOrder = child._localZOrder;
+ if (tag == null)
+ tag = child.tag;
+
+ if (this._renderCmd._setBatchNodeForAddChild(child)) {
+ //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check
+ cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
+ this._hasChildren = true;
+ }
+ },
+
+ // Frames
+ /**
+ * Sets a new sprite frame to the sprite.
+ * @function
+ * @param {cc.SpriteFrame|String} newFrame
+ */
+ setSpriteFrame: function (newFrame) {
+ var _t = this;
+ if (typeof newFrame === 'string') {
+ newFrame = cc.spriteFrameCache.getSpriteFrame(newFrame);
+ cc.assert(newFrame, cc._LogInfos.Sprite_setSpriteFrame);
+ }
+ this._loader.clear();
+
+ this.setNodeDirty(true);
+
+ // update rect
+ var pNewTexture = newFrame.getTexture();
+ _t._textureLoaded = newFrame.textureLoaded();
+ this._loader.clear();
+ if (!_t._textureLoaded) {
+ this._loader.once(pNewTexture, function () {
+ this.setSpriteFrame(newFrame);
+ this.dispatchEvent("load");
+ }, this);
+ return false;
+ }
+
+ var frameOffset = newFrame.getOffset();
+ _t._unflippedOffsetPositionFromCenter.x = frameOffset.x;
+ _t._unflippedOffsetPositionFromCenter.y = frameOffset.y;
+
+ if (pNewTexture !== _t._texture) {
+ this._renderCmd._setTexture(pNewTexture);
+ _t.setColor(_t._realColor);
+ }
+ _t.setTextureRect(newFrame.getRect(), newFrame.isRotated(), newFrame.getOriginalSize());
+ },
+
+ /**
+ * Sets a new display frame to the sprite.
+ * @param {cc.SpriteFrame|String} newFrame
+ * @deprecated
+ */
+ setDisplayFrame: function (newFrame) {
+ cc.log(cc._LogInfos.Sprite_setDisplayFrame);
+ this.setSpriteFrame(newFrame);
+ },
+
+ /**
+ * Returns whether or not a cc.SpriteFrame is being displayed
+ * @function
+ * @param {cc.SpriteFrame} frame
+ * @return {Boolean}
+ */
+ isFrameDisplayed: function (frame) {
+ return this._renderCmd.isFrameDisplayed(frame);
+ },
+
+ /**
+ * Returns the current displayed frame.
+ * @deprecated since 3.4, please use getSpriteFrame instead
+ * @return {cc.SpriteFrame}
+ */
+ displayFrame: function () {
+ return this.getSpriteFrame();
+ },
+
+ /**
+ * Returns the current displayed frame.
+ * @return {cc.SpriteFrame}
+ */
+ getSpriteFrame: function () {
+ return new cc.SpriteFrame(this._texture,
+ cc.rectPointsToPixels(this._rect),
+ this._rectRotated,
+ cc.pointPointsToPixels(this._unflippedOffsetPositionFromCenter),
+ cc.sizePointsToPixels(this._contentSize));
+ },
+
+ /**
+ * Sets the batch node to sprite
+ * @function
+ * @param {cc.SpriteBatchNode|null} spriteBatchNode
+ * @example
+ * var batch = new cc.SpriteBatchNode("Images/grossini_dance_atlas.png", 15);
+ * var sprite = new cc.Sprite(batch.texture, cc.rect(0, 0, 57, 57));
+ * batch.addChild(sprite);
+ * layer.addChild(batch);
+ */
+ setBatchNode: function (spriteBatchNode) {
+ },
+
+ // CCTextureProtocol
+ /**
+ * Sets the texture of sprite
+ * @function
+ * @param {cc.Texture2D|String} texture
+ */
+ setTexture: function (texture) {
+ if (!texture)
+ return this._renderCmd._setTexture(null);
+
+ //CCSprite.cpp 327 and 338
+ var isFileName = (typeof texture === 'string');
+
+ if (isFileName)
+ texture = cc.textureCache.addImage(texture);
+
+ this._loader.clear();
+ if (!texture._textureLoaded) {
+ // wait for the load to be set again
+ this._loader.once(texture, function () {
+ this.setTexture(texture);
+ this.dispatchEvent("load");
+ }, this);
+ return false;
+ }
+
+ this._renderCmd._setTexture(texture);
+ if (isFileName)
+ this._changeRectWithTexture(texture);
+ this.setColor(this._realColor);
+ this._textureLoaded = true;
+ },
+
+ _changeRectWithTexture: function (texture) {
+ var contentSize = texture._contentSize;
+ var rect = cc.rect(
+ 0, 0,
+ contentSize.width, contentSize.height
+ );
+ this.setTextureRect(rect);
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.Sprite.CanvasRenderCmd(this);
+ else
+ return new cc.Sprite.WebGLRenderCmd(this);
+ }
+});
+
+/**
+ * Create a sprite with image path or frame name or texture or spriteFrame.
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.Sprite
+ * @param {String|cc.SpriteFrame|HTMLImageElement|cc.Texture2D} fileName The string which indicates a path to image file, e.g., "scene1/monster.png".
+ * @param {cc.Rect} rect Only the contents inside rect of pszFileName's texture will be applied for this sprite.
+ * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated.
+ * @return {cc.Sprite} A valid sprite object
+ */
+cc.Sprite.create = function (fileName, rect, rotated) {
+ return new cc.Sprite(fileName, rect, rotated);
+};
+
+/**
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.Sprite
+ * @function
+ */
+cc.Sprite.createWithTexture = cc.Sprite.create;
+
+/**
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.Sprite
+ * @function
+ */
+cc.Sprite.createWithSpriteFrameName = cc.Sprite.create;
+
+/**
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.Sprite
+ * @function
+ */
+cc.Sprite.createWithSpriteFrame = cc.Sprite.create;
+/**
+ * cc.Sprite invalid index on the cc.SpriteBatchNode
+ * @constant
+ * @type {Number}
+ */
+cc.Sprite.INDEX_NOT_INITIALIZED = -1;
+
+cc.EventHelper.prototype.apply(cc.Sprite.prototype);
+
+cc.assert(cc.isFunction(cc._tmp.PrototypeSprite), cc._LogInfos.MissingFile, "SpritesPropertyDefine.js");
+cc._tmp.PrototypeSprite();
+delete cc._tmp.PrototypeSprite;
+
+(function () {
+ var manager = cc.Sprite.LoadManager = function () {
+ this.list = [];
+ };
+
+ manager.prototype.add = function (source, callback, target) {
+ if (!source || !source.addEventListener) return;
+ source.addEventListener('load', callback, target);
+ this.list.push({
+ source: source,
+ listener: callback,
+ target: target
+ });
+ };
+ manager.prototype.once = function (source, callback, target) {
+ if (!source || !source.addEventListener) return;
+ var tmpCallback = function (event) {
+ source.removeEventListener('load', tmpCallback, target);
+ callback.call(target, event);
+ };
+ source.addEventListener('load', tmpCallback, target);
+ this.list.push({
+ source: source,
+ listener: tmpCallback,
+ target: target
+ });
+ };
+ manager.prototype.clear = function () {
+ while (this.list.length > 0) {
+ var item = this.list.pop();
+ item.source.removeEventListener('load', item.listener, item.target);
+ }
+ };
+})();
diff --git a/cocos2d/core/sprites/CCSpriteBatchNode.js b/cocos2d/core/sprites/CCSpriteBatchNode.js
new file mode 100644
index 0000000000..3abd61fb4c
--- /dev/null
+++ b/cocos2d/core/sprites/CCSpriteBatchNode.js
@@ -0,0 +1,438 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+
+/**
+ *
+ * A cc.SpriteBatchNode can reference one and only one texture (one image file, one texture atlas).
+ * Only the cc.Sprites that are contained in that texture can be added to the cc.SpriteBatchNode.
+ * All cc.Sprites added to a cc.SpriteBatchNode are drawn in one WebGL draw call.
+ * If the cc.Sprites are not added to a cc.SpriteBatchNode then an WebGL draw call will be needed for each one, which is less efficient.
+ *
+ * Limitations:
+ * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is cc.Sprite or any subclass of cc.Sprite.
+ * eg: particles, labels and layer can't be added to a cc.SpriteBatchNode.
+ * - Either all its children are Aliased or Antialiased. It can't be a mix.
+ * This is because "alias" is a property of the texture, and all the sprites share the same texture.
+ *
+ * @class
+ * @extends cc.Node
+ *
+ * @param {String|cc.Texture2D} fileImage
+ * @example
+ *
+ * // 1. create a SpriteBatchNode with image path
+ * var spriteBatchNode = new cc.SpriteBatchNode("res/animations/grossini.png");
+ *
+ * // 2. create a SpriteBatchNode with texture
+ * var texture = cc.textureCache.addImage("res/animations/grossini.png");
+ * var spriteBatchNode = new cc.SpriteBatchNode(texture);
+ *
+ * @property {cc.TextureAtlas} textureAtlas - The texture atlas
+ * @property {Array} descendants - <@readonly> Descendants of sprite batch node
+ */
+cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
+ _blendFunc: null,
+ // all descendants: chlidren, gran children, etc...
+ _texture: null,
+ _className: "SpriteBatchNode",
+
+ ctor: function (fileImage) {
+ cc.Node.prototype.ctor.call(this);
+ this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
+
+ var texture2D;
+ if (cc.isString(fileImage)) {
+ texture2D = cc.textureCache.getTextureForKey(fileImage);
+ if (!texture2D)
+ texture2D = cc.textureCache.addImage(fileImage);
+ } else if (fileImage instanceof cc.Texture2D)
+ texture2D = fileImage;
+
+ texture2D && this.initWithTexture(texture2D);
+ },
+
+ /**
+ *
+ * Same as addChild
+ *
+ * @param {cc.Sprite} child
+ * @param {Number} z zOrder
+ * @param {Number} aTag
+ * @return {cc.SpriteBatchNode}
+ * @deprecated since v3.12
+ */
+ addSpriteWithoutQuad: function (child, z, aTag) {
+ this.addChild(child, z, aTag);
+ return this;
+ },
+
+ // property
+ /**
+ * Return null, no texture atlas is used any more
+ * @return {cc.TextureAtlas}
+ * @deprecated since v3.12
+ */
+ getTextureAtlas: function () {
+ return null;
+ },
+
+ /**
+ * TextureAtlas of cc.SpriteBatchNode setter
+ * @param {cc.TextureAtlas} textureAtlas
+ * @deprecated since v3.12
+ */
+ setTextureAtlas: function (textureAtlas) {
+ },
+
+ /**
+ * Return Descendants of cc.SpriteBatchNode
+ * @return {Array}
+ * @deprecated since v3.12
+ */
+ getDescendants: function () {
+ return this._children;
+ },
+
+ /**
+ *
+ * Initializes a cc.SpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
+ * The capacity will be increased in 33% in runtime if it run out of space.
+ * The file will be loaded using the TextureMgr.
+ * Please pass parameters to constructor to initialize the sprite batch node, do not call this function yourself.
+ *
+ * @param {String} fileImage
+ * @param {Number} capacity
+ * @return {Boolean}
+ */
+ initWithFile: function (fileImage, capacity) {
+ var texture2D = cc.textureCache.getTextureForKey(fileImage);
+ if (!texture2D)
+ texture2D = cc.textureCache.addImage(fileImage);
+ return this.initWithTexture(texture2D, capacity);
+ },
+
+ /**
+ *
+ * initializes a cc.SpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
+ * The capacity will be increased in 33% in runtime if it run out of space.
+ * The file will be loaded using the TextureMgr.
+ * Please pass parameters to constructor to initialize the sprite batch node, do not call this function yourself.
+ *
+ * @param {String} fileImage
+ * @param {Number} capacity
+ * @return {Boolean}
+ */
+ init: function (fileImage, capacity) {
+ var texture2D = cc.textureCache.getTextureForKey(fileImage);
+ if (!texture2D)
+ texture2D = cc.textureCache.addImage(fileImage);
+ return this.initWithTexture(texture2D, capacity);
+ },
+
+ /**
+ * Do nothing
+ * @deprecated since v3.12
+ */
+ increaseAtlasCapacity: function () {
+ },
+
+ /**
+ * Removes a child given a certain index. It will also cleanup the running actions depending on the cleanup parameter.
+ * @warning Removing a child from a cc.SpriteBatchNode is very slow
+ * @param {Number} index
+ * @param {Boolean} doCleanup
+ */
+ removeChildAtIndex: function (index, doCleanup) {
+ this.removeChild(this._children[index], doCleanup);
+ },
+
+ /**
+ * Do nothing
+ * @param {cc.Sprite} pobParent
+ * @param {Number} index
+ * @return {Number}
+ * @deprecated since v3.12
+ */
+ rebuildIndexInOrder: function (pobParent, index) {
+ return index;
+ },
+
+ /**
+ * Returns highest atlas index in child
+ * @param {cc.Sprite} sprite
+ * @return {Number}
+ * @deprecated since v3.12
+ */
+ highestAtlasIndexInChild: function (sprite) {
+ var children = sprite.children;
+ if (!children || children.length === 0)
+ return sprite.zIndex;
+ else
+ return this.highestAtlasIndexInChild(children[children.length - 1]);
+ },
+
+ /**
+ * Returns lowest atlas index in child
+ * @param {cc.Sprite} sprite
+ * @return {Number}
+ * @deprecated since v3.12
+ */
+ lowestAtlasIndexInChild: function (sprite) {
+ var children = sprite.children;
+ if (!children || children.length === 0)
+ return sprite.zIndex;
+ else
+ return this.lowestAtlasIndexInChild(children[children.length - 1]);
+ },
+
+ /**
+ * Returns index for child
+ * @param {cc.Sprite} sprite
+ * @return {Number}
+ * @deprecated since v3.12
+ */
+ atlasIndexForChild: function (sprite) {
+ return sprite.zIndex;
+ },
+
+ /**
+ * Sprites use this to start sortChildren, don't call this manually
+ * @param {Boolean} reorder
+ * @deprecated since v3.12
+ */
+ reorderBatch: function (reorder) {
+ this._reorderChildDirty = reorder;
+ },
+
+ /**
+ * Sets the source and destination blending function for the texture
+ * @param {Number | cc.BlendFunc} src
+ * @param {Number} dst
+ */
+ setBlendFunc: function (src, dst) {
+ if (dst === undefined)
+ this._blendFunc = src;
+ else
+ this._blendFunc = {src: src, dst: dst};
+ },
+
+ /**
+ * Returns the blending function used for the texture
+ * @return {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
+ },
+
+ /**
+ *
+ * Updates a quad at a certain index into the texture atlas. The CCSprite won't be added into the children array.
+ * This method should be called only when you are dealing with very big AtlasSrite and when most of the cc.Sprite won't be updated.
+ * For example: a tile map (cc.TMXMap) or a label with lots of characters (BitmapFontAtlas)
+ *
+ * @function
+ * @param {cc.Sprite} sprite
+ * @param {Number} index
+ */
+ updateQuadFromSprite: function (sprite, index) {
+ cc.assert(sprite, cc._LogInfos.CCSpriteBatchNode_updateQuadFromSprite_2);
+ if (!(sprite instanceof cc.Sprite)) {
+ cc.log(cc._LogInfos.CCSpriteBatchNode_updateQuadFromSprite);
+ return;
+ }
+
+ //
+ // update the quad directly. Don't add the sprite to the scene graph
+ //
+ sprite.dirty = true;
+ // UpdateTransform updates the textureAtlas quad
+ sprite._renderCmd.transform(this._renderCmd, true);
+ },
+
+ /**
+ *
+ * Same as addChild(sprite, index)
+ *
+ * @function
+ * @param {cc.Sprite} sprite
+ * @param {Number} index
+ * @deprecated since v3.12
+ */
+ insertQuadFromSprite: function (sprite, index) {
+ this.addChild(sprite, index);
+ },
+
+ /**
+ * Same as addChild(sprite, index)
+ * @param {cc.Sprite} sprite The child sprite
+ * @param {Number} index The insert index
+ * @deprecated since v3.12
+ */
+ insertChild: function (sprite, index) {
+ this.addChild(sprite, index);
+ },
+
+ /**
+ * Add child at the end
+ * @function
+ * @param {cc.Sprite} sprite
+ */
+ appendChild: function (sprite) {
+ this.sortAllChildren();
+ var lastLocalZOrder = this._children[this._children.length - 1]._localZOrder;
+ this.addChild(sprite.lastLocalZOrder + 1);
+ },
+
+ /**
+ * Same as removeChild
+ * @function
+ * @param {cc.Sprite} sprite
+ * @param {Boolean} [cleanup=true] true if all running actions and callbacks on the child node will be cleanup, false otherwise.
+ * @deprecated since v3.12
+ */
+ removeSpriteFromAtlas: function (sprite, cleanup) {
+ this.removeChild(sprite, cleanup);
+ },
+
+ /**
+ * Set the texture property
+ * @function
+ * @param {cc.Texture2D} tex
+ * @return {Boolean}
+ */
+ initWithTexture: function (tex) {
+ this.setTexture(tex);
+ return true;
+ },
+
+ // CCTextureProtocol
+ /**
+ * Returns texture of the sprite batch node
+ * @function
+ * @return {cc.Texture2D}
+ */
+ getTexture: function () {
+ return this._texture;
+ },
+
+ /**
+ * Sets the texture of the sprite batch node.
+ * @function
+ * @param {cc.Texture2D} texture
+ */
+ setTexture: function (texture) {
+ this._texture = texture;
+
+ if (texture._textureLoaded) {
+ var i, children = this._children, len = children.length;
+ for (i = 0; i < len; ++i) {
+ children[i].setTexture(texture);
+ }
+ }
+ else {
+ texture.addEventListener("load", function () {
+ var i, children = this._children, len = children.length;
+ for (i = 0; i < len; ++i) {
+ children[i].setTexture(texture);
+ }
+ }, this);
+ }
+ },
+
+ setShaderProgram: function (newShaderProgram) {
+ this._renderCmd.setShaderProgram(newShaderProgram);
+ var i, children = this._children, len = children.length;
+ for (i = 0; i < len; ++i) {
+ children[i].setShaderProgram(newShaderProgram);
+ }
+ },
+
+ /**
+ * Add child to the sprite batch node (override addChild of cc.Node)
+ * @function
+ * @override
+ * @param {cc.Sprite} child
+ * @param {Number} [zOrder]
+ * @param {Number} [tag]
+ */
+ addChild: function (child, zOrder, tag) {
+ cc.assert(child !== undefined, cc._LogInfos.CCSpriteBatchNode_addChild_3);
+
+ if (!this._isValidChild(child))
+ return;
+
+ zOrder = (zOrder === undefined) ? child.zIndex : zOrder;
+ tag = (tag === undefined) ? child.tag : tag;
+ cc.Node.prototype.addChild.call(this, child, zOrder, tag);
+
+ // Apply shader
+ if (this._renderCmd._shaderProgram) {
+ child.shaderProgram = this._renderCmd._shaderProgram;
+ }
+ },
+
+ _isValidChild: function (child) {
+ if (!(child instanceof cc.Sprite)) {
+ cc.log(cc._LogInfos.Sprite_addChild_4);
+ return false;
+ }
+ if (child.texture !== this._texture) {
+ cc.log(cc._LogInfos.Sprite_addChild_5);
+ return false;
+ }
+ return true;
+ }
+});
+
+var _p = cc.SpriteBatchNode.prototype;
+
+// Override properties
+cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
+cc.defineGetterSetter(_p, "shaderProgram", _p.getShaderProgram, _p.setShaderProgram);
+
+
+/**
+ *
+ * creates a cc.SpriteBatchNodeCanvas with a file image (.png, .jpg etc) with a default capacity of 29 children.
+ * The capacity will be increased in 33% in runtime if it run out of space.
+ * The file will be loaded using the TextureMgr.
+ *
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.SpriteBatchNode
+ * @param {String|cc.Texture2D} fileImage
+ * @return {cc.SpriteBatchNode}
+ */
+cc.SpriteBatchNode.create = function (fileImage) {
+ return new cc.SpriteBatchNode(fileImage);
+};
+
+/**
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.SpriteBatchNode
+ * @function
+ */
+cc.SpriteBatchNode.createWithTexture = cc.SpriteBatchNode.create;
diff --git a/cocos2d/core/sprites/CCSpriteCanvasRenderCmd.js b/cocos2d/core/sprites/CCSpriteCanvasRenderCmd.js
new file mode 100644
index 0000000000..87da2606e5
--- /dev/null
+++ b/cocos2d/core/sprites/CCSpriteCanvasRenderCmd.js
@@ -0,0 +1,251 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.Sprite.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = true;
+ this._textureCoord = {
+ renderX: 0, //the x of texture coordinate for render, when texture tinted, its value doesn't equal x.
+ renderY: 0, //the y of texture coordinate for render, when texture tinted, its value doesn't equal y.
+ x: 0, //the x of texture coordinate for node.
+ y: 0, //the y of texture coordinate for node.
+ width: 0,
+ height: 0,
+ validRect: false
+ };
+ this._blendFuncStr = "source-over";
+ this._colorized = false;
+ this._canUseDirtyRegion = true;
+ this._textureToRender = null;
+ };
+
+ var proto = cc.Sprite.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.Sprite.CanvasRenderCmd;
+ proto._spriteCmdCtor = cc.Sprite.CanvasRenderCmd;
+
+ proto.setDirtyRecursively = function (value) {
+ };
+
+ proto._setTexture = function (texture) {
+ var node = this._node;
+ if (node._texture !== texture) {
+ node._textureLoaded = texture ? texture._textureLoaded : false;
+ node._texture = texture;
+
+ var texSize = texture._contentSize;
+ var rect = cc.rect(0, 0, texSize.width, texSize.height);
+ node.setTextureRect(rect);
+ this._updateColor();
+ }
+ };
+
+ proto._setColorDirty = function () {
+ this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty | cc.Node._dirtyFlags.opacityDirty);
+ };
+
+ proto.isFrameDisplayed = function (frame) { //TODO there maybe has a bug
+ var node = this._node;
+ if (frame.getTexture() !== node._texture)
+ return false;
+ return cc.rectEqualToRect(frame.getRect(), node._rect);
+ };
+
+ proto.updateBlendFunc = function (blendFunc) {
+ this._blendFuncStr = cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc(blendFunc);
+ };
+
+ proto._setBatchNodeForAddChild = function (child) {
+ return true;
+ };
+
+ proto._handleTextureForRotatedTexture = function (texture, rect, rotated, counterclockwise) {
+ if (rotated && texture.isLoaded()) {
+ var tempElement = texture.getHtmlElementObj();
+ tempElement = cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas(tempElement, rect, counterclockwise);
+ var tempTexture = new cc.Texture2D();
+ tempTexture.initWithElement(tempElement);
+ tempTexture.handleLoadedTexture();
+ texture = tempTexture;
+ rect.x = rect.y = 0;
+ this._node._rect = cc.rect(0, 0, rect.width, rect.height);
+ }
+ return texture;
+ };
+
+ proto._checkTextureBoundary = function (texture, rect, rotated) {
+ if (texture && texture.url) {
+ var _x = rect.x + rect.width, _y = rect.y + rect.height;
+ if (_x > texture.width)
+ cc.error(cc._LogInfos.RectWidth, texture.url);
+ if (_y > texture.height)
+ cc.error(cc._LogInfos.RectHeight, texture.url);
+ }
+ };
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var node = this._node;
+ var locTextureCoord = this._textureCoord, alpha = (this._displayedOpacity / 255);
+ var texture = this._textureToRender || node._texture;
+
+ if ((texture && (locTextureCoord.width === 0 || locTextureCoord.height === 0 || !texture._textureLoaded)) || alpha === 0)
+ return;
+
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+ var locX = node._offsetPosition.x, locHeight = node._rect.height, locWidth = node._rect.width,
+ locY = -node._offsetPosition.y - locHeight, image;
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ wrapper.setCompositeOperation(this._blendFuncStr);
+ wrapper.setGlobalAlpha(alpha);
+
+ if (node._flippedX || node._flippedY)
+ wrapper.save();
+ if (node._flippedX) {
+ locX = -locX - locWidth;
+ context.scale(-1, 1);
+ }
+ if (node._flippedY) {
+ locY = node._offsetPosition.y;
+ context.scale(1, -1);
+ }
+
+ var sx, sy, sw, sh, x, y, w, h;
+ if (this._colorized) {
+ sx = 0;
+ sy = 0;
+ } else {
+ sx = locTextureCoord.renderX;
+ sy = locTextureCoord.renderY;
+ }
+ sw = locTextureCoord.width;
+ sh = locTextureCoord.height;
+
+ x = locX;
+ y = locY;
+ w = locWidth;
+ h = locHeight;
+
+ if (texture && texture._htmlElementObj) {
+ image = texture._htmlElementObj;
+ if (texture._pattern !== "") {
+ wrapper.setFillStyle(context.createPattern(image, texture._pattern));
+ context.fillRect(x, y, w, h);
+ } else {
+ context.drawImage(image,
+ sx, sy, sw, sh,
+ x, y, w, h);
+ }
+ } else {
+ var contentSize = node._contentSize;
+ if (locTextureCoord.validRect) {
+ var curColor = this._displayedColor;
+ wrapper.setFillStyle("rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)");
+ context.fillRect(x, y, contentSize.width * scaleX, contentSize.height * scaleY);
+ }
+ }
+ if (node._flippedX || node._flippedY)
+ wrapper.restore();
+ cc.g_NumberOfDraws++;
+ };
+
+ proto._updateColor = function () {
+ var node = this._node;
+
+ var texture = node._texture, rect = this._textureCoord;
+ var dColor = this._displayedColor;
+
+ if (texture) {
+ if (dColor.r !== 255 || dColor.g !== 255 || dColor.b !== 255) {
+ this._textureToRender = texture._generateColorTexture(dColor.r, dColor.g, dColor.b, rect);
+ this._colorized = true;
+ } else if (texture) {
+ this._textureToRender = texture;
+ this._colorized = false;
+ }
+ }
+ };
+
+ proto._textureLoadedCallback = function (sender) {
+ var node = this;
+ if (node._textureLoaded)
+ return;
+
+ node._textureLoaded = true;
+ var locRect = node._rect, locRenderCmd = this._renderCmd;
+ if (!locRect) {
+ locRect = cc.rect(0, 0, sender.width, sender.height);
+ } else if (cc._rectEqualToZero(locRect)) {
+ locRect.width = sender.width;
+ locRect.height = sender.height;
+ }
+
+ node.texture = sender;
+ node.setTextureRect(locRect, node._rectRotated);
+
+ //set the texture's color after the it loaded
+ var locColor = locRenderCmd._displayedColor;
+ if (locColor.r !== 255 || locColor.g !== 255 || locColor.b !== 255)
+ locRenderCmd._updateColor();
+
+ // by default use "Self Render".
+ // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
+ node.setBatchNode(node._batchNode);
+ node.dispatchEvent("load");
+ };
+
+ proto._setTextureCoords = function (rect, needConvert) {
+ if (needConvert === undefined)
+ needConvert = true;
+ var locTextureRect = this._textureCoord,
+ scaleFactor = needConvert ? cc.contentScaleFactor() : 1;
+ locTextureRect.renderX = locTextureRect.x = 0 | (rect.x * scaleFactor);
+ locTextureRect.renderY = locTextureRect.y = 0 | (rect.y * scaleFactor);
+ locTextureRect.width = 0 | (rect.width * scaleFactor);
+ locTextureRect.height = 0 | (rect.height * scaleFactor);
+ locTextureRect.validRect = !(locTextureRect.width === 0 || locTextureRect.height === 0 || locTextureRect.x < 0 || locTextureRect.y < 0);
+ };
+
+ cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas = function (texture, rect, counterclockwise) {
+ if (!texture)
+ return null;
+
+ if (!rect)
+ return texture;
+
+ counterclockwise = counterclockwise == null ? true : counterclockwise; // texture package is counterclockwise, spine is clockwise
+
+ var nCanvas = document.createElement("canvas");
+ nCanvas.width = rect.width;
+ nCanvas.height = rect.height;
+ var ctx = nCanvas.getContext("2d");
+ ctx.translate(nCanvas.width / 2, nCanvas.height / 2);
+ if (counterclockwise)
+ ctx.rotate(-1.5707963267948966);
+ else
+ ctx.rotate(1.5707963267948966);
+ ctx.drawImage(texture, rect.x, rect.y, rect.height, rect.width, -rect.height / 2, -rect.width / 2, rect.height, rect.width);
+ return nCanvas;
+ };
+})();
diff --git a/cocos2d/core/sprites/CCSpriteFrame.js b/cocos2d/core/sprites/CCSpriteFrame.js
new file mode 100644
index 0000000000..4879225a53
--- /dev/null
+++ b/cocos2d/core/sprites/CCSpriteFrame.js
@@ -0,0 +1,420 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ *
+ * A cc.SpriteFrame has:
+ * - texture: A cc.Texture2D that will be used by the cc.Sprite
+ * - rectangle: A rectangle of the texture
+ *
+ * You can modify the frame of a cc.Sprite by doing:
+ *
+ * @class
+ * @extends cc.Class
+ *
+ * @param {String|cc.Texture2D} filename
+ * @param {cc.Rect} rect If parameters' length equal 2, rect in points, else rect in pixels
+ * @param {Boolean} [rotated] Whether the frame is rotated in the texture
+ * @param {cc.Point} [offset] The offset of the frame in the texture
+ * @param {cc.Size} [originalSize] The size of the frame in the texture
+ *
+ * @example
+ * // 1. Create a cc.SpriteFrame with image path
+ * var frame1 = new cc.SpriteFrame("res/grossini_dance.png",cc.rect(0,0,90,128));
+ * var frame2 = new cc.SpriteFrame("res/grossini_dance.png",cc.rect(0,0,90,128),false,0,cc.size(90,128));
+ *
+ * // 2. Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
+ * var texture = cc.textureCache.addImage("res/grossini_dance.png");
+ * var frame1 = new cc.SpriteFrame(texture, cc.rect(0,0,90,128));
+ * var frame2 = new cc.SpriteFrame(texture, cc.rect(0,0,90,128),false,0,cc.size(90,128));
+ */
+cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{
+ _offset: null,
+ _originalSize: null,
+ _rectInPixels: null,
+ _rotated: false,
+ _rect: null,
+ _offsetInPixels: null,
+ _originalSizeInPixels: null,
+ _texture: null,
+ _textureFilename: "",
+ _textureLoaded: false,
+
+ ctor: function (filename, rect, rotated, offset, originalSize) {
+ this._offset = cc.p(0, 0);
+ this._offsetInPixels = cc.p(0, 0);
+ this._originalSize = cc.size(0, 0);
+ this._rotated = false;
+ this._originalSizeInPixels = cc.size(0, 0);
+ this._textureFilename = "";
+ this._texture = null;
+ this._textureLoaded = false;
+
+ if (filename !== undefined && rect !== undefined) {
+ if (rotated === undefined || offset === undefined || originalSize === undefined)
+ this.initWithTexture(filename, rect);
+ else
+ this.initWithTexture(filename, rect, rotated, offset, originalSize);
+ }
+ },
+
+ /**
+ * Returns whether the texture have been loaded
+ * @returns {boolean}
+ */
+ textureLoaded: function () {
+ return this._textureLoaded;
+ },
+
+ /**
+ * Add a event listener for texture loaded event.
+ * @param {Function} callback
+ * @param {Object} target
+ * @deprecated since 3.1, please use addEventListener instead
+ */
+ addLoadedEventListener: function (callback, target) {
+ this.addEventListener("load", callback, target);
+ },
+
+ /**
+ * Gets the rect of the frame in the texture
+ * @return {cc.Rect}
+ */
+ getRectInPixels: function () {
+ var locRectInPixels = this._rectInPixels;
+ return cc.rect(locRectInPixels.x, locRectInPixels.y, locRectInPixels.width, locRectInPixels.height);
+ },
+
+ /**
+ * Sets the rect of the frame in the texture
+ * @param {cc.Rect} rectInPixels
+ */
+ setRectInPixels: function (rectInPixels) {
+ if (!this._rectInPixels) {
+ this._rectInPixels = cc.rect(0, 0, 0, 0);
+ }
+ this._rectInPixels.x = rectInPixels.x;
+ this._rectInPixels.y = rectInPixels.y;
+ this._rectInPixels.width = rectInPixels.width;
+ this._rectInPixels.height = rectInPixels.height;
+ this._rect = cc.rectPixelsToPoints(rectInPixels);
+ },
+
+ /**
+ * Returns whether the sprite frame is rotated in the texture.
+ * @return {Boolean}
+ */
+ isRotated: function () {
+ return this._rotated;
+ },
+
+ /**
+ * Set whether the sprite frame is rotated in the texture.
+ * @param {Boolean} bRotated
+ */
+ setRotated: function (bRotated) {
+ this._rotated = bRotated;
+ },
+
+ /**
+ * Returns the rect of the sprite frame in the texture
+ * @return {cc.Rect}
+ */
+ getRect: function () {
+ var locRect = this._rect;
+ return cc.rect(locRect.x, locRect.y, locRect.width, locRect.height);
+ },
+
+ /**
+ * Sets the rect of the sprite frame in the texture
+ * @param {cc.Rect} rect
+ */
+ setRect: function (rect) {
+ if (!this._rect) {
+ this._rect = cc.rect(0, 0, 0, 0);
+ }
+ this._rect.x = rect.x;
+ this._rect.y = rect.y;
+ this._rect.width = rect.width;
+ this._rect.height = rect.height;
+ this._rectInPixels = cc.rectPointsToPixels(this._rect);
+ },
+
+ /**
+ * Returns the offset of the sprite frame in the texture in pixel
+ * @return {cc.Point}
+ */
+ getOffsetInPixels: function () {
+ return cc.p(this._offsetInPixels);
+ },
+
+ /**
+ * Sets the offset of the sprite frame in the texture in pixel
+ * @param {cc.Point} offsetInPixels
+ */
+ setOffsetInPixels: function (offsetInPixels) {
+ this._offsetInPixels.x = offsetInPixels.x;
+ this._offsetInPixels.y = offsetInPixels.y;
+ cc._pointPixelsToPointsOut(this._offsetInPixels, this._offset);
+ },
+
+ /**
+ * Returns the original size of the trimmed image
+ * @return {cc.Size}
+ */
+ getOriginalSizeInPixels: function () {
+ return cc.size(this._originalSizeInPixels);
+ },
+
+ /**
+ * Sets the original size of the trimmed image
+ * @param {cc.Size} sizeInPixels
+ */
+ setOriginalSizeInPixels: function (sizeInPixels) {
+ this._originalSizeInPixels.width = sizeInPixels.width;
+ this._originalSizeInPixels.height = sizeInPixels.height;
+ },
+
+ /**
+ * Returns the original size of the trimmed image
+ * @return {cc.Size}
+ */
+ getOriginalSize: function () {
+ return cc.size(this._originalSize);
+ },
+
+ /**
+ * Sets the original size of the trimmed image
+ * @param {cc.Size} sizeInPixels
+ */
+ setOriginalSize: function (sizeInPixels) {
+ this._originalSize.width = sizeInPixels.width;
+ this._originalSize.height = sizeInPixels.height;
+ },
+
+ /**
+ * Returns the texture of the frame
+ * @return {cc.Texture2D}
+ */
+ getTexture: function () {
+ if (this._texture)
+ return this._texture;
+ if (this._textureFilename !== "") {
+ var locTexture = cc.textureCache.addImage(this._textureFilename);
+ if (locTexture)
+ this._textureLoaded = locTexture.isLoaded();
+ return locTexture;
+ }
+ return null;
+ },
+
+ /**
+ * Sets the texture of the frame, the texture is retained automatically
+ * @param {cc.Texture2D} texture
+ */
+ setTexture: function (texture) {
+ if (this._texture !== texture) {
+ var locLoaded = texture.isLoaded();
+ this._textureLoaded = locLoaded;
+ this._texture = texture;
+ if (!locLoaded) {
+ texture.addEventListener("load", function (sender) {
+ this._textureLoaded = true;
+ if (this._rotated && cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+ var tempElement = sender.getHtmlElementObj();
+ tempElement = cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas(tempElement, this.getRect());
+ var tempTexture = new cc.Texture2D();
+ tempTexture.initWithElement(tempElement);
+ tempTexture.handleLoadedTexture();
+ this.setTexture(tempTexture);
+
+ var rect = this.getRect();
+ this.setRect(cc.rect(0, 0, rect.width, rect.height));
+ }
+ var locRect = this._rect;
+ if (locRect.width === 0 && locRect.height === 0) {
+ var w = sender.width, h = sender.height;
+ this._rect.width = w;
+ this._rect.height = h;
+ this._rectInPixels = cc.rectPointsToPixels(this._rect);
+ this._originalSizeInPixels.width = this._rectInPixels.width;
+ this._originalSizeInPixels.height = this._rectInPixels.height;
+ this._originalSize.width = w;
+ this._originalSize.height = h;
+ }
+ //dispatch 'load' event of cc.SpriteFrame
+ this.dispatchEvent("load");
+ }, this);
+ }
+ }
+ },
+
+ /**
+ * Returns the offset of the frame in the texture
+ * @return {cc.Point}
+ */
+ getOffset: function () {
+ return cc.p(this._offset);
+ },
+
+ /**
+ * Sets the offset of the frame in the texture
+ * @param {cc.Point} offsets
+ */
+ setOffset: function (offsets) {
+ this._offset.x = offsets.x;
+ this._offset.y = offsets.y;
+ },
+
+ /**
+ * Clone the sprite frame
+ * @returns {SpriteFrame}
+ */
+ clone: function () {
+ var frame = new cc.SpriteFrame();
+ frame.initWithTexture(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels);
+ frame.setTexture(this._texture);
+ return frame;
+ },
+
+ /**
+ * Copy the sprite frame
+ * @return {cc.SpriteFrame}
+ */
+ copyWithZone: function () {
+ var copy = new cc.SpriteFrame();
+ copy.initWithTexture(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels);
+ copy.setTexture(this._texture);
+ return copy;
+ },
+
+ /**
+ * Copy the sprite frame
+ * @returns {cc.SpriteFrame}
+ */
+ copy: function () {
+ return this.copyWithZone();
+ },
+
+ /**
+ * Initializes SpriteFrame with Texture, rect, rotated, offset and originalSize in pixels.
+ * Please pass parameters to the constructor to initialize the sprite, do not call this function yourself.
+ * @param {String|cc.Texture2D} texture
+ * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels
+ * @param {Boolean} [rotated=false]
+ * @param {cc.Point} [offset=cc.p(0,0)]
+ * @param {cc.Size} [originalSize=rect.size]
+ * @return {Boolean}
+ */
+ initWithTexture: function (texture, rect, rotated, offset, originalSize) {
+ if (arguments.length === 2)
+ rect = cc.rectPointsToPixels(rect);
+
+ offset = offset || cc.p(0, 0);
+ originalSize = originalSize || rect;
+ rotated = rotated || false;
+
+ if (typeof texture === 'string') {
+ this._texture = null;
+ this._textureFilename = texture;
+ } else if (texture instanceof cc.Texture2D) {
+ this.setTexture(texture);
+ }
+
+ texture = this.getTexture();
+
+ this._rectInPixels = rect;
+ this._rect = cc.rectPixelsToPoints(rect);
+
+ if (texture && texture.url && texture.isLoaded()) {
+ var _x, _y;
+ if (rotated) {
+ _x = rect.x + rect.height;
+ _y = rect.y + rect.width;
+ } else {
+ _x = rect.x + rect.width;
+ _y = rect.y + rect.height;
+ }
+ if (_x > texture.getPixelsWide()) {
+ cc.error(cc._LogInfos.RectWidth, texture.url);
+ }
+ if (_y > texture.getPixelsHigh()) {
+ cc.error(cc._LogInfos.RectHeight, texture.url);
+ }
+ }
+
+ this._offsetInPixels.x = offset.x;
+ this._offsetInPixels.y = offset.y;
+ cc._pointPixelsToPointsOut(offset, this._offset);
+ this._originalSizeInPixels.width = originalSize.width;
+ this._originalSizeInPixels.height = originalSize.height;
+ cc._sizePixelsToPointsOut(originalSize, this._originalSize);
+ this._rotated = rotated;
+ return true;
+ }
+});
+
+cc.EventHelper.prototype.apply(cc.SpriteFrame.prototype);
+
+/**
+ *
+ * Create a cc.SpriteFrame with a texture filename, rect, rotated, offset and originalSize in pixels.
+ * The originalSize is the size in pixels of the frame before being trimmed.
+ *
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.SpriteFrame
+ * @param {String|cc.Texture2D} filename
+ * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels
+ * @param {Boolean} rotated
+ * @param {cc.Point} offset
+ * @param {cc.Size} originalSize
+ * @return {cc.SpriteFrame}
+ */
+cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) {
+ return new cc.SpriteFrame(filename, rect, rotated, offset, originalSize);
+};
+
+/**
+ * @deprecated since v3.0, please use new construction instead
+ * @see cc.SpriteFrame
+ * @function
+ */
+cc.SpriteFrame.createWithTexture = cc.SpriteFrame.create;
+
+cc.SpriteFrame._frameWithTextureForCanvas = function (texture, rect, rotated, offset, originalSize) {
+ var spriteFrame = new cc.SpriteFrame();
+ spriteFrame._texture = texture;
+ spriteFrame._rectInPixels = rect;
+ spriteFrame._rect = cc.rectPixelsToPoints(rect);
+ spriteFrame._offsetInPixels.x = offset.x;
+ spriteFrame._offsetInPixels.y = offset.y;
+ cc._pointPixelsToPointsOut(spriteFrame._offsetInPixels, spriteFrame._offset);
+ spriteFrame._originalSizeInPixels.width = originalSize.width;
+ spriteFrame._originalSizeInPixels.height = originalSize.height;
+ cc._sizePixelsToPointsOut(spriteFrame._originalSizeInPixels, spriteFrame._originalSize);
+ spriteFrame._rotated = rotated;
+ return spriteFrame;
+};
diff --git a/cocos2d/core/sprites/CCSpriteFrameCache.js b/cocos2d/core/sprites/CCSpriteFrameCache.js
new file mode 100644
index 0000000000..7d38e89a5b
--- /dev/null
+++ b/cocos2d/core/sprites/CCSpriteFrameCache.js
@@ -0,0 +1,360 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ *
+ * cc.spriteFrameCache is a singleton that handles the loading of the sprite frames. It saves in a cache the sprite frames.
+ *
+ * example
+ * // add SpriteFrames to spriteFrameCache With File
+ * cc.spriteFrameCache.addSpriteFrames(s_grossiniPlist);
+ *
+ * @class
+ * @name cc.spriteFrameCache
+ */
+cc.spriteFrameCache = /** @lends cc.spriteFrameCache# */{
+ _CCNS_REG1: /^\s*\{\s*([\-]?\d+[.]?\d*)\s*,\s*([\-]?\d+[.]?\d*)\s*\}\s*$/,
+ _CCNS_REG2: /^\s*\{\s*\{\s*([\-]?\d+[.]?\d*)\s*,\s*([\-]?\d+[.]?\d*)\s*\}\s*,\s*\{\s*([\-]?\d+[.]?\d*)\s*,\s*([\-]?\d+[.]?\d*)\s*\}\s*\}\s*$/,
+
+ _spriteFrames: {},
+ _spriteFramesAliases: {},
+ _frameConfigCache: {},
+
+ _rectFromString: function (content) {
+ var result = this._CCNS_REG2.exec(content);
+ if (!result) return cc.rect(0, 0, 0, 0);
+ return cc.rect(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), parseFloat(result[4]));
+ },
+
+ _pointFromString: function (content) {
+ var result = this._CCNS_REG1.exec(content);
+ if (!result) return cc.p(0, 0);
+ return cc.p(parseFloat(result[1]), parseFloat(result[2]));
+ },
+
+ _sizeFromString: function (content) {
+ var result = this._CCNS_REG1.exec(content);
+ if (!result) return cc.size(0, 0);
+ return cc.size(parseFloat(result[1]), parseFloat(result[2]));
+ },
+
+ _getFrameConfig: function (url) {
+ var dict = cc.loader.getRes(url);
+
+ cc.assert(dict, cc._LogInfos.spriteFrameCache__getFrameConfig_2, url);
+
+ cc.loader.release(url);//release it in loader
+ if (dict._inited) {
+ this._frameConfigCache[url] = dict;
+ return dict;
+ }
+ this._frameConfigCache[url] = this._parseFrameConfig(dict);
+ return this._frameConfigCache[url];
+ },
+
+ _getFrameConfigByJsonObject: function (url, jsonObject) {
+ cc.assert(jsonObject, cc._LogInfos.spriteFrameCache__getFrameConfig_2, url);
+ this._frameConfigCache[url] = this._parseFrameConfig(jsonObject);
+ return this._frameConfigCache[url];
+ },
+
+ _parseFrameConfig: function (dict) {
+ var tempFrames = dict["frames"], tempMeta = dict["metadata"] || dict["meta"];
+ var frames = {}, meta = {};
+ var format = 0;
+ if (tempMeta) {//init meta
+ var tmpFormat = tempMeta["format"];
+ format = (tmpFormat.length <= 1) ? parseInt(tmpFormat) : tmpFormat;
+ meta.image = tempMeta["textureFileName"] || tempMeta["textureFileName"] || tempMeta["image"];
+ }
+ for (var key in tempFrames) {
+ var frameDict = tempFrames[key];
+ if (!frameDict) continue;
+ var tempFrame = {};
+
+ if (format == 0) {
+ tempFrame.rect = cc.rect(frameDict["x"], frameDict["y"], frameDict["width"], frameDict["height"]);
+ tempFrame.rotated = false;
+ tempFrame.offset = cc.p(frameDict["offsetX"], frameDict["offsetY"]);
+ var ow = frameDict["originalWidth"];
+ var oh = frameDict["originalHeight"];
+ // check ow/oh
+ if (!ow || !oh) {
+ cc.log(cc._LogInfos.spriteFrameCache__getFrameConfig);
+ }
+ // Math.abs ow/oh
+ ow = Math.abs(ow);
+ oh = Math.abs(oh);
+ tempFrame.size = cc.size(ow, oh);
+ } else if (format == 1 || format == 2) {
+ tempFrame.rect = this._rectFromString(frameDict["frame"]);
+ tempFrame.rotated = frameDict["rotated"] || false;
+ tempFrame.offset = this._pointFromString(frameDict["offset"]);
+ tempFrame.size = this._sizeFromString(frameDict["sourceSize"]);
+ } else if (format == 3) {
+ // get values
+ var spriteSize = this._sizeFromString(frameDict["spriteSize"]);
+ var textureRect = this._rectFromString(frameDict["textureRect"]);
+ if (spriteSize) {
+ textureRect = cc.rect(textureRect.x, textureRect.y, spriteSize.width, spriteSize.height);
+ }
+ tempFrame.rect = textureRect;
+ tempFrame.rotated = frameDict["textureRotated"] || false; // == "true";
+ tempFrame.offset = this._pointFromString(frameDict["spriteOffset"]);
+ tempFrame.size = this._sizeFromString(frameDict["spriteSourceSize"]);
+ tempFrame.aliases = frameDict["aliases"];
+ } else {
+ var tmpFrame = frameDict["frame"], tmpSourceSize = frameDict["sourceSize"];
+ key = frameDict["filename"] || key;
+ tempFrame.rect = cc.rect(tmpFrame["x"], tmpFrame["y"], tmpFrame["w"], tmpFrame["h"]);
+ tempFrame.rotated = frameDict["rotated"] || false;
+ tempFrame.offset = cc.p(0, 0);
+ tempFrame.size = cc.size(tmpSourceSize["w"], tmpSourceSize["h"]);
+ }
+ frames[key] = tempFrame;
+ }
+ return {_inited: true, frames: frames, meta: meta};
+ },
+
+ // Adds multiple Sprite Frames from a json object. it uses for local web view app.
+ _addSpriteFramesByObject: function (url, jsonObject, texture) {
+ cc.assert(url, cc._LogInfos.spriteFrameCache_addSpriteFrames_2);
+ if (!jsonObject || !jsonObject["frames"])
+ return;
+
+ var frameConfig = this._frameConfigCache[url] || this._getFrameConfigByJsonObject(url, jsonObject);
+ //this._checkConflict(frameConfig); //TODO
+ this._createSpriteFrames(url, frameConfig, texture);
+ },
+
+ _createSpriteFrames: function (url, frameConfig, texture) {
+ var frames = frameConfig.frames, meta = frameConfig.meta;
+ if (!texture) {
+ var texturePath = cc.path.changeBasename(url, meta.image || ".png");
+ texture = cc.textureCache.addImage(texturePath);
+ } else if (texture instanceof cc.Texture2D) {
+ //do nothing
+ } else if (cc.isString(texture)) {//string
+ texture = cc.textureCache.addImage(texture);
+ } else {
+ cc.assert(0, cc._LogInfos.spriteFrameCache_addSpriteFrames_3);
+ }
+
+ //create sprite frames
+ var spAliases = this._spriteFramesAliases, spriteFrames = this._spriteFrames;
+ for (var key in frames) {
+ var frame = frames[key];
+ var spriteFrame = spriteFrames[key];
+ if (!spriteFrame) {
+ spriteFrame = new cc.SpriteFrame(texture, cc.rect(frame.rect), frame.rotated, frame.offset, frame.size);
+ var aliases = frame.aliases;
+ if (aliases) {//set aliases
+ for (var i = 0, li = aliases.length; i < li; i++) {
+ var alias = aliases[i];
+ if (spAliases[alias])
+ cc.log(cc._LogInfos.spriteFrameCache_addSpriteFrames, alias);
+ spAliases[alias] = key;
+ }
+ }
+
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS && spriteFrame.isRotated()) {
+ //clip to canvas
+ var locTexture = spriteFrame.getTexture();
+ if (locTexture.isLoaded()) {
+ var tempElement = spriteFrame.getTexture().getHtmlElementObj();
+ tempElement = cc.Sprite.CanvasRenderCmd._cutRotateImageToCanvas(tempElement, spriteFrame.getRectInPixels());
+ var tempTexture = new cc.Texture2D();
+ tempTexture.initWithElement(tempElement);
+ tempTexture.handleLoadedTexture();
+ spriteFrame.setTexture(tempTexture);
+ spriteFrame.setRotated(false);
+
+ var rect = spriteFrame._rect;
+ spriteFrame.setRect(cc.rect(0, 0, rect.width, rect.height));
+ }
+ }
+ spriteFrames[key] = spriteFrame;
+ }
+ }
+ },
+
+ /**
+ *
+ * Adds multiple Sprite Frames from a plist or json file.
+ * A texture will be loaded automatically. The texture name will composed by replacing the .plist or .json suffix with .png
+ * If you want to use another texture, you should use the addSpriteFrames:texture parameter.
+ *
+ * @param {String} url file path
+ * @param {HTMLImageElement|cc.Texture2D|string} [texture]
+ * @example
+ * // add SpriteFrames to SpriteFrameCache With File
+ * cc.spriteFrameCache.addSpriteFrames(s_grossiniPlist);
+ * cc.spriteFrameCache.addSpriteFrames(s_grossiniJson);
+ */
+ addSpriteFrames: function (url, texture) {
+ cc.assert(url, cc._LogInfos.spriteFrameCache_addSpriteFrames_2);
+
+ //Is it a SpriteFrame plist?
+ var dict = this._frameConfigCache[url] || cc.loader.getRes(url);
+ if (!dict || !dict["frames"])
+ return;
+
+ var frameConfig = this._frameConfigCache[url] || this._getFrameConfig(url);
+ //this._checkConflict(frameConfig); //TODO
+ this._createSpriteFrames(url, frameConfig, texture);
+ },
+
+ // Function to check if frames to add exists already, if so there may be name conflit that must be solved
+ _checkConflict: function (dictionary) {
+ var framesDict = dictionary["frames"];
+
+ for (var key in framesDict) {
+ if (this._spriteFrames[key]) {
+ cc.log(cc._LogInfos.spriteFrameCache__checkConflict, key);
+ }
+ }
+ },
+
+ /**
+ *
+ * Adds an sprite frame with a given name.
+ * If the name already exists, then the contents of the old name will be replaced with the new one.
+ *
+ * @param {cc.SpriteFrame} frame
+ * @param {String} frameName
+ */
+ addSpriteFrame: function (frame, frameName) {
+ this._spriteFrames[frameName] = frame;
+ },
+
+ /**
+ *
+ * Purges the dictionary of loaded sprite frames.
+ * Call this method if you receive the "Memory Warning".
+ * In the short term: it will free some resources preventing your app from being killed.
+ * In the medium term: it will allocate more resources.
+ * In the long term: it will be the same.
+ *
+ */
+ removeSpriteFrames: function () {
+ this._spriteFrames = {};
+ this._spriteFramesAliases = {};
+ },
+
+ /**
+ * Deletes an sprite frame from the sprite frame cache.
+ * @param {String} name
+ */
+ removeSpriteFrameByName: function (name) {
+ // explicit nil handling
+ if (!name) {
+ return;
+ }
+
+ // Is this an alias ?
+ if (this._spriteFramesAliases[name]) {
+ delete(this._spriteFramesAliases[name]);
+ }
+ if (this._spriteFrames[name]) {
+ delete(this._spriteFrames[name]);
+ }
+ // XXX. Since we don't know the .plist file that originated the frame, we must remove all .plist from the cache
+ },
+
+ /**
+ *
+ * Removes multiple Sprite Frames from a plist file.
+ * Sprite Frames stored in this file will be removed.
+ * It is convinient to call this method when a specific texture needs to be removed.
+ *
+ * @param {String} url Plist filename
+ */
+ removeSpriteFramesFromFile: function (url) {
+ var self = this, spriteFrames = self._spriteFrames,
+ aliases = self._spriteFramesAliases, cfg = self._frameConfigCache[url];
+ if (!cfg) return;
+ var frames = cfg.frames;
+ for (var key in frames) {
+ if (spriteFrames[key]) {
+ delete(spriteFrames[key]);
+ for (var alias in aliases) {//remove alias
+ if (aliases[alias] === key) delete aliases[alias];
+ }
+ }
+ }
+ },
+
+ /**
+ *
+ * Removes all Sprite Frames associated with the specified textures.
+ * It is convenient to call this method when a specific texture needs to be removed.
+ *
+ * @param {HTMLImageElement|HTMLCanvasElement|cc.Texture2D} texture
+ */
+ removeSpriteFramesFromTexture: function (texture) {
+ var self = this, spriteFrames = self._spriteFrames, aliases = self._spriteFramesAliases;
+ for (var key in spriteFrames) {
+ var frame = spriteFrames[key];
+ if (frame && (frame.getTexture() === texture)) {
+ delete(spriteFrames[key]);
+ for (var alias in aliases) {//remove alias
+ if (aliases[alias] === key) delete aliases[alias];
+ }
+ }
+ }
+ },
+
+ /**
+ *
+ * Returns an Sprite Frame that was previously added.
+ * If the name is not found it will return nil.
+ * You should retain the returned copy if you are going to use it.
+ *
+ * @param {String} name name of SpriteFrame
+ * @return {cc.SpriteFrame}
+ * @example
+ * //get a SpriteFrame by name
+ * var frame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png");
+ */
+ getSpriteFrame: function (name) {
+ var self = this, frame = self._spriteFrames[name];
+ if (!frame) {
+ // try alias dictionary
+ var key = self._spriteFramesAliases[name];
+ if (key) {
+ frame = self._spriteFrames[key.toString()];
+ if (!frame) delete self._spriteFramesAliases[name];
+ }
+ }
+ return frame;
+ },
+
+ _clear: function () {
+ this._spriteFrames = {};
+ this._spriteFramesAliases = {};
+ this._frameConfigCache = {};
+ }
+};
diff --git a/cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js b/cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js
new file mode 100644
index 0000000000..51ea5024cb
--- /dev/null
+++ b/cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js
@@ -0,0 +1,332 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//Sprite's WebGL render command
+(function () {
+
+ cc.Sprite.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = true;
+
+ this._vertices = [
+ {x: 0, y: 0, u: 0, v: 0}, // tl
+ {x: 0, y: 0, u: 0, v: 0}, // bl
+ {x: 0, y: 0, u: 0, v: 0}, // tr
+ {x: 0, y: 0, u: 0, v: 0} // br
+ ];
+ this._color = new Uint32Array(1);
+ this._dirty = false;
+ this._recursiveDirty = false;
+
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
+ };
+
+ var proto = cc.Sprite.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.Sprite.WebGLRenderCmd;
+ proto._spriteCmdCtor = cc.Sprite.WebGLRenderCmd;
+
+ proto.updateBlendFunc = function (blendFunc) {
+ };
+
+ proto.setDirtyFlag = function (dirtyFlag) {
+ cc.Node.WebGLRenderCmd.prototype.setDirtyFlag.call(this, dirtyFlag);
+ this._dirty = true;
+ };
+
+ proto.setDirtyRecursively = function (value) {
+ this._recursiveDirty = value;
+ this._dirty = value;
+ // recursively set dirty
+ var locChildren = this._node._children, child, l = locChildren ? locChildren.length : 0;
+ for (var i = 0; i < l; i++) {
+ child = locChildren[i];
+ (child instanceof cc.Sprite) && child._renderCmd.setDirtyRecursively(value);
+ }
+ };
+
+ proto._setBatchNodeForAddChild = function (child) {
+ var node = this._node;
+ if (node._batchNode) {
+ if (!(child instanceof cc.Sprite)) {
+ cc.log(cc._LogInfos.Sprite_addChild);
+ return false;
+ }
+ if (child.texture._webTextureObj !== node.textureAtlas.texture._webTextureObj)
+ cc.log(cc._LogInfos.Sprite_addChild_2);
+
+ //put it in descendants array of batch node
+ node._batchNode.appendChild(child);
+ if (!node._reorderChildDirty)
+ node._setReorderChildDirtyRecursively();
+ }
+ return true;
+ };
+
+ proto._handleTextureForRotatedTexture = function (texture) {
+ return texture;
+ };
+
+ proto.isFrameDisplayed = function (frame) {
+ var node = this._node;
+ return (cc.rectEqualToRect(frame.getRect(), node._rect) && frame.getTexture().getName() === node._texture.getName()
+ && cc.pointEqualToPoint(frame.getOffset(), node._unflippedOffsetPositionFromCenter));
+ };
+
+ proto._textureLoadedCallback = function (sender) {
+ if (this._textureLoaded)
+ return;
+
+ this._textureLoaded = true;
+ var locRect = this._rect;
+ if (!locRect) {
+ locRect = cc.rect(0, 0, sender.width, sender.height);
+ } else if (cc._rectEqualToZero(locRect)) {
+ locRect.width = sender.width;
+ locRect.height = sender.height;
+ }
+
+ this.texture = sender;
+ this.setTextureRect(locRect, this._rectRotated);
+
+ // by default use "Self Render".
+ // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
+ this.setBatchNode(this._batchNode);
+ this.dispatchEvent("load");
+
+ // Force refresh the render command list
+ cc.renderer.childrenOrderDirty = true;
+ };
+
+ proto._setTextureCoords = function (rect, needConvert) {
+ if (needConvert === undefined)
+ needConvert = true;
+ if (needConvert)
+ rect = cc.rectPointsToPixels(rect);
+ var node = this._node;
+
+ var tex = node._batchNode ? node.textureAtlas.texture : node._texture;
+ var uvs = this._vertices;
+ if (!tex)
+ return;
+
+ var atlasWidth = tex.pixelsWidth;
+ var atlasHeight = tex.pixelsHeight;
+
+ var left, right, top, bottom, tempSwap;
+ if (node._rectRotated) {
+ if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
+ left = (2 * rect.x + 1) / (2 * atlasWidth);
+ right = left + (rect.height * 2 - 2) / (2 * atlasWidth);
+ top = (2 * rect.y + 1) / (2 * atlasHeight);
+ bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight);
+ } else {
+ left = rect.x / atlasWidth;
+ right = (rect.x + rect.height) / atlasWidth;
+ top = rect.y / atlasHeight;
+ bottom = (rect.y + rect.width) / atlasHeight;
+ }
+
+ if (node._flippedX) {
+ tempSwap = top;
+ top = bottom;
+ bottom = tempSwap;
+ }
+
+ if (node._flippedY) {
+ tempSwap = left;
+ left = right;
+ right = tempSwap;
+ }
+
+ uvs[0].u = right; // tl
+ uvs[0].v = top; // tl
+ uvs[1].u = left; // bl
+ uvs[1].v = top; // bl
+ uvs[2].u = right; // tr
+ uvs[2].v = bottom; // tr
+ uvs[3].u = left; // br
+ uvs[3].v = bottom; // br
+ } else {
+ if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
+ left = (2 * rect.x + 1) / (2 * atlasWidth);
+ right = left + (rect.width * 2 - 2) / (2 * atlasWidth);
+ top = (2 * rect.y + 1) / (2 * atlasHeight);
+ bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight);
+ } else {
+ left = rect.x / atlasWidth;
+ right = (rect.x + rect.width) / atlasWidth;
+ top = rect.y / atlasHeight;
+ bottom = (rect.y + rect.height) / atlasHeight;
+ }
+
+ if (node._flippedX) {
+ tempSwap = left;
+ left = right;
+ right = tempSwap;
+ }
+
+ if (node._flippedY) {
+ tempSwap = top;
+ top = bottom;
+ bottom = tempSwap;
+ }
+
+ uvs[0].u = left; // tl
+ uvs[0].v = top; // tl
+ uvs[1].u = left; // bl
+ uvs[1].v = bottom; // bl
+ uvs[2].u = right; // tr
+ uvs[2].v = top; // tr
+ uvs[3].u = right; // br
+ uvs[3].v = bottom; // br
+ }
+ };
+
+ proto._setColorDirty = function () {
+ };
+
+ proto._updateBlendFunc = function () {
+ if (this._batchNode) {
+ cc.log(cc._LogInfos.Sprite__updateBlendFunc);
+ return;
+ }
+
+ // it's possible to have an untextured sprite
+ var node = this._node,
+ blendFunc = node._blendFunc;
+ if (!node._texture || !node._texture.hasPremultipliedAlpha()) {
+ if (blendFunc.src === cc.ONE && blendFunc.dst === cc.BLEND_DST) {
+ blendFunc.src = cc.SRC_ALPHA;
+ }
+ node.opacityModifyRGB = false;
+ } else {
+ if (blendFunc.src === cc.SRC_ALPHA && blendFunc.dst === cc.BLEND_DST) {
+ blendFunc.src = cc.ONE;
+ }
+ node.opacityModifyRGB = true;
+ }
+ };
+
+ proto._setTexture = function (texture) {
+ var node = this._node;
+ if (node._texture !== texture) {
+ node._textureLoaded = texture ? texture._textureLoaded : false;
+ node._texture = texture;
+
+ // Update texture rect and blend func
+ if (texture) {
+ var texSize = texture._contentSize;
+ var rect = cc.rect(0, 0, texSize.width, texSize.height);
+ node.setTextureRect(rect);
+ this._updateBlendFunc();
+ }
+
+ if (node._textureLoaded) {
+ // Force refresh the render command list
+ cc.renderer.childrenOrderDirty = true;
+ }
+ }
+ };
+
+ proto._checkTextureBoundary = function (texture, rect, rotated) {
+ if (texture && texture.url) {
+ var _x, _y;
+ if (rotated) {
+ _x = rect.x + rect.height;
+ _y = rect.y + rect.width;
+ } else {
+ _x = rect.x + rect.width;
+ _y = rect.y + rect.height;
+ }
+ if (_x > texture.width) {
+ cc.error(cc._LogInfos.RectWidth, texture.url);
+ }
+ if (_y > texture.height) {
+ cc.error(cc._LogInfos.RectHeight, texture.url);
+ }
+ }
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+
+ var node = this._node,
+ lx = node._offsetPosition.x, rx = lx + node._rect.width,
+ by = node._offsetPosition.y, ty = by + node._rect.height,
+ wt = this._worldTransform,
+ wtx = wt.tx, wty = wt.ty,
+ lxa = lx * wt.a, lxb = lx * wt.b, rxa = rx * wt.a, rxb = rx * wt.b,
+ tyc = ty * wt.c, tyd = ty * wt.d, byc = by * wt.c, byd = by * wt.d;
+
+ var vertices = this._vertices;
+ vertices[0].x = lxa + tyc + wtx; // tl
+ vertices[0].y = lxb + tyd + wty;
+ vertices[1].x = lxa + byc + wtx; // bl
+ vertices[1].y = lxb + byd + wty;
+ vertices[2].x = rxa + tyc + wtx; // tr
+ vertices[2].y = rxb + tyd + wty;
+ vertices[3].x = rxa + byc + wtx; // br
+ vertices[3].y = rxb + byd + wty;
+ };
+
+ proto.needDraw = function () {
+ var node = this._node, locTexture = node._texture;
+ return (this._needDraw && locTexture);
+ };
+
+ proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
+ var node = this._node, locTexture = node._texture;
+ if (!(locTexture && locTexture._textureLoaded && node._rect.width && node._rect.height) || !this._displayedOpacity)
+ return 0;
+
+ // Fill in vertex data with quad information (4 vertices for sprite)
+ var opacity = this._displayedOpacity;
+ var r = this._displayedColor.r,
+ g = this._displayedColor.g,
+ b = this._displayedColor.b;
+ if (node._opacityModifyRGB) {
+ var a = opacity / 255;
+ r *= a;
+ g *= a;
+ b *= a;
+ }
+ this._color[0] = ((opacity << 24) | (b << 16) | (g << 8) | r);
+ var z = node._vertexZ;
+
+ var vertices = this._vertices;
+ var i, len = vertices.length, vertex, offset = vertexDataOffset;
+ for (i = 0; i < len; ++i) {
+ vertex = vertices[i];
+ f32buffer[offset] = vertex.x;
+ f32buffer[offset + 1] = vertex.y;
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = this._color[0];
+ f32buffer[offset + 4] = vertex.u;
+ f32buffer[offset + 5] = vertex.v;
+ offset += 6;
+ }
+
+ return len;
+ };
+})();
diff --git a/cocos2d/core/sprites/SpritesPropertyDefine.js b/cocos2d/core/sprites/SpritesPropertyDefine.js
new file mode 100644
index 0000000000..20e8cc938a
--- /dev/null
+++ b/cocos2d/core/sprites/SpritesPropertyDefine.js
@@ -0,0 +1,67 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc._tmp.PrototypeSprite = function () {
+ var _p = cc.Sprite.prototype;
+
+ // Override properties
+ cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB, _p.setOpacityModifyRGB);
+ cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
+ cc.defineGetterSetter(_p, "color", _p.getColor, _p.setColor);
+
+ // Extended properties
+ /** @expose */
+ _p.dirty;
+ /** @expose */
+ _p.flippedX;
+ cc.defineGetterSetter(_p, "flippedX", _p.isFlippedX, _p.setFlippedX);
+ /** @expose */
+ _p.flippedY;
+ cc.defineGetterSetter(_p, "flippedY", _p.isFlippedY, _p.setFlippedY);
+ /** @expose */
+ _p.offsetX;
+ cc.defineGetterSetter(_p, "offsetX", _p._getOffsetX);
+ /** @expose */
+ _p.offsetY;
+ cc.defineGetterSetter(_p, "offsetY", _p._getOffsetY);
+ /** @expose */
+ _p.atlasIndex;
+ /** @expose */
+ _p.texture;
+ cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
+ /** @expose */
+ _p.textureRectRotated;
+ cc.defineGetterSetter(_p, "textureRectRotated", _p.isTextureRectRotated);
+ /** @expose */
+ _p.textureAtlas;
+ /** @expose */
+ _p.batchNode;
+ cc.defineGetterSetter(_p, "batchNode", _p.getBatchNode, _p.setBatchNode);
+ /** @expose */
+ _p.quad;
+ cc.defineGetterSetter(_p, "quad", _p.getQuad);
+
+};
diff --git a/cocos2d/support/CCPointExtension.js b/cocos2d/core/support/CCPointExtension.js
similarity index 91%
rename from cocos2d/support/CCPointExtension.js
rename to cocos2d/core/support/CCPointExtension.js
index 9003fe163a..3171a5f7ea 100644
--- a/cocos2d/support/CCPointExtension.js
+++ b/cocos2d/core/support/CCPointExtension.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -86,7 +86,7 @@ cc.pMult = function (point, floatVar) {
* Calculates midpoint between two points.
* @param {cc.Point} v1
* @param {cc.Point} v2
- * @return {cc.pMult}
+ * @return {cc.Point}
*/
cc.pMidpoint = function (v1, v2) {
return cc.pMult(cc.pAdd(v1, v2), 0.5);
@@ -134,7 +134,7 @@ cc.pRPerp = function (point) {
* Calculates the projection of v1 over v2.
* @param {cc.Point} v1
* @param {cc.Point} v2
- * @return {cc.pMult}
+ * @return {cc.Point}
*/
cc.pProject = function (v1, v2) {
return cc.pMult(v2, cc.pDot(v1, v2) / cc.pDot(v2, v2));
@@ -192,7 +192,7 @@ cc.pLength = function (v) {
* Calculates the distance between two points
* @param {cc.Point} v1
* @param {cc.Point} v2
- * @return {cc.pLength}
+ * @return {Number}
*/
cc.pDistance = function (v1, v2) {
return cc.pLength(cc.pSub(v1, v2));
@@ -204,7 +204,8 @@ cc.pDistance = function (v1, v2) {
* @return {cc.Point}
*/
cc.pNormalize = function (v) {
- return cc.pMult(v, 1.0 / cc.pLength(v));
+ var n = cc.pLength(v);
+ return n === 0 ? cc.p(v) : cc.pMult(v, 1.0 / n);
};
/**
@@ -283,7 +284,7 @@ cc.pCompOp = function (p, opFunc) {
* @param {cc.Point} a
* @param {cc.Point} b
* @param {Number} alpha
- * @return {cc.pAdd}
+ * @return {cc.Point}
*/
cc.pLerp = function (a, b, alpha) {
return cc.pAdd(cc.pMult(a, 1 - alpha), cc.pMult(b, alpha));
@@ -356,6 +357,11 @@ cc.pRotateByAngle = function (v, pivot, angle) {
/**
* A general line-line intersection test
+ * indicating successful intersection of a line
+ * note that to truly test intersection for segments we have to make
+ * sure that s & t lie within [0..1] and for rays, make sure s & t > 0
+ * the hit point is p3 + t * (p4 - p3);
+ * the hit point also is p1 + s * (p2 - p1);
* @param {cc.Point} A A is the startpoint for the first line P1 = (p1 - p2).
* @param {cc.Point} B B is the endpoint for the first line P1 = (p1 - p2).
* @param {cc.Point} C C is the startpoint for the second line P2 = (p3 - p4).
@@ -363,14 +369,9 @@ cc.pRotateByAngle = function (v, pivot, angle) {
* @param {cc.Point} retP retP.x is the range for a hitpoint in P1 (pa = p1 + s*(p2 - p1)),
* retP.y is the range for a hitpoint in P3 (pa = p2 + t*(p4 - p3)).
* @return {Boolean}
- * indicating successful intersection of a line
- * note that to truly test intersection for segments we have to make
- * sure that s & t lie within [0..1] and for rays, make sure s & t > 0
- * the hit point is p3 + t * (p4 - p3);
- * the hit point also is p1 + s * (p2 - p1);
*/
cc.pLineIntersect = function (A, B, C, D, retP) {
- if ((A.x == B.x && A.y == B.y) || (C.x == D.x && C.y == D.y)) {
+ if ((A.x === B.x && A.y === B.y) || (C.x === D.x && C.y === D.y)) {
return false;
}
var BAx = B.x - A.x;
@@ -385,8 +386,8 @@ cc.pLineIntersect = function (A, B, C, D, retP) {
retP.x = DCx * ACy - DCy * ACx;
retP.y = BAx * ACy - BAy * ACx;
- if (denom == 0) {
- if (retP.x == 0 || retP.y == 0) {
+ if (denom === 0) {
+ if (retP.x === 0 || retP.y === 0) {
// Lines incident
return true;
}
@@ -435,7 +436,7 @@ cc.pIntersectPoint = function (A, B, C, D) {
return P;
}
- return cc.PointZero();
+ return cc.p(0,0);
};
/**
@@ -446,59 +447,70 @@ cc.pIntersectPoint = function (A, B, C, D) {
*/
cc.pSameAs = function (A, B) {
if ((A != null) && (B != null)) {
- return (A.x == B.x && A.y == B.y);
+ return (A.x === B.x && A.y === B.y);
}
return false;
};
-// High Perfomance In Place Operationrs ---------------------------------------
+// High Performance In Place Operationrs ---------------------------------------
/**
- * sets the position of the point to 0
- */
+ * sets the position of the point to 0
+ * @param {cc.Point} v
+ */
cc.pZeroIn = function(v) {
v.x = 0;
v.y = 0;
};
/**
- * copies the position of one point to another
- */
+ * copies the position of one point to another
+ * @param {cc.Point} v1
+ * @param {cc.Point} v2
+ */
cc.pIn = function(v1, v2) {
v1.x = v2.x;
v1.y = v2.y;
};
/**
- * multiplies the point with the given factor (inplace)
- */
+ * multiplies the point with the given factor (inplace)
+ * @param {cc.Point} point
+ * @param {Number} floatVar
+ */
cc.pMultIn = function(point, floatVar) {
point.x *= floatVar;
point.y *= floatVar;
};
/**
- * subtracts one point from another (inplace)
- */
+ * subtracts one point from another (inplace)
+ * @param {cc.Point} v1
+ * @param {cc.Point} v2
+ */
cc.pSubIn = function(v1, v2) {
v1.x -= v2.x;
v1.y -= v2.y;
};
/**
- * adds one point to another (inplace)
- */
+ * adds one point to another (inplace)
+ * @param {cc.Point} v1
+ * @param {cc.Point} v2
+ */
cc.pAddIn = function(v1, v2) {
v1.x += v2.x;
v1.y += v2.y;
};
/**
- * normalizes the point (inplace)
- */
+ * normalizes the point (inplace)
+ * @param {cc.Point} v
+ */
cc.pNormalizeIn = function(v) {
- cc.pMultIn(v, 1.0 / Math.sqrt(v.x * v.x + v.y * v.y));
+ var n = Math.sqrt(v.x * v.x + v.y * v.y);
+ if (n !== 0)
+ cc.pMultIn(v, 1.0 / n);
};
-
diff --git a/cocos2d/support/CCVertex.js b/cocos2d/core/support/CCVertex.js
similarity index 81%
rename from cocos2d/support/CCVertex.js
rename to cocos2d/core/support/CCVertex.js
index 3272519442..44b92f0d22 100644
--- a/cocos2d/support/CCVertex.js
+++ b/cocos2d/core/support/CCVertex.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2009 Valentin Milea
http://www.cocos2d-x.org
@@ -58,9 +60,9 @@ cc.vertexLineToPolygon = function (points, stroke, vertices, offset, nuPoints) {
// Calculate angle between vectors
var angle = Math.acos(cc.pDot(p2p1, p0p1));
- if (angle < cc.DEGREES_TO_RADIANS(70))
+ if (angle < cc.degreesToRadians(70))
perpVector = cc.pPerp(cc.pNormalize(cc.pMidpoint(p2p1, p0p1)));
- else if (angle < cc.DEGREES_TO_RADIANS(170))
+ else if (angle < cc.degreesToRadians(170))
perpVector = cc.pNormalize(cc.pMidpoint(p2p1, p0p1));
else
perpVector = cc.pPerp(cc.pNormalize(cc.pSub(p2, p0)));
@@ -74,15 +76,15 @@ cc.vertexLineToPolygon = function (points, stroke, vertices, offset, nuPoints) {
}
// Validate vertexes
- offset = (offset == 0) ? 0 : offset - 1;
+ offset = (offset === 0) ? 0 : offset - 1;
for (i = offset; i < nuPointsMinus; i++) {
idx = i * 2;
var idx1 = idx + 2;
- var v1 = cc.Vertex2(vertices[idx * 2], vertices[idx * 2 + 1]);
- var v2 = cc.Vertex2(vertices[(idx + 1) * 2], vertices[(idx + 1) * 2 + 1]);
- var v3 = cc.Vertex2(vertices[idx1 * 2], vertices[idx1 * 2]);
- var v4 = cc.Vertex2(vertices[(idx1 + 1) * 2], vertices[(idx1 + 1) * 2 + 1]);
+ var v1 = cc.vertex2(vertices[idx * 2], vertices[idx * 2 + 1]);
+ var v2 = cc.vertex2(vertices[(idx + 1) * 2], vertices[(idx + 1) * 2 + 1]);
+ var v3 = cc.vertex2(vertices[idx1 * 2], vertices[idx1 * 2]);
+ var v4 = cc.vertex2(vertices[(idx1 + 1) * 2], vertices[(idx1 + 1) * 2 + 1]);
//BOOL fixVertex = !ccpLineIntersect(ccp(p1.x, p1.y), ccp(p4.x, p4.y), ccp(p2.x, p2.y), ccp(p3.x, p3.y), &s, &t);
var fixVertexResult = !cc.vertexLineIntersect(v1.x, v1.y, v4.x, v4.y, v2.x, v2.y, v3.x, v3.y);
@@ -100,7 +102,7 @@ cc.vertexLineToPolygon = function (points, stroke, vertices, offset, nuPoints) {
};
/**
- * returns wheter or not the line intersects
+ * returns whether or not the line intersects
* @param {Number} Ax
* @param {Number} Ay
* @param {Number} Bx
@@ -115,7 +117,7 @@ cc.vertexLineIntersect = function (Ax, Ay, Bx, By, Cx, Cy, Dx, Dy) {
var distAB, theCos, theSin, newX;
// FAIL: Line undefined
- if ((Ax == Bx && Ay == By) || (Cx == Dx && Cy == Dy))
+ if ((Ax === Bx && Ay === By) || (Cx === Dx && Cy === Dy))
return {isSuccess:false, value:0};
// Translate system to make A the origin
@@ -140,11 +142,29 @@ cc.vertexLineIntersect = function (Ax, Ay, Bx, By, Cx, Cy, Dx, Dy) {
Dx = newX;
// FAIL: Lines are parallel.
- if (Cy == Dy) return {isSuccess:false, value:0};
+ if (Cy === Dy) return {isSuccess:false, value:0};
// Discover the relative position of the intersection in the line AB
var t = (Dx + (Cx - Dx) * Dy / (Dy - Cy)) / distAB;
// Success.
return {isSuccess:true, value:t};
+};
+
+/**
+ * returns wheter or not polygon defined by vertex list is clockwise
+ * @param {Array} verts
+ * @return {Boolean}
+ */
+cc.vertexListIsClockwise = function(verts) {
+ for (var i = 0, len = verts.length; i < len; i++) {
+ var a = verts[i];
+ var b = verts[(i + 1) % len];
+ var c = verts[(i + 2) % len];
+
+ if (cc.pCross(cc.pSub(b, a), cc.pSub(c, b)) > 0)
+ return false;
+ }
+
+ return true;
};
\ No newline at end of file
diff --git a/cocos2d/support/TransformUtils.js b/cocos2d/core/support/TransformUtils.js
similarity index 83%
rename from cocos2d/support/TransformUtils.js
rename to cocos2d/core/support/TransformUtils.js
index 4716f6c8a9..bb57c6f8c4 100644
--- a/cocos2d/support/TransformUtils.js
+++ b/cocos2d/core/support/TransformUtils.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2009 Valentin Milea
http://www.cocos2d-x.org
@@ -23,6 +25,12 @@
THE SOFTWARE.
****************************************************************************/
+/**
+ * convert an affine transform object to a kmMat4 object
+ * @param {cc.AffineTransform} trans
+ * @param {cc.kmMat4} mat
+ * @function
+ */
cc.CGAffineToGL = function (trans, mat) {
// | m[0] m[4] m[8] m[12] | | m11 m21 m31 m41 | | a c 0 tx |
// | m[1] m[5] m[9] m[13] | | m12 m22 m32 m42 | | b d 0 ty |
@@ -38,6 +46,12 @@ cc.CGAffineToGL = function (trans, mat) {
mat[13] = trans.ty;
};
+/**
+ * Convert a kmMat4 object to an affine transform object
+ * @param {cc.kmMat4} mat
+ * @param {cc.AffineTransform} trans
+ * @function
+ */
cc.GLToCGAffine = function (mat, trans) {
trans.a = mat[0];
trans.c = mat[4];
diff --git a/cocos2d/core/textures/CCTexture2D.js b/cocos2d/core/textures/CCTexture2D.js
new file mode 100644
index 0000000000..b69d83cfd9
--- /dev/null
+++ b/cocos2d/core/textures/CCTexture2D.js
@@ -0,0 +1,622 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//CONSTANTS:
+
+/**
+ * Horizontal center and vertical center.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_CENTER = 0x33;
+
+/**
+ * Horizontal center and vertical top.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_TOP = 0x13;
+
+/**
+ * Horizontal right and vertical top.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_TOP_RIGHT = 0x12;
+
+/**
+ * Horizontal right and vertical center.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_RIGHT = 0x32;
+
+/**
+ * Horizontal right and vertical bottom.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_BOTTOM_RIGHT = 0x22;
+
+/**
+ * Horizontal center and vertical bottom.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_BOTTOM = 0x23;
+
+/**
+ * Horizontal left and vertical bottom.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_BOTTOM_LEFT = 0x21;
+
+/**
+ * Horizontal left and vertical center.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_LEFT = 0x31;
+
+/**
+ * Horizontal left and vertical top.
+ * @constant
+ * @type Number
+ */
+cc.ALIGN_TOP_LEFT = 0x11;
+//----------------------Possible texture pixel formats----------------------------
+
+
+// By default PVR images are treated as if they don't have the alpha channel premultiplied
+cc.PVRHaveAlphaPremultiplied_ = false;
+
+//cc.Texture2DWebGL move to TextureWebGL.js
+
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+
+ var proto = {
+ _contentSize: null,
+ _textureLoaded: false,
+ _htmlElementObj: null,
+ url: null,
+ _pattern: null,
+
+ ctor: function () {
+ this._contentSize = cc.size(0, 0);
+ this._textureLoaded = false;
+ this._htmlElementObj = null;
+ this._pattern = "";
+ this._pixelsWide = 0;
+ this._pixelsHigh = 0;
+ },
+
+ /**
+ * get width in pixels
+ * @return {Number}
+ */
+ getPixelsWide: function () {
+ return this._pixelsWide;
+ },
+
+ /**
+ * get height of in pixels
+ * @return {Number}
+ */
+ getPixelsHigh: function () {
+ return this._pixelsHigh;
+ },
+
+ /**
+ * get content size
+ * @returns {cc.Size}
+ */
+ getContentSize: function () {
+ var locScaleFactor = cc.contentScaleFactor();
+ return cc.size(this._contentSize.width / locScaleFactor, this._contentSize.height / locScaleFactor);
+ },
+
+ _getWidth: function () {
+ return this._contentSize.width / cc.contentScaleFactor();
+ },
+ _getHeight: function () {
+ return this._contentSize.height / cc.contentScaleFactor();
+ },
+
+ /**
+ * get content size in pixels
+ * @returns {cc.Size}
+ */
+ getContentSizeInPixels: function () {
+ return this._contentSize;
+ },
+
+ /**
+ * init with HTML element
+ * @param {HTMLImageElement|HTMLCanvasElement} element
+ */
+ initWithElement: function (element) {
+ if (!element)
+ return;
+ this._htmlElementObj = element;
+ this._pixelsWide = this._contentSize.width = element.width;
+ this._pixelsHigh = this._contentSize.height = element.height;
+ this._textureLoaded = true;
+ },
+
+ /**
+ * HTMLElement Object getter
+ * @return {HTMLImageElement|HTMLCanvasElement}
+ */
+ getHtmlElementObj: function () {
+ return this._htmlElementObj;
+ },
+
+ /**
+ * check whether texture is loaded
+ * @returns {boolean}
+ */
+ isLoaded: function () {
+ return this._textureLoaded;
+ },
+
+ /**
+ * handle loaded texture
+ */
+ handleLoadedTexture: function () {
+ var self = this;
+ if (!self._htmlElementObj) {
+ return;
+ }
+
+ var locElement = self._htmlElementObj;
+ self._pixelsWide = self._contentSize.width = locElement.width;
+ self._pixelsHigh = self._contentSize.height = locElement.height;
+
+ //dispatch load event to listener.
+ self.dispatchEvent("load");
+ },
+
+ /**
+ * description of cc.Texture2D
+ * @returns {string}
+ */
+ description: function () {
+ return "";
+ },
+
+ initWithData: function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
+ //support only in WebGl rendering mode
+ return false;
+ },
+
+ initWithImage: function (uiImage) {
+ //support only in WebGl rendering mode
+ return false;
+ },
+
+ initWithString: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
+ //support only in WebGl rendering mode
+ return false;
+ },
+
+ releaseTexture: function () {
+ this._htmlElementObj = null;
+ cc.loader.release(this.url);
+ },
+
+ getName: function () {
+ //support only in WebGl rendering mode
+ return null;
+ },
+
+ getMaxS: function () {
+ //support only in WebGl rendering mode
+ return 1;
+ },
+
+ setMaxS: function (maxS) {
+ //support only in WebGl rendering mode
+ },
+
+ getMaxT: function () {
+ return 1;
+ },
+
+ setMaxT: function (maxT) {
+ //support only in WebGl rendering mode
+ },
+
+ getPixelFormat: function () {
+ //support only in WebGl rendering mode
+ return null;
+ },
+
+ getShaderProgram: function () {
+ //support only in WebGl rendering mode
+ return null;
+ },
+
+ setShaderProgram: function (shaderProgram) {
+ //support only in WebGl rendering mode
+ },
+
+ hasPremultipliedAlpha: function () {
+ //support only in WebGl rendering mode
+ return false;
+ },
+
+ hasMipmaps: function () {
+ //support only in WebGl rendering mode
+ return false;
+ },
+
+ releaseData: function (data) {
+ //support only in WebGl rendering mode
+ data = null;
+ },
+
+ keepData: function (data, length) {
+ //support only in WebGl rendering mode
+ return data;
+ },
+
+ drawAtPoint: function (point) {
+ //support only in WebGl rendering mode
+ },
+
+ drawInRect: function (rect) {
+ //support only in WebGl rendering mode
+ },
+
+ /**
+ * init with ETC file
+ * @warning does not support on HTML5
+ */
+ initWithETCFile: function (file) {
+ cc.log(cc._LogInfos.Texture2D_initWithETCFile);
+ return false;
+ },
+
+ /**
+ * init with PVR file
+ * @warning does not support on HTML5
+ */
+ initWithPVRFile: function (file) {
+ cc.log(cc._LogInfos.Texture2D_initWithPVRFile);
+ return false;
+ },
+
+ /**
+ * init with PVRTC data
+ * @warning does not support on HTML5
+ */
+ initWithPVRTCData: function (data, level, bpp, hasAlpha, length, pixelFormat) {
+ cc.log(cc._LogInfos.Texture2D_initWithPVRTCData);
+ return false;
+ },
+
+ setTexParameters: function (texParams, magFilter, wrapS, wrapT) {
+ if (magFilter !== undefined)
+ texParams = {minFilter: texParams, magFilter: magFilter, wrapS: wrapS, wrapT: wrapT};
+
+ if (texParams.wrapS === cc.REPEAT && texParams.wrapT === cc.REPEAT) {
+ this._pattern = "repeat";
+ return;
+ }
+
+ if (texParams.wrapS === cc.REPEAT) {
+ this._pattern = "repeat-x";
+ return;
+ }
+
+ if (texParams.wrapT === cc.REPEAT) {
+ this._pattern = "repeat-y";
+ return;
+ }
+
+ this._pattern = "";
+ },
+
+ setAntiAliasTexParameters: function () {
+ //support only in WebGl rendering mode
+ },
+
+ setAliasTexParameters: function () {
+ //support only in WebGl rendering mode
+ },
+
+ generateMipmap: function () {
+ //support only in WebGl rendering mode
+ },
+
+ stringForFormat: function () {
+ //support only in WebGl rendering mode
+ return "";
+ },
+
+ bitsPerPixelForFormat: function (format) {
+ //support only in WebGl rendering mode
+ return -1;
+ },
+
+ /**
+ * add listener for loaded event
+ * @param {Function} callback
+ * @param {cc.Node} target
+ * @deprecated since 3.1, please use addEventListener instead
+ */
+ addLoadedEventListener: function (callback, target) {
+ this.addEventListener("load", callback, target);
+ },
+
+ /**
+ * remove listener from listeners by target
+ * @param {cc.Node} target
+ */
+ removeLoadedEventListener: function (target) {
+ this.removeEventTarget("load", target);
+ },
+
+ _generateColorTexture: function () {/*overide*/
+ },
+ _generateTextureCacheForColor: function () {
+ if (this.channelCache)
+ return this.channelCache;
+
+ var textureCache = [
+ document.createElement("canvas"),
+ document.createElement("canvas"),
+ document.createElement("canvas"),
+ document.createElement("canvas")
+ ];
+ //todo texture onload
+ renderToCache(this._htmlElementObj, textureCache);
+ return this.channelCache = textureCache;
+ },
+
+ //hack for gray effect
+ _grayElementObj: null,
+ _backupElement: null,
+ _isGray: false,
+ _switchToGray: function (toGray) {
+ if (!this._textureLoaded || this._isGray === toGray)
+ return;
+ this._isGray = toGray;
+ if (this._isGray) {
+ this._backupElement = this._htmlElementObj;
+ if (!this._grayElementObj)
+ this._grayElementObj = cc.Texture2D._generateGrayTexture(this._htmlElementObj);
+ this._htmlElementObj = this._grayElementObj;
+ } else {
+ if (this._backupElement !== null)
+ this._htmlElementObj = this._backupElement;
+ }
+ },
+
+ _generateGrayTexture: function() {
+ if(!this._textureLoaded)
+ return null;
+ var grayElement = cc.Texture2D._generateGrayTexture(this._htmlElementObj);
+ var newTexture = new cc.Texture2D();
+ newTexture.initWithElement(grayElement);
+ newTexture.handleLoadedTexture();
+ return newTexture;
+ },
+ };
+
+ var renderToCache = function (image, cache) {
+ var w = image.width;
+ var h = image.height;
+
+ cache[0].width = w;
+ cache[0].height = h;
+ cache[1].width = w;
+ cache[1].height = h;
+ cache[2].width = w;
+ cache[2].height = h;
+ cache[3].width = w;
+ cache[3].height = h;
+
+ var cacheCtx = cache[3].getContext("2d");
+ cacheCtx.drawImage(image, 0, 0);
+ var pixels = cacheCtx.getImageData(0, 0, w, h).data;
+
+ var ctx;
+ for (var rgbI = 0; rgbI < 4; rgbI++) {
+ ctx = cache[rgbI].getContext("2d");
+
+ var to = ctx.getImageData(0, 0, w, h);
+ var data = to.data;
+ for (var i = 0; i < pixels.length; i += 4) {
+ data[i] = (rgbI === 0) ? pixels[i] : 0;
+ data[i + 1] = (rgbI === 1) ? pixels[i + 1] : 0;
+ data[i + 2] = (rgbI === 2) ? pixels[i + 2] : 0;
+ data[i + 3] = pixels[i + 3];
+ }
+ ctx.putImageData(to, 0, 0);
+ }
+ image.onload = null;
+ };
+
+ //change color function
+ if (cc.sys._supportCanvasNewBlendModes) {
+ //multiply mode
+ //Primary afferent, Draw a new texture based on rect
+ proto._generateColorTexture = function (r, g, b, rect, canvas) {
+ var onlyCanvas = false;
+ if (canvas)
+ onlyCanvas = true;
+ else
+ canvas = document.createElement("canvas");
+ var textureImage = this._htmlElementObj;
+ if (!rect)
+ rect = cc.rect(0, 0, textureImage.width, textureImage.height);
+
+ canvas.width = rect.width;
+ canvas.height = rect.height;
+
+ var context = canvas.getContext("2d");
+ context.globalCompositeOperation = "source-over";
+ context.fillStyle = "rgb(" + (r | 0) + "," + (g | 0) + "," + (b | 0) + ")";
+ context.fillRect(0, 0, rect.width, rect.height);
+ context.globalCompositeOperation = "multiply";
+ context.drawImage(
+ textureImage,
+ rect.x, rect.y, rect.width, rect.height,
+ 0, 0, rect.width, rect.height
+ );
+ context.globalCompositeOperation = "destination-atop";
+ context.drawImage(
+ textureImage,
+ rect.x, rect.y, rect.width, rect.height,
+ 0, 0, rect.width, rect.height
+ );
+ if (onlyCanvas)
+ return canvas;
+ var newTexture = new cc.Texture2D();
+ newTexture.initWithElement(canvas);
+ newTexture.handleLoadedTexture();
+ return newTexture;
+ };
+ } else {
+ //Four color map overlay
+ proto._generateColorTexture = function (r, g, b, rect, canvas) {
+ var onlyCanvas = false;
+ if (canvas)
+ onlyCanvas = true;
+ else
+ canvas = document.createElement("canvas");
+
+ var textureImage = this._htmlElementObj;
+ if (!rect)
+ rect = cc.rect(0, 0, textureImage.width, textureImage.height);
+ var x, y, w, h;
+ x = rect.x; y = rect.y; w = rect.width; h = rect.height;
+ if (!w || !h)
+ return;
+
+ canvas.width = w;
+ canvas.height = h;
+
+ var context = canvas.getContext("2d");
+ var tintedImgCache = cc.textureCache.getTextureColors(this);
+ context.globalCompositeOperation = 'lighter';
+ context.drawImage(
+ tintedImgCache[3],
+ x, y, w, h,
+ 0, 0, w, h
+ );
+ if (r > 0) {
+ context.globalAlpha = r / 255;
+ context.drawImage(
+ tintedImgCache[0],
+ x, y, w, h,
+ 0, 0, w, h
+ );
+ }
+ if (g > 0) {
+ context.globalAlpha = g / 255;
+ context.drawImage(
+ tintedImgCache[1],
+ x, y, w, h,
+ 0, 0, w, h
+ );
+ }
+ if (b > 0) {
+ context.globalAlpha = b / 255;
+ context.drawImage(
+ tintedImgCache[2],
+ x, y, w, h,
+ 0, 0, w, h
+ );
+ }
+ if (onlyCanvas)
+ return canvas;
+
+ var newTexture = new cc.Texture2D();
+ newTexture.initWithElement(canvas);
+ newTexture.handleLoadedTexture();
+ return newTexture;
+ };
+ }
+
+ /**
+ *
+ * This class allows to easily create OpenGL or Canvas 2D textures from images, text or raw data.
+ * The created cc.Texture2D object will always have power-of-two dimensions.
+ * Depending on how you create the cc.Texture2D object, the actual image area of the texture might be smaller than the texture dimensions
+ * i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).
+ * Be aware that the content of the generated textures will be upside-down!
+ * @name cc.Texture2D
+ * @class
+ * @extends cc.Class
+ *
+ * @property {WebGLTexture} name - <@readonly> WebGLTexture Object
+ * @property {Number} pixelFormat - <@readonly> Pixel format of the texture
+ * @property {Number} pixelsWidth - <@readonly> Width in pixels
+ * @property {Number} pixelsHeight - <@readonly> Height in pixels
+ * @property {Number} width - Content width in points
+ * @property {Number} height - Content height in points
+ * @property {cc.GLProgram} shaderProgram - The shader program used by drawAtPoint and drawInRect
+ * @property {Number} maxS - Texture max S
+ * @property {Number} maxT - Texture max T
+ */
+ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */proto);
+
+ cc.Texture2D._generateGrayTexture = function (texture, rect, renderCanvas) {
+ if (texture === null)
+ return null;
+ renderCanvas = renderCanvas || document.createElement("canvas");
+ rect = rect || cc.rect(0, 0, texture.width, texture.height);
+ renderCanvas.width = rect.width;
+ renderCanvas.height = rect.height;
+
+ var context = renderCanvas.getContext("2d");
+ context.drawImage(texture, rect.x, rect.y, rect.width, rect.height, 0, 0, rect.width, rect.height);
+ var imgData = context.getImageData(0, 0, rect.width, rect.height);
+ var data = imgData.data;
+ for (var i = 0, len = data.length; i < len; i += 4) {
+ data[i] = data[i + 1] = data[i + 2] = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 * data[i + 2];
+ }
+ context.putImageData(imgData, 0, 0);
+ return renderCanvas;
+ };
+
+ } else if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ cc.assert(cc.isFunction(cc._tmp.WebGLTexture2D), cc._LogInfos.MissingFile, "TexturesWebGL.js");
+ cc._tmp.WebGLTexture2D();
+ delete cc._tmp.WebGLTexture2D;
+ }
+
+ cc.EventHelper.prototype.apply(cc.Texture2D.prototype);
+
+ cc.assert(cc.isFunction(cc._tmp.PrototypeTexture2D), cc._LogInfos.MissingFile, "TexturesPropertyDefine.js");
+ cc._tmp.PrototypeTexture2D();
+ delete cc._tmp.PrototypeTexture2D;
+});
diff --git a/cocos2d/textures/CCTextureAtlas.js b/cocos2d/core/textures/CCTextureAtlas.js
similarity index 66%
rename from cocos2d/textures/CCTextureAtlas.js
rename to cocos2d/core/textures/CCTextureAtlas.js
index 80179f824b..b996dc7f42 100644
--- a/cocos2d/textures/CCTextureAtlas.js
+++ b/cocos2d/core/textures/CCTextureAtlas.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -35,30 +35,57 @@
* The TextureAtlas capacity can be increased or decreased in runtime.
* @class
* @extends cc.Class
+ *
+ * @property {Boolean} dirty - Indicates whether or not the array buffer of the VBO needs to be updated.
+ * @property {Image} texture - Image texture for cc.TextureAtlas.
+ * @property {Number} capacity - <@readonly> Quantity of quads that can be stored with the current texture atlas size.
+ * @property {Number} totalQuads - <@readonly> Quantity of quads that are going to be drawn.
+ * @property {Array} quads - <@readonly> Quads that are going to be rendered
*/
-cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
- _indices:null,
+cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{ //WebGL only
+ dirty: false,
+ texture: null,
+
+ _indices: null,
//0: vertex 1: indices
- _buffersVBO:null,
- //indicates whether or not the array buffer of the VBO needs to be updated
- _dirty:false,
- _capacity:0,
- _texture:null,
-
- _quads:null,
- _quadsArrayBuffer:null,
- _quadsWebBuffer:null,
- _quadsReader:null,
-
- ctor:function () {
+ _buffersVBO: null,
+ _capacity: 0,
+
+ _quads: null,
+ _quadsArrayBuffer: null,
+ _quadsWebBuffer: null,
+ _quadsReader: null,
+
+ /**
+ * Creates a TextureAtlas with an filename and with an initial capacity for Quads.
+ * The TextureAtlas capacity can be increased in runtime.
+ * Constructor of cc.TextureAtlas
+ * @param {String|cc.Texture2D} fileName
+ * @param {Number} capacity
+ * @example
+ * 1.
+ * //creates a TextureAtlas with filename
+ * var textureAtlas = new cc.TextureAtlas("res/hello.png", 3);
+ * 2.
+ * //creates a TextureAtlas with texture
+ * var texture = cc.textureCache.addImage("hello.png");
+ * var textureAtlas = new cc.TextureAtlas(texture, 3);
+ */
+ ctor: function (fileName, capacity) {
this._buffersVBO = [];
+
+ if (cc.isString(fileName)) {
+ this.initWithFile(fileName, capacity);
+ } else if (fileName instanceof cc.Texture2D) {
+ this.initWithTexture(fileName, capacity);
+ }
},
/**
* Quantity of quads that are going to be drawn.
* @return {Number}
*/
- getTotalQuads:function () {
+ getTotalQuads: function () {
//return this._quads.length;
return this._totalQuads;
},
@@ -67,7 +94,7 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* Quantity of quads that can be stored with the current texture atlas size
* @return {Number}
*/
- getCapacity:function () {
+ getCapacity: function () {
return this._capacity;
},
@@ -75,54 +102,54 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* Texture of the texture atlas
* @return {Image}
*/
- getTexture:function () {
- return this._texture;
+ getTexture: function () {
+ return this.texture;
},
/**
* @param {Image} texture
*/
- setTexture:function (texture) {
- this._texture = texture;
+ setTexture: function (texture) {
+ this.texture = texture;
},
/**
* specify if the array buffer of the VBO needs to be updated
* @param {Boolean} dirty
*/
- setDirty:function (dirty) {
- this._dirty = dirty;
+ setDirty: function (dirty) {
+ this.dirty = dirty;
},
/**
* whether or not the array buffer of the VBO needs to be updated
* @returns {boolean}
*/
- isDirty:function () {
- return this._dirty;
+ isDirty: function () {
+ return this.dirty;
},
/**
* Quads that are going to be rendered
* @return {Array}
*/
- getQuads:function () {
+ getQuads: function () {
return this._quads;
},
/**
* @param {Array} quads
*/
- setQuads:function (quads) {
- this._quads = quads;
+ setQuads: function (quads) {
//TODO need re-binding
+ this._quads = quads;
},
- _copyQuadsToTextureAtlas:function(quads, index){
- if(!quads)
+ _copyQuadsToTextureAtlas: function (quads, index) {
+ if (!quads)
return;
- for(var i = 0; i < quads.length ; i++)
+ for (var i = 0; i < quads.length; i++)
this._setQuadToArray(quads[i], index + i);
},
@@ -142,11 +169,11 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* Description
* @return {String}
*/
- description:function () {
+ description: function () {
return '';
},
- _setupIndices:function () {
+ _setupIndices: function () {
if (this._capacity === 0)
return;
var locIndices = this._indices, locCapacity = this._capacity;
@@ -171,8 +198,8 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
}
},
- _setupVBO:function () {
- var gl = cc.renderContext;
+ _setupVBO: function () {
+ var gl = cc._renderContext;
//create WebGLBuffer
this._buffersVBO[0] = gl.createBuffer();
this._buffersVBO[1] = gl.createBuffer();
@@ -181,16 +208,14 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
this._mapBuffers();
},
- _mapBuffers:function () {
- var gl = cc.renderContext;
+ _mapBuffers: function () {
+ var gl = cc._renderContext;
gl.bindBuffer(gl.ARRAY_BUFFER, this._quadsWebBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
-
- //cc.CHECK_GL_ERROR_DEBUG();
},
/**
@@ -205,13 +230,13 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* var textureAtlas = new cc.TextureAtlas();
* textureAtlas.initWithTexture("hello.png", 3);
*/
- initWithFile:function (file, capacity) {
+ initWithFile: function (file, capacity) {
// retained in property
- var texture = cc.TextureCache.getInstance().addImage(file);
+ var texture = cc.textureCache.addImage(file);
if (texture)
return this.initWithTexture(texture, capacity);
else {
- cc.log("cocos2d: Could not open file: " + file);
+ cc.log(cc._LogInfos.TextureAtlas_initWithFile, file);
return false;
}
},
@@ -226,22 +251,21 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* @return {Boolean}
* @example
* //example
- * var texture = cc.TextureCache.getInstance().addImage("hello.png");
+ * var texture = cc.textureCache.addImage("hello.png");
* var textureAtlas = new cc.TextureAtlas();
* textureAtlas.initWithTexture(texture, 3);
*/
- initWithTexture:function (texture, capacity) {
- //cc.Assert(texture != null, "TextureAtlas.initWithTexture():texture should not be null");
+ initWithTexture: function (texture, capacity) {
+ cc.assert(texture, cc._LogInfos.TextureAtlas_initWithTexture);
+
capacity = 0 | (capacity);
this._capacity = capacity;
this._totalQuads = 0;
// retained in property
- this._texture = texture;
+ this.texture = texture;
// Re-initialization is not allowed
- cc.Assert(this._quads == null && this._indices == null, "TextureAtlas.initWithTexture():_quads and _indices should not be null");
-
this._quads = [];
this._indices = new Uint16Array(capacity * 6);
var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
@@ -252,50 +276,54 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
return false;
var locQuads = this._quads;
- for(var i = 0; i< capacity; i++)
- locQuads[i] =new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, i * quadSize);
+ for (var i = 0; i < capacity; i++)
+ locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, i * quadSize);
this._setupIndices();
this._setupVBO();
- this._dirty = true;
+ this.dirty = true;
return true;
},
/**
* Updates a Quad (texture, vertex and color) at a certain index
* index must be between 0 and the atlas capacity - 1
- * @param {cc.V2F_C4B_T2F_Quad} quad
+ * @param {cc.V3F_C4B_T2F_Quad} quad
* @param {Number} index
*/
- updateQuad:function (quad, index) {
- //cc.Assert(index >= 0 && index < this._capacity, "updateQuadWithTexture: Invalid index");
+ updateQuad: function (quad, index) {
+ cc.assert(quad, cc._LogInfos.TextureAtlas_updateQuad);
+ cc.assert(index >= 0 && index < this._capacity, cc._LogInfos.TextureAtlas_updateQuad_2);
+
this._totalQuads = Math.max(index + 1, this._totalQuads);
this._setQuadToArray(quad, index);
- this._dirty = true;
+ this.dirty = true;
},
/**
* Inserts a Quad (texture, vertex and color) at a certain index
* index must be between 0 and the atlas capacity - 1
- * @param {cc.V2F_C4B_T2F_Quad} quad
+ * @param {cc.V3F_C4B_T2F_Quad} quad
* @param {Number} index
*/
- insertQuad:function (quad, index) {
- cc.Assert(index < this._capacity, "insertQuadWithTexture: Invalid index");
+ insertQuad: function (quad, index) {
+ cc.assert(index < this._capacity, cc._LogInfos.TextureAtlas_insertQuad_2);
this._totalQuads++;
- cc.Assert(this._totalQuads <= this._capacity, "invalid totalQuads");
-
+ if (this._totalQuads > this._capacity) {
+ cc.log(cc._LogInfos.TextureAtlas_insertQuad);
+ return;
+ }
var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
// issue #575. index can be > totalQuads
- var remaining = (this._totalQuads-1) - index;
+ var remaining = (this._totalQuads - 1) - index;
var startOffset = index * quadSize;
var moveLength = remaining * quadSize;
- this._quads[this._totalQuads -1] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads -1) * quadSize);
+ this._quads[this._totalQuads - 1] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads - 1) * quadSize);
this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize);
this._setQuadToArray(quad, index);
- this._dirty = true;
+ this.dirty = true;
},
/**
@@ -308,28 +336,32 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* @param {Number} index
* @param {Number} amount
*/
- insertQuads:function (quads, index, amount) {
+ insertQuads: function (quads, index, amount) {
amount = amount || quads.length;
- var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
- cc.Assert(index + amount <= this._capacity, "insertQuadWithTexture: Invalid index + amount");
+ cc.assert((index + amount) <= this._capacity, cc._LogInfos.TextureAtlas_insertQuads);
+
+ var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
this._totalQuads += amount;
- cc.Assert(this._totalQuads <= this._capacity, "invalid totalQuads");
+ if (this._totalQuads > this._capacity) {
+ cc.log(cc._LogInfos.TextureAtlas_insertQuad);
+ return;
+ }
// issue #575. index can be > totalQuads
- var remaining = (this._totalQuads-1) - index - amount;
+ var remaining = (this._totalQuads - 1) - index - amount;
var startOffset = index * quadSize;
var moveLength = remaining * quadSize;
- var lastIndex = (this._totalQuads-1) - amount;
+ var lastIndex = (this._totalQuads - 1) - amount;
var i;
- for(i = 0; i < amount;i++)
- this._quads[lastIndex + i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads -1) * quadSize);
+ for (i = 0; i < amount; i++)
+ this._quads[lastIndex + i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, (this._totalQuads - 1) * quadSize);
this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize * amount);
- for(i = 0; i < amount; i++)
+ for (i = 0; i < amount; i++)
this._setQuadToArray(quads[i], index + i);
- this._dirty = true;
+ this.dirty = true;
},
/**
@@ -338,28 +370,30 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* @param {Number} fromIndex
* @param {Number} newIndex
*/
- insertQuadFromIndex:function (fromIndex, newIndex) {
- cc.Assert(newIndex >= 0 && newIndex < this._totalQuads, "insertQuadFromIndex:atIndex: Invalid index");
- cc.Assert(fromIndex >= 0 && fromIndex < this._totalQuads, "insertQuadFromIndex:atIndex: Invalid index");
+ insertQuadFromIndex: function (fromIndex, newIndex) {
if (fromIndex === newIndex)
return;
+ cc.assert(newIndex >= 0 || newIndex < this._totalQuads, cc._LogInfos.TextureAtlas_insertQuadFromIndex);
+
+ cc.assert(fromIndex >= 0 || fromIndex < this._totalQuads, cc._LogInfos.TextureAtlas_insertQuadFromIndex_2);
+
var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
var locQuadsReader = this._quadsReader;
- var sourceArr = locQuadsReader.subarray(fromIndex * quadSize,quadSize);
+ var sourceArr = locQuadsReader.subarray(fromIndex * quadSize, quadSize);
var startOffset, moveLength;
- if(fromIndex > newIndex){
+ if (fromIndex > newIndex) {
startOffset = newIndex * quadSize;
moveLength = (fromIndex - newIndex) * quadSize;
- locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength),startOffset + quadSize);
- locQuadsReader.set(sourceArr,startOffset);
- }else{
+ locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength), startOffset + quadSize);
+ locQuadsReader.set(sourceArr, startOffset);
+ } else {
startOffset = (fromIndex + 1) * quadSize;
moveLength = (newIndex - fromIndex) * quadSize;
- locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength),startOffset - quadSize);
+ locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength), startOffset - quadSize);
locQuadsReader.set(sourceArr, newIndex * quadSize);
}
- this._dirty = true;
+ this.dirty = true;
},
/**
@@ -367,33 +401,40 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* The capacity remains the same, but the total number of quads to be drawn is reduced in 1
* @param {Number} index
*/
- removeQuadAtIndex:function (index) {
- cc.Assert(index < this._totalQuads, "removeQuadAtIndex: Invalid index");
+ removeQuadAtIndex: function (index) {
+ cc.assert(index < this._totalQuads, cc._LogInfos.TextureAtlas_removeQuadAtIndex);
+
var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
this._totalQuads--;
this._quads.length = this._totalQuads;
- if(index !== this._totalQuads){
+ if (index !== this._totalQuads) {
//move data
var startOffset = (index + 1) * quadSize;
var moveLength = (this._totalQuads - index) * quadSize;
this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength), startOffset - quadSize);
}
- this._dirty = true;
+ this.dirty = true;
},
- removeQuadsAtIndex:function (index, amount) {
- cc.Assert(index + amount <= this._totalQuads, "removeQuadAtIndex: index + amount out of bounds");
+ /**
+ * Removes a given number of quads at a given index
+ * @param {Number} index
+ * @param {Number} amount
+ */
+ removeQuadsAtIndex: function (index, amount) {
+ cc.assert(index + amount <= this._totalQuads, cc._LogInfos.TextureAtlas_removeQuadsAtIndex);
+
this._totalQuads -= amount;
- if(index !== this._totalQuads){
+ if (index !== this._totalQuads) {
//move data
var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
var srcOffset = (index + amount) * quadSize;
var moveLength = (this._totalQuads - index) * quadSize;
var dstOffset = index * quadSize;
- this._quadsReader.set(this._quadsReader.subarray(srcOffset,srcOffset + moveLength),dstOffset);
+ this._quadsReader.set(this._quadsReader.subarray(srcOffset, srcOffset + moveLength), dstOffset);
}
- this._dirty = true;
+ this.dirty = true;
},
/**
@@ -401,13 +442,13 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* The TextureAtlas capacity remains untouched. No memory is freed.
* The total number of quads to be drawn will be 0
*/
- removeAllQuads:function () {
+ removeAllQuads: function () {
this._quads.length = 0;
this._totalQuads = 0;
},
- _setDirty:function(dirty){
- this._dirty = dirty;
+ _setDirty: function (dirty) {
+ this.dirty = dirty;
},
/**
@@ -419,8 +460,8 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* @param {Number} newCapacity
* @return {Boolean}
*/
- resizeCapacity:function (newCapacity) {
- if (newCapacity == this._capacity)
+ resizeCapacity: function (newCapacity) {
+ if (newCapacity === this._capacity)
return true;
var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
@@ -430,23 +471,23 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
this._capacity = 0 | newCapacity;
var i, capacity = this._capacity, locTotalQuads = this._totalQuads;
- if (this._quads == null) {
+ if (this._quads === null) {
this._quads = [];
this._quadsArrayBuffer = new ArrayBuffer(quadSize * capacity);
this._quadsReader = new Uint8Array(this._quadsArrayBuffer);
- for(i = 0; i< capacity; i++)
- this._quads = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer,i * quadSize);
+ for (i = 0; i < capacity; i++)
+ this._quads = new cc.V3F_C4B_T2F_Quad(null, null, null, null, this._quadsArrayBuffer, i * quadSize);
} else {
var newQuads, newArrayBuffer, quads = this._quads;
if (capacity > oldCapacity) {
newQuads = [];
newArrayBuffer = new ArrayBuffer(quadSize * capacity);
- for(i = 0; i < locTotalQuads;i++){
- newQuads[i] = new cc.V3F_C4B_T2F_Quad(quads[i].tl,quads[i].bl,quads[i].tr,quads[i].br,
- newArrayBuffer,i * quadSize);
+ for (i = 0; i < locTotalQuads; i++) {
+ newQuads[i] = new cc.V3F_C4B_T2F_Quad(quads[i].tl, quads[i].bl, quads[i].tr, quads[i].br,
+ newArrayBuffer, i * quadSize);
}
- for(;i oldCapacity) {
@@ -479,7 +520,7 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
this._setupIndices();
this._mapBuffers();
- this._dirty = true;
+ this.dirty = true;
return true;
},
@@ -488,7 +529,7 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* don't use this unless you know what you're doing
* @param {Number} amount
*/
- increaseTotalQuadsWith:function (amount) {
+ increaseTotalQuadsWith: function (amount) {
this._totalQuads += amount;
},
@@ -499,17 +540,19 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* @param {Number} newIndex
*/
moveQuadsFromIndex: function (oldIndex, amount, newIndex) {
- if (arguments.length == 2) {
+ if (newIndex === undefined) {
newIndex = amount;
amount = this._totalQuads - oldIndex;
- cc.Assert(newIndex + (this._totalQuads - oldIndex) <= this._capacity, "moveQuadsFromIndex move is out of bounds");
- if(amount === 0)
+
+ cc.assert((newIndex + (this._totalQuads - oldIndex)) <= this._capacity, cc._LogInfos.TextureAtlas_moveQuadsFromIndex);
+
+ if (amount === 0)
return;
- }else{
- cc.Assert(newIndex + amount <= this._totalQuads, "moveQuadsFromIndex:newIndex: Invalid index");
- cc.Assert(oldIndex < this._totalQuads, "moveQuadsFromIndex:oldIndex: Invalid index");
+ } else {
+ cc.assert((newIndex + amount) <= this._totalQuads, cc._LogInfos.TextureAtlas_moveQuadsFromIndex_2);
+ cc.assert(oldIndex < this._totalQuads, cc._LogInfos.TextureAtlas_moveQuadsFromIndex_3);
- if (oldIndex == newIndex)
+ if (oldIndex === newIndex)
return;
}
@@ -530,7 +573,7 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
locQuadsReader.set(locQuadsReader.subarray(moveStart, moveStart + moveLength), srcOffset);
}
locQuadsReader.set(sourceArr, dstOffset);
- this._dirty = true;
+ this.dirty = true;
},
/**
@@ -539,7 +582,7 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
* @param {Number} index
* @param {Number} amount
*/
- fillWithEmptyQuadsFromIndex:function (index, amount) {
+ fillWithEmptyQuadsFromIndex: function (index, amount) {
var count = amount * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
var clearReader = new Uint8Array(this._quadsArrayBuffer, index * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT, count);
for (var i = 0; i < count; i++)
@@ -548,59 +591,15 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
// TextureAtlas - Drawing
- /**
- * Draws n quads from an index (offset).
- * n + start can't be greater than the capacity of the atlas
- * @param {Number} n
- * @param {Number} start
- */
- drawNumberOfQuads:function (n, start) {
- start = start || 0;
- if (0 === n || !this._texture || !this._texture.isLoaded())
- return;
-
- var gl = cc.renderContext;
- cc.glBindTexture2D(this._texture);
-
- //
- // Using VBO without VAO
- //
- //vertices
- //gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
- // XXX: update is done in draw... perhaps it should be done in a timer
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX);
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this._quadsWebBuffer);
- if (this._dirty)
- gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
-
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); // vertices
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); // colors
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16); // tex coords
-
- if (this._dirty)
- this._dirty = false;
-
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
-
- if (cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP)
- gl.drawElements(gl.TRIANGLE_STRIP, n * 6, gl.UNSIGNED_SHORT, start * 6 * this._indices.BYTES_PER_ELEMENT);
- else
- gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, start * 6 * this._indices.BYTES_PER_ELEMENT);
-
- cc.g_NumberOfDraws++;
- //cc.CHECK_GL_ERROR_DEBUG();
- },
-
/**
* Draws all the Atlas's Quads
*/
- drawQuads:function () {
+ drawQuads: function () {
this.drawNumberOfQuads(this._totalQuads, 0);
},
_releaseBuffer: function () {
- var gl = cc.renderContext;
+ var gl = cc._renderContext;
if (this._buffersVBO) {
if (this._buffersVBO[0])
gl.deleteBuffer(this._buffersVBO[0]);
@@ -612,37 +611,45 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{
}
});
+var _p = cc.TextureAtlas.prototype;
+
+// Extended properties
+/** @expose */
+_p.totalQuads;
+cc.defineGetterSetter(_p, "totalQuads", _p.getTotalQuads);
+/** @expose */
+_p.capacity;
+cc.defineGetterSetter(_p, "capacity", _p.getCapacity);
+/** @expose */
+_p.quads;
+cc.defineGetterSetter(_p, "quads", _p.getQuads, _p.setQuads);
+
/**
* Creates a TextureAtlas with an filename and with an initial capacity for Quads.
* The TextureAtlas capacity can be increased in runtime.
- * @param {String} file
+ * @deprecated since v3.0, please use new cc.TextureAtlas(fileName, capacity) instead
+ * @param {String|cc.Texture2D} fileName
* @param {Number} capacity
* @return {cc.TextureAtlas|Null}
- * @example
- * //example
- * var textureAtlas = cc.TextureAtlas.create("hello.png", 3);
*/
-cc.TextureAtlas.create = function (file, capacity) {
- var textureAtlas = new cc.TextureAtlas();
- if (textureAtlas && textureAtlas.initWithFile(file, capacity))
- return textureAtlas;
- return null;
+cc.TextureAtlas.create = function (fileName, capacity) {
+ return new cc.TextureAtlas(fileName, capacity);
};
/**
- * Creates a TextureAtlas with a previously initialized Texture2D object, and with an initial capacity for n Quads.
- * The TextureAtlas capacity can be increased in runtime.
- * @param {Image|cc.Texture2D} texture
- * @param {Number} capacity
- * @return {cc.TextureAtlas}
- * @example
- * //example
- * var texture = cc.TextureCache.getInstance().addImage("hello.png");
- * var textureAtlas = cc.TextureAtlas.createWithTexture(texture, 3);
+ * @deprecated since v3.0, please use new cc.TextureAtlas(texture) instead
+ * @function
*/
-cc.TextureAtlas.createWithTexture = function (texture, capacity) {
- var textureAtlas = new cc.TextureAtlas();
- if (textureAtlas && textureAtlas.initWithTexture(texture, capacity))
- return textureAtlas;
- return null;
-};
+cc.TextureAtlas.createWithTexture = cc.TextureAtlas.create;
+
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ cc.assert(cc.isFunction(cc._tmp.WebGLTextureAtlas), cc._LogInfos.MissingFile, "TexturesWebGL.js");
+ cc._tmp.WebGLTextureAtlas();
+ delete cc._tmp.WebGLTextureAtlas;
+ }
+});
+
+cc.assert(cc.isFunction(cc._tmp.PrototypeTextureAtlas), cc._LogInfos.MissingFile, "TexturesPropertyDefine.js");
+cc._tmp.PrototypeTextureAtlas();
+delete cc._tmp.PrototypeTextureAtlas;
diff --git a/cocos2d/core/textures/CCTextureCache.js b/cocos2d/core/textures/CCTextureCache.js
new file mode 100644
index 0000000000..5e59c2f83c
--- /dev/null
+++ b/cocos2d/core/textures/CCTextureCache.js
@@ -0,0 +1,385 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.textureCache is a singleton object, it's the global cache for cc.Texture2D
+ * @class
+ * @name cc.textureCache
+ */
+cc.textureCache = /** @lends cc.textureCache# */{
+ _textures: {},
+ _textureColorsCache: {},
+ _textureKeySeq: (0 | Math.random() * 1000),
+
+ _loadedTexturesBefore: {},
+
+ //handleLoadedTexture move to Canvas/WebGL
+
+ _initializingRenderer: function () {
+ var selPath;
+ //init texture from _loadedTexturesBefore
+ var locLoadedTexturesBefore = this._loadedTexturesBefore, locTextures = this._textures;
+ for (selPath in locLoadedTexturesBefore) {
+ var tex2d = locLoadedTexturesBefore[selPath];
+ tex2d.handleLoadedTexture();
+ locTextures[selPath] = tex2d;
+ }
+ this._loadedTexturesBefore = {};
+ },
+
+ /**
+ *
+ * Returns a Texture2D object given an PVR filename
+ * If the file image was not previously loaded, it will create a new CCTexture2D
+ * object and it will return it. Otherwise it will return a reference of a previously loaded image
+ * note: AddPVRTCImage does not support on HTML5
+ *
+ * @param {String} filename
+ * @return {cc.Texture2D}
+ */
+ addPVRTCImage: function (filename) {
+ cc.log(cc._LogInfos.textureCache_addPVRTCImage);
+ },
+
+ /**
+ *
+ * Returns a Texture2D object given an ETC filename
+ * If the file image was not previously loaded, it will create a new CCTexture2D
+ * object and it will return it. Otherwise it will return a reference of a previously loaded image
+ * note:addETCImage does not support on HTML5
+ *
+ * @param {String} filename
+ * @return {cc.Texture2D}
+ */
+ addETCImage: function (filename) {
+ cc.log(cc._LogInfos.textureCache_addETCImage);
+ },
+
+ /**
+ * Description
+ * @return {String}
+ */
+ description: function () {
+ return "";
+ },
+
+ /**
+ * Returns an already created texture. Returns null if the texture doesn't exist.
+ * @param {String} textureKeyName
+ * @return {cc.Texture2D|Null}
+ * @deprecated
+ * @example
+ * //example
+ * var key = cc.textureCache.textureForKey("hello.png");
+ */
+ textureForKey: function (textureKeyName) {
+ cc.log(cc._LogInfos.textureCache_textureForKey);
+ return this.getTextureForKey(textureKeyName);
+ },
+
+ /**
+ * Returns an already created texture. Returns null if the texture doesn't exist.
+ * @param {String} textureKeyName
+ * @return {cc.Texture2D|Null}
+ * @example
+ * //example
+ * var key = cc.textureCache.getTextureForKey("hello.png");
+ */
+ getTextureForKey: function (textureKeyName) {
+ return this._textures[textureKeyName] || this._textures[cc.loader._getAliase(textureKeyName)];
+ },
+
+ /**
+ * @param {Image} texture
+ * @return {String|Null}
+ * @example
+ * //example
+ * var key = cc.textureCache.getKeyByTexture(texture);
+ */
+ getKeyByTexture: function (texture) {
+ for (var key in this._textures) {
+ if (this._textures[key] === texture) {
+ return key;
+ }
+ }
+ return null;
+ },
+
+ _generalTextureKey: function (id) {
+ return "_textureKey_" + id;
+ },
+
+ /**
+ * @param {Image} texture
+ * @return {Array}
+ * @example
+ * //example
+ * var cacheTextureForColor = cc.textureCache.getTextureColors(texture);
+ */
+ getTextureColors: function (texture) {
+ var image = texture._htmlElementObj;
+ var key = this.getKeyByTexture(image);
+ if (!key) {
+ if (image instanceof HTMLImageElement)
+ key = image.src;
+ else
+ key = this._generalTextureKey(texture.__instanceId);
+ }
+
+ if (!this._textureColorsCache[key])
+ this._textureColorsCache[key] = texture._generateTextureCacheForColor();
+ return this._textureColorsCache[key];
+ },
+
+ /**
+ * Returns a Texture2D object given an PVR filename
+ * If the file image was not previously loaded, it will create a new Texture2D
+ * object and it will return it. Otherwise it will return a reference of a previously loaded image
+ * @param {String} path
+ * @return {cc.Texture2D}
+ */
+ addPVRImage: function (path) {
+ cc.log(cc._LogInfos.textureCache_addPVRImage);
+ },
+
+ /**
+ * Purges the dictionary of loaded textures.
+ * Call this method if you receive the "Memory Warning"
+ * In the short term: it will free some resources preventing your app from being killed
+ * In the medium term: it will allocate more resources
+ * In the long term: it will be the same
+ * @example
+ * //example
+ * cc.textureCache.removeAllTextures();
+ */
+ removeAllTextures: function () {
+ var locTextures = this._textures;
+ for (var selKey in locTextures) {
+ if (locTextures[selKey])
+ locTextures[selKey].releaseTexture();
+ }
+ this._textures = {};
+ },
+
+ /**
+ * Deletes a texture from the cache given a texture
+ * @param {Image} texture
+ * @example
+ * //example
+ * cc.textureCache.removeTexture(texture);
+ */
+ removeTexture: function (texture) {
+ if (!texture)
+ return;
+
+ var locTextures = this._textures;
+ for (var selKey in locTextures) {
+ if (locTextures[selKey] === texture) {
+ locTextures[selKey].releaseTexture();
+ delete(locTextures[selKey]);
+ }
+ }
+ },
+
+ /**
+ * Deletes a texture from the cache given a its key name
+ * @param {String} textureKeyName
+ * @example
+ * //example
+ * cc.textureCache.removeTexture("hello.png");
+ */
+ removeTextureForKey: function (textureKeyName) {
+ if (textureKeyName == null)
+ return;
+ var tex = this._textures[textureKeyName];
+ if (tex) {
+ tex.releaseTexture();
+ delete(this._textures[textureKeyName]);
+ }
+ },
+
+ //addImage move to Canvas/WebGL
+
+ /**
+ * Cache the image data
+ * @param {String} path
+ * @param {Image|HTMLImageElement|HTMLCanvasElement} texture
+ */
+ cacheImage: function (path, texture) {
+ if (texture instanceof cc.Texture2D) {
+ this._textures[path] = texture;
+ return;
+ }
+ var texture2d = new cc.Texture2D();
+ texture2d.initWithElement(texture);
+ texture2d.handleLoadedTexture();
+ this._textures[path] = texture2d;
+ },
+
+ /**
+ * Returns a Texture2D object given an UIImage image
+ * If the image was not previously loaded, it will create a new Texture2D object and it will return it.
+ * Otherwise it will return a reference of a previously loaded image
+ * The "key" parameter will be used as the "key" for the cache.
+ * If "key" is null, then a new texture will be created each time.
+ * @param {HTMLImageElement|HTMLCanvasElement} image
+ * @param {String} key
+ * @return {cc.Texture2D}
+ */
+ addUIImage: function (image, key) {
+ cc.assert(image, cc._LogInfos.textureCache_addUIImage_2);
+
+ if (key) {
+ if (this._textures[key])
+ return this._textures[key];
+ }
+
+ // prevents overloading the autorelease pool
+ var texture = new cc.Texture2D();
+ texture.initWithImage(image);
+ if (key != null)
+ this._textures[key] = texture;
+ else
+ cc.log(cc._LogInfos.textureCache_addUIImage);
+ return texture;
+ },
+
+ /**
+ * Output to cc.log the current contents of this TextureCache
+ * This will attempt to calculate the size of each texture, and the total texture memory in use.
+ */
+ dumpCachedTextureInfo: function () {
+ var count = 0;
+ var totalBytes = 0, locTextures = this._textures;
+
+ for (var key in locTextures) {
+ var selTexture = locTextures[key];
+ count++;
+ if (selTexture.getHtmlElementObj() instanceof HTMLImageElement)
+ cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo, key, selTexture.getHtmlElementObj().src, selTexture.getPixelsWide(), selTexture.getPixelsHigh());
+ else {
+ cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selTexture.getPixelsWide(), selTexture.getPixelsHigh());
+ }
+ totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4;
+ }
+
+ var locTextureColorsCache = this._textureColorsCache;
+ for (key in locTextureColorsCache) {
+ var selCanvasColorsArr = locTextureColorsCache[key];
+ for (var selCanvasKey in selCanvasColorsArr) {
+ var selCanvas = selCanvasColorsArr[selCanvasKey];
+ count++;
+ cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selCanvas.width, selCanvas.height);
+ totalBytes += selCanvas.width * selCanvas.height * 4;
+ }
+
+ }
+ cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_3, count, totalBytes / 1024, (totalBytes / (1024.0 * 1024.0)).toFixed(2));
+ },
+
+ _clear: function () {
+ this._textures = {};
+ this._textureColorsCache = {};
+ this._textureKeySeq = (0 | Math.random() * 1000);
+ this._loadedTexturesBefore = {};
+ }
+};
+
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+
+ var _p = cc.textureCache;
+
+ _p.handleLoadedTexture = function (url, img) {
+ var locTexs = this._textures;
+ //remove judge
+ var tex = locTexs[url];
+ if (!tex) {
+ tex = locTexs[url] = new cc.Texture2D();
+ tex.url = url;
+ }
+ tex.initWithElement(img);
+ tex.handleLoadedTexture();
+ return tex;
+ };
+
+ /**
+ * Returns a Texture2D object given an file image
+ * If the file image was not previously loaded, it will create a new Texture2D
+ * object and it will return it. It will use the filename as a key.
+ * Otherwise it will return a reference of a previously loaded image.
+ * Supported image extensions: .png, .jpg, .gif
+ * @param {String} url
+ * @param {Function} cb
+ * @param {Object} target
+ * @return {cc.Texture2D}
+ * @example
+ * //example
+ * cc.textureCache.addImage("hello.png");
+ */
+ _p.addImage = function (url, cb, target) {
+
+ cc.assert(url, cc._LogInfos.Texture2D_addImage);
+
+ var locTexs = this._textures;
+ //remove judge
+ var tex = locTexs[url] || locTexs[cc.loader._getAliase(url)];
+ if (tex) {
+ if (tex.isLoaded()) {
+ cb && cb.call(target, tex);
+ return tex;
+ }
+ else {
+ tex.addEventListener("load", function () {
+ cb && cb.call(target, tex);
+ }, target);
+ return tex;
+ }
+ }
+
+ tex = locTexs[url] = new cc.Texture2D();
+ tex.url = url;
+ var basePath = cc.loader.getBasePath ? cc.loader.getBasePath() : cc.loader.resPath;
+ cc.loader.loadImg(cc.path.join(basePath || "", url), function (err, img) {
+ if (err)
+ return cb && cb.call(target, err);
+
+ var texResult = cc.textureCache.handleLoadedTexture(url, img);
+ cb && cb.call(target, texResult);
+ });
+
+ return tex;
+ };
+
+ _p.addImageAsync = _p.addImage;
+ _p = null;
+
+ } else if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ cc.assert(cc.isFunction(cc._tmp.WebGLTextureCache), cc._LogInfos.MissingFile, "TexturesWebGL.js");
+ cc._tmp.WebGLTextureCache();
+ delete cc._tmp.WebGLTextureCache;
+ }
+});
diff --git a/cocos2d/core/textures/TexturesPropertyDefine.js b/cocos2d/core/textures/TexturesPropertyDefine.js
new file mode 100644
index 0000000000..518a5f5139
--- /dev/null
+++ b/cocos2d/core/textures/TexturesPropertyDefine.js
@@ -0,0 +1,228 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc._tmp.PrototypeTexture2D = function () {
+
+ var _c = cc.Texture2D;
+
+ /**
+ *
+ * treats (or not) PVR files as if they have alpha premultiplied.
+ * Since it is impossible to know at runtime if the PVR images have the alpha channel premultiplied, it is
+ * possible load them as if they have (or not) the alpha channel premultiplied.
+ *
+ * By default it is disabled.
+ *
+ * @param haveAlphaPremultiplied
+ */
+ _c.PVRImagesHavePremultipliedAlpha = function (haveAlphaPremultiplied) {
+ cc.PVRHaveAlphaPremultiplied_ = haveAlphaPremultiplied;
+ };
+
+ /**
+ * 32-bit texture: RGBA8888
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_RGBA8888
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_RGBA8888 = 2;
+
+ /**
+ * 24-bit texture: RGBA888
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_RGB888
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_RGB888 = 3;
+
+ /**
+ * 16-bit texture without Alpha channel
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_RGB565
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_RGB565 = 4;
+
+ /**
+ * 8-bit textures used as masks
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_A8
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_A8 = 5;
+
+ /**
+ * 8-bit intensity texture
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_I8
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_I8 = 6;
+
+ /**
+ * 16-bit textures used as masks
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_AI88
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_AI88 = 7;
+
+ /**
+ * 16-bit textures: RGBA4444
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_RGBA4444
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_RGBA4444 = 8;
+
+ /**
+ * 16-bit textures: RGB5A1
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_RGB5A1
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_RGB5A1 = 7;
+
+ /**
+ * 4-bit PVRTC-compressed texture: PVRTC4
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_PVRTC4
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_PVRTC4 = 9;
+
+ /**
+ * 2-bit PVRTC-compressed texture: PVRTC2
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_PVRTC2
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_PVRTC2 = 10;
+
+ /**
+ * Default texture format: RGBA8888
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_DEFAULT
+ * @static
+ * @constant
+ * @type {Number}
+ */
+ _c.PIXEL_FORMAT_DEFAULT = _c.PIXEL_FORMAT_RGBA8888;
+
+ /**
+ * The default pixel format
+ * @memberOf cc.Texture2D
+ * @name PIXEL_FORMAT_PVRTC2
+ * @static
+ * @type {Number}
+ */
+ _c.defaultPixelFormat = _c.PIXEL_FORMAT_DEFAULT;
+
+ var _M = cc.Texture2D._M = {};
+ _M[_c.PIXEL_FORMAT_RGBA8888] = "RGBA8888";
+ _M[_c.PIXEL_FORMAT_RGB888] = "RGB888";
+ _M[_c.PIXEL_FORMAT_RGB565] = "RGB565";
+ _M[_c.PIXEL_FORMAT_A8] = "A8";
+ _M[_c.PIXEL_FORMAT_I8] = "I8";
+ _M[_c.PIXEL_FORMAT_AI88] = "AI88";
+ _M[_c.PIXEL_FORMAT_RGBA4444] = "RGBA4444";
+ _M[_c.PIXEL_FORMAT_RGB5A1] = "RGB5A1";
+ _M[_c.PIXEL_FORMAT_PVRTC4] = "PVRTC4";
+ _M[_c.PIXEL_FORMAT_PVRTC2] = "PVRTC2";
+
+ var _B = cc.Texture2D._B = {};
+ _B[_c.PIXEL_FORMAT_RGBA8888] = 32;
+ _B[_c.PIXEL_FORMAT_RGB888] = 24;
+ _B[_c.PIXEL_FORMAT_RGB565] = 16;
+ _B[_c.PIXEL_FORMAT_A8] = 8;
+ _B[_c.PIXEL_FORMAT_I8] = 8;
+ _B[_c.PIXEL_FORMAT_AI88] = 16;
+ _B[_c.PIXEL_FORMAT_RGBA4444] = 16;
+ _B[_c.PIXEL_FORMAT_RGB5A1] = 16;
+ _B[_c.PIXEL_FORMAT_PVRTC4] = 4;
+ _B[_c.PIXEL_FORMAT_PVRTC2] = 3;
+
+ var _p = cc.Texture2D.prototype;
+
+ // Extended properties
+ /** @expose */
+ _p.name;
+ cc.defineGetterSetter(_p, "name", _p.getName);
+ /** @expose */
+ _p.pixelFormat;
+ cc.defineGetterSetter(_p, "pixelFormat", _p.getPixelFormat);
+ /** @expose */
+ _p.pixelsWidth;
+ cc.defineGetterSetter(_p, "pixelsWidth", _p.getPixelsWide);
+ /** @expose */
+ _p.pixelsHeight;
+ cc.defineGetterSetter(_p, "pixelsHeight", _p.getPixelsHigh);
+ //cc.defineGetterSetter(_p, "size", _p.getContentSize, _p.setContentSize);
+ /** @expose */
+ _p.width;
+ cc.defineGetterSetter(_p, "width", _p._getWidth);
+ /** @expose */
+ _p.height;
+ cc.defineGetterSetter(_p, "height", _p._getHeight);
+};
+
+cc._tmp.PrototypeTextureAtlas = function () {
+
+ var _p = cc.TextureAtlas.prototype;
+
+ // Extended properties
+ /** @expose */
+ _p.totalQuads;
+ cc.defineGetterSetter(_p, "totalQuads", _p.getTotalQuads);
+ /** @expose */
+ _p.capacity;
+ cc.defineGetterSetter(_p, "capacity", _p.getCapacity);
+ /** @expose */
+ _p.quads;
+ cc.defineGetterSetter(_p, "quads", _p.getQuads, _p.setQuads);
+
+};
+
diff --git a/cocos2d/core/textures/TexturesWebGL.js b/cocos2d/core/textures/TexturesWebGL.js
new file mode 100644
index 0000000000..2dfe145e56
--- /dev/null
+++ b/cocos2d/core/textures/TexturesWebGL.js
@@ -0,0 +1,932 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc._tmp.WebGLTexture2D = function () {
+
+ /**
+ *
+ * This class allows to easily create OpenGL or Canvas 2D textures from images, text or raw data.
+ * The created cc.Texture2D object will always have power-of-two dimensions.
+ * Depending on how you create the cc.Texture2D object, the actual image area of the texture might be smaller than the texture dimensions
+ * i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).
+ * Be aware that the content of the generated textures will be upside-down!
+ * @name cc.Texture2D
+ * @class
+ * @extends cc.Class
+ *
+ * @property {WebGLTexture} name - <@readonly> WebGLTexture Object
+ * @property {Number} pixelFormat - <@readonly> Pixel format of the texture
+ * @property {Number} pixelsWidth - <@readonly> Width in pixels
+ * @property {Number} pixelsHeight - <@readonly> Height in pixels
+ * @property {Number} width - Content width in points
+ * @property {Number} height - Content height in points
+ * @property {cc.GLProgram} shaderProgram - The shader program used by drawAtPoint and drawInRect
+ * @property {Number} maxS - Texture max S
+ * @property {Number} maxT - Texture max T
+ */
+ //Original : Texture2DWebGL
+ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{
+ // By default PVR images are treated as if they don't have the alpha channel premultiplied
+ _pVRHaveAlphaPremultiplied: true,
+ _pixelFormat: null,
+ _pixelsWide: 0,
+ _pixelsHigh: 0,
+ _name: "",
+ _contentSize: null,
+ maxS: 0,
+ maxT: 0,
+ _hasPremultipliedAlpha: false,
+ _hasMipmaps: false,
+
+ shaderProgram: null,
+
+ _textureLoaded: false,
+ _htmlElementObj: null,
+ _webTextureObj: null,
+
+ url: null,
+
+ /**
+ * constructor of cc.Texture2D
+ */
+ ctor: function () {
+ this._contentSize = cc.size(0, 0);
+ this._pixelFormat = cc.Texture2D.defaultPixelFormat;
+ },
+
+ /**
+ * release texture
+ */
+ releaseTexture: function () {
+ if (this._webTextureObj)
+ cc._renderContext.deleteTexture(this._webTextureObj);
+ this._htmlElementObj = null;
+ cc.loader.release(this.url);
+ },
+
+ /**
+ * pixel format of the texture
+ * @return {Number}
+ */
+ getPixelFormat: function () {
+ return this._pixelFormat;
+ },
+
+ /**
+ * width in pixels
+ * @return {Number}
+ */
+ getPixelsWide: function () {
+ return this._pixelsWide;
+ },
+
+ /**
+ * height in pixels
+ * @return {Number}
+ */
+ getPixelsHigh: function () {
+ return this._pixelsHigh;
+ },
+
+ /**
+ * get WebGLTexture Object
+ * @return {WebGLTexture}
+ */
+ getName: function () {
+ return this._webTextureObj;
+ },
+
+ /**
+ * content size
+ * @return {cc.Size}
+ */
+ getContentSize: function () {
+ return cc.size(this._contentSize.width / cc.contentScaleFactor(), this._contentSize.height / cc.contentScaleFactor());
+ },
+
+ _getWidth: function () {
+ return this._contentSize.width / cc.contentScaleFactor();
+ },
+ _getHeight: function () {
+ return this._contentSize.height / cc.contentScaleFactor();
+ },
+
+ /**
+ * get content size in pixels
+ * @return {cc.Size}
+ */
+ getContentSizeInPixels: function () {
+ return this._contentSize;
+ },
+
+ /**
+ * texture max S
+ * @return {Number}
+ */
+ getMaxS: function () {
+ return this.maxS;
+ },
+
+ /**
+ * set texture max S
+ * @param {Number} maxS
+ */
+ setMaxS: function (maxS) {
+ this.maxS = maxS;
+ },
+
+ /**
+ * get texture max T
+ * @return {Number}
+ */
+ getMaxT: function () {
+ return this.maxT;
+ },
+
+ /**
+ * set texture max T
+ * @param {Number} maxT
+ */
+ setMaxT: function (maxT) {
+ this.maxT = maxT;
+ },
+
+ /**
+ * return shader program used by drawAtPoint and drawInRect
+ * @return {cc.GLProgram}
+ */
+ getShaderProgram: function () {
+ return this.shaderProgram;
+ },
+
+ /**
+ * set shader program used by drawAtPoint and drawInRect
+ * @param {cc.GLProgram} shaderProgram
+ */
+ setShaderProgram: function (shaderProgram) {
+ this.shaderProgram = shaderProgram;
+ },
+
+ /**
+ * whether or not the texture has their Alpha premultiplied
+ * @return {Boolean}
+ */
+ hasPremultipliedAlpha: function () {
+ return this._hasPremultipliedAlpha;
+ },
+
+ /**
+ * whether or not use mipmap
+ * @return {Boolean}
+ */
+ hasMipmaps: function () {
+ return this._hasMipmaps;
+ },
+
+ /**
+ * description
+ * @return {string}
+ */
+ description: function () {
+ var _t = this;
+ return "";
+ },
+
+ /**
+ * These functions are needed to create mutable textures
+ * @param {Array} data
+ */
+ releaseData: function (data) {
+ data = null;
+ },
+
+ keepData: function (data, length) {
+ //The texture data mustn't be saved because it isn't a mutable texture.
+ return data;
+ },
+
+ /**
+ * Intializes with a texture2d with data
+ * @param {Array} data
+ * @param {Number} pixelFormat
+ * @param {Number} pixelsWide
+ * @param {Number} pixelsHigh
+ * @param {cc.Size} contentSize
+ * @return {Boolean}
+ */
+ initWithData: function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
+ var self = this, tex2d = cc.Texture2D;
+ var gl = cc._renderContext;
+ var format = gl.RGBA, type = gl.UNSIGNED_BYTE;
+
+ var bitsPerPixel = cc.Texture2D._B[pixelFormat];
+
+ var bytesPerRow = pixelsWide * bitsPerPixel / 8;
+ if (bytesPerRow % 8 === 0) {
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8);
+ } else if (bytesPerRow % 4 === 0) {
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
+ } else if (bytesPerRow % 2 === 0) {
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2);
+ } else {
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+ }
+
+ self._webTextureObj = gl.createTexture();
+ cc.glBindTexture2D(self);
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ // Specify OpenGL texture image
+ switch (pixelFormat) {
+ case tex2d.PIXEL_FORMAT_RGBA8888:
+ format = gl.RGBA;
+ break;
+ case tex2d.PIXEL_FORMAT_RGB888:
+ format = gl.RGB;
+ break;
+ case tex2d.PIXEL_FORMAT_RGBA4444:
+ type = gl.UNSIGNED_SHORT_4_4_4_4;
+ break;
+ case tex2d.PIXEL_FORMAT_RGB5A1:
+ type = gl.UNSIGNED_SHORT_5_5_5_1;
+ break;
+ case tex2d.PIXEL_FORMAT_RGB565:
+ type = gl.UNSIGNED_SHORT_5_6_5;
+ break;
+ case tex2d.PIXEL_FORMAT_AI88:
+ format = gl.LUMINANCE_ALPHA;
+ break;
+ case tex2d.PIXEL_FORMAT_A8:
+ format = gl.ALPHA;
+ break;
+ case tex2d.PIXEL_FORMAT_I8:
+ format = gl.LUMINANCE;
+ break;
+ default:
+ cc.assert(0, cc._LogInfos.Texture2D_initWithData);
+ }
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, pixelsWide, pixelsHigh, 0, format, type, data);
+
+
+ self._contentSize.width = contentSize.width;
+ self._contentSize.height = contentSize.height;
+ self._pixelsWide = pixelsWide;
+ self._pixelsHigh = pixelsHigh;
+ self._pixelFormat = pixelFormat;
+ self.maxS = contentSize.width / pixelsWide;
+ self.maxT = contentSize.height / pixelsHigh;
+
+ self._hasPremultipliedAlpha = false;
+ self._hasMipmaps = false;
+ self.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
+
+ self._textureLoaded = true;
+
+ return true;
+ },
+
+ /**
+ Drawing extensions to make it easy to draw basic quads using a CCTexture2D object.
+ These functions require gl.TEXTURE_2D and both gl.VERTEX_ARRAY and gl.TEXTURE_COORD_ARRAY client states to be enabled.
+ */
+
+ /**
+ * draws a texture at a given point
+ * @param {cc.Point} point
+ */
+ drawAtPoint: function (point) {
+ var self = this;
+ var coordinates = [
+ 0.0, self.maxT,
+ self.maxS, self.maxT,
+ 0.0, 0.0,
+ self.maxS, 0.0],
+ gl = cc._renderContext;
+
+ var width = self._pixelsWide * self.maxS,
+ height = self._pixelsHigh * self.maxT;
+
+ var vertices = [
+ point.x, point.y, 0.0,
+ width + point.x, point.y, 0.0,
+ point.x, height + point.y, 0.0,
+ width + point.x, height + point.y, 0.0];
+
+ self._glProgramState.apply();
+ self._glProgramState._glprogram.setUniformsForBuiltins();
+
+ cc.glBindTexture2D(self);
+
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
+
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+ },
+
+ /**
+ * draws a texture inside a rect
+ * @param {cc.Rect} rect
+ */
+ drawInRect: function (rect) {
+ var self = this;
+ var coordinates = [
+ 0.0, self.maxT,
+ self.maxS, self.maxT,
+ 0.0, 0.0,
+ self.maxS, 0.0];
+
+ var vertices = [rect.x, rect.y, /*0.0,*/
+ rect.x + rect.width, rect.y, /*0.0,*/
+ rect.x, rect.y + rect.height, /*0.0,*/
+ rect.x + rect.width, rect.y + rect.height /*0.0*/];
+
+ self._glProgramState.apply();
+ self._glProgramState._glprogram.setUniformsForBuiltins();
+
+ cc.glBindTexture2D(self);
+
+ var gl = cc._renderContext;
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
+
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+ },
+
+ /**
+ Extensions to make it easy to create a CCTexture2D object from an image file.
+ Note that RGBA type textures will have their alpha premultiplied - use the blending mode (gl.ONE, gl.ONE_MINUS_SRC_ALPHA).
+ */
+
+ /**
+ * Initializes a texture from a UIImage object
+ * @param uiImage
+ * @return {Boolean}
+ */
+ initWithImage: function (uiImage) {
+ if (uiImage == null) {
+ cc.log(cc._LogInfos.Texture2D_initWithImage);
+ return false;
+ }
+
+ var imageWidth = uiImage.getWidth();
+ var imageHeight = uiImage.getHeight();
+
+ var maxTextureSize = cc.configuration.getMaxTextureSize();
+ if (imageWidth > maxTextureSize || imageHeight > maxTextureSize) {
+ cc.log(cc._LogInfos.Texture2D_initWithImage_2, imageWidth, imageHeight, maxTextureSize, maxTextureSize);
+ return false;
+ }
+ this._textureLoaded = true;
+
+ // always load premultiplied images
+ return this._initPremultipliedATextureWithImage(uiImage, imageWidth, imageHeight);
+ },
+
+ /**
+ * init with HTML element
+ * @param {HTMLImageElement|HTMLCanvasElement} element
+ */
+ initWithElement: function (element) {
+ if (!element)
+ return;
+ this._webTextureObj = cc._renderContext.createTexture();
+ this._htmlElementObj = element;
+ this._textureLoaded = true;
+ // Textures should be loaded with premultiplied alpha in order to avoid gray bleeding
+ // when semitransparent textures are interpolated (e.g. when scaled).
+ this._hasPremultipliedAlpha = true;
+ },
+
+ /**
+ * HTMLElement Object getter
+ * @return {HTMLElement}
+ */
+ getHtmlElementObj: function () {
+ return this._htmlElementObj;
+ },
+
+ /**
+ * whether texture is loaded
+ * @return {Boolean}
+ */
+ isLoaded: function () {
+ return this._textureLoaded;
+ },
+
+ /**
+ * handler of texture loaded event
+ * @param {Boolean} [premultiplied=false]
+ */
+ handleLoadedTexture: function (premultiplied) {
+ var self = this;
+ premultiplied =
+ (premultiplied !== undefined)
+ ? premultiplied
+ : self._hasPremultipliedAlpha;
+ // Not sure about this ! Some texture need to be updated even after loaded
+ if (!cc.game._rendererInitialized)
+ return;
+ if (!self._htmlElementObj)
+ return;
+ if (!self._htmlElementObj.width || !self._htmlElementObj.height)
+ return;
+
+ //upload image to buffer
+ var gl = cc._renderContext;
+
+ cc.glBindTexture2D(self);
+
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
+ if (premultiplied)
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
+
+ // Specify OpenGL texture image
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self._htmlElementObj);
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
+
+ self.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
+ cc.glBindTexture2D(null);
+ if (premultiplied)
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);
+
+ var pixelsWide = self._htmlElementObj.width;
+ var pixelsHigh = self._htmlElementObj.height;
+
+ self._pixelsWide = self._contentSize.width = pixelsWide;
+ self._pixelsHigh = self._contentSize.height = pixelsHigh;
+ self._pixelFormat = cc.Texture2D.PIXEL_FORMAT_RGBA8888;
+ self.maxS = 1;
+ self.maxT = 1;
+
+ self._hasPremultipliedAlpha = premultiplied;
+ self._hasMipmaps = false;
+ if (window.ENABLE_IMAEG_POOL) {
+ self._htmlElementObj = null;
+ }
+
+ //dispatch load event to listener.
+ self.dispatchEvent("load");
+ },
+
+ /**
+ Extensions to make it easy to create a cc.Texture2D object from a string of text.
+ Note that the generated textures are of type A8 - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
+ */
+ /**
+ * Initializes a texture from a string with dimensions, alignment, font name and font size (note: initWithString does not support on HTML5)
+ * @param {String} text
+ * @param {String | cc.FontDefinition} fontName or fontDefinition
+ * @param {Number} fontSize
+ * @param {cc.Size} dimensions
+ * @param {Number} hAlignment
+ * @param {Number} vAlignment
+ * @return {Boolean}
+ */
+ initWithString: function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
+ cc.log(cc._LogInfos.Texture2D_initWithString);
+ return null;
+ },
+
+ /**
+ * Initializes a texture from a ETC file (note: initWithETCFile does not support on HTML5)
+ * @note Compatible to Cocos2d-x
+ * @param {String} file
+ * @return {Boolean}
+ */
+ initWithETCFile: function (file) {
+ cc.log(cc._LogInfos.Texture2D_initWithETCFile_2);
+ return false;
+ },
+
+ /**
+ * Initializes a texture from a PVR file
+ * @param {String} file
+ * @return {Boolean}
+ */
+ initWithPVRFile: function (file) {
+ cc.log(cc._LogInfos.Texture2D_initWithPVRFile_2);
+ return false;
+ },
+
+ /**
+ Extensions to make it easy to create a cc.Texture2D object from a PVRTC file
+ Note that the generated textures don't have their alpha premultiplied - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
+ */
+ /**
+ * Initializes a texture from a PVRTC buffer
+ * @note compatible to cocos2d-iphone interface.
+ * @param {Array} data
+ * @param {Number} level
+ * @param {Number} bpp
+ * @param {Boolean} hasAlpha
+ * @param {Number} length
+ * @param {Number} pixelFormat
+ * @return {Boolean}
+ */
+ initWithPVRTCData: function (data, level, bpp, hasAlpha, length, pixelFormat) {
+ cc.log(cc._LogInfos.Texture2D_initWithPVRTCData_2);
+ return false;
+ },
+
+ /**
+ * sets the min filter, mag filter, wrap s and wrap t texture parameters.
+ * If the texture size is NPOT (non power of 2), then in can only use gl.CLAMP_TO_EDGE in gl.TEXTURE_WRAP_{S,T}.
+ * @param {Object|Number} texParams texParams object or minFilter
+ * @param {Number} [magFilter]
+ * @param {Number} [wrapS]
+ * @param {Number} [wrapT]
+ */
+ setTexParameters: function (texParams, magFilter, wrapS, wrapT) {
+ var _t = this;
+ var gl = cc._renderContext;
+
+ if (magFilter !== undefined)
+ texParams = {minFilter: texParams, magFilter: magFilter, wrapS: wrapS, wrapT: wrapT};
+
+ cc.assert((_t._pixelsWide === cc.NextPOT(_t._pixelsWide) && _t._pixelsHigh === cc.NextPOT(_t._pixelsHigh)) ||
+ (texParams.wrapS === gl.CLAMP_TO_EDGE && texParams.wrapT === gl.CLAMP_TO_EDGE),
+ "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures");
+
+ cc.glBindTexture2D(_t);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT);
+ },
+
+ /**
+ * sets antialias texture parameters:
+ * - GL_TEXTURE_MIN_FILTER = GL_NEAREST
+ * - GL_TEXTURE_MAG_FILTER = GL_NEAREST
+ */
+ setAntiAliasTexParameters: function () {
+ var gl = cc._renderContext;
+
+ cc.glBindTexture2D(this);
+ if (!this._hasMipmaps)
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ else
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ },
+
+ /**
+ * sets alias texture parameters:
+ * GL_TEXTURE_MIN_FILTER = GL_NEAREST
+ * GL_TEXTURE_MAG_FILTER = GL_NEAREST
+ */
+ setAliasTexParameters: function () {
+ var gl = cc._renderContext;
+
+ cc.glBindTexture2D(this);
+ if (!this._hasMipmaps)
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ else
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ },
+
+ /**
+ * Generates mipmap images for the texture.
+ * It only works if the texture size is POT (power of 2).
+ */
+ generateMipmap: function () {
+ var _t = this;
+ cc.assert(_t._pixelsWide === cc.NextPOT(_t._pixelsWide) && _t._pixelsHigh === cc.NextPOT(_t._pixelsHigh), "Mimpap texture only works in POT textures");
+
+ cc.glBindTexture2D(_t);
+ cc._renderContext.generateMipmap(cc._renderContext.TEXTURE_2D);
+ _t._hasMipmaps = true;
+ },
+
+ /**
+ * returns the pixel format.
+ * @return {String}
+ */
+ stringForFormat: function () {
+ return cc.Texture2D._M[this._pixelFormat];
+ },
+
+ /**
+ * returns the bits-per-pixel of the in-memory OpenGL texture
+ * @return {Number}
+ */
+ bitsPerPixelForFormat: function (format) {//TODO I want to delete the format argument, use this._pixelFormat
+ format = format || this._pixelFormat;
+ var value = cc.Texture2D._B[format];
+ if (value != null) return value;
+ cc.log(cc._LogInfos.Texture2D_bitsPerPixelForFormat, format);
+ return -1;
+ },
+
+ _initPremultipliedATextureWithImage: function (uiImage, width, height) {
+ var tex2d = cc.Texture2D;
+ var tempData = uiImage.getData();
+ var inPixel32 = null;
+ var inPixel8 = null;
+ var outPixel16 = null;
+ var hasAlpha = uiImage.hasAlpha();
+ var imageSize = cc.size(uiImage.getWidth(), uiImage.getHeight());
+ var pixelFormat = tex2d.defaultPixelFormat;
+ var bpp = uiImage.getBitsPerComponent();
+
+ // compute pixel format
+ if (!hasAlpha) {
+ if (bpp >= 8) {
+ pixelFormat = tex2d.PIXEL_FORMAT_RGB888;
+ } else {
+ cc.log(cc._LogInfos.Texture2D__initPremultipliedATextureWithImage);
+ pixelFormat = tex2d.PIXEL_FORMAT_RGB565;
+ }
+ }
+
+ // Repack the pixel data into the right format
+ var i, length = width * height;
+
+ if (pixelFormat === tex2d.PIXEL_FORMAT_RGB565) {
+ if (hasAlpha) {
+ // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
+ tempData = new Uint16Array(width * height);
+ inPixel32 = uiImage.getData();
+
+ for (i = 0; i < length; ++i) {
+ tempData[i] =
+ ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) | // R
+ ((((inPixel32[i] >> 8) & 0xFF) >> 2) << 5) | // G
+ ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 0); // B
+ }
+ } else {
+ // Convert "RRRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB"
+ tempData = new Uint16Array(width * height);
+ inPixel8 = uiImage.getData();
+
+ for (i = 0; i < length; ++i) {
+ tempData[i] =
+ (((inPixel8[i] & 0xFF) >> 3) << 11) | // R
+ (((inPixel8[i] & 0xFF) >> 2) << 5) | // G
+ (((inPixel8[i] & 0xFF) >> 3) << 0); // B
+ }
+ }
+ } else if (pixelFormat === tex2d.PIXEL_FORMAT_RGBA4444) {
+ // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
+ tempData = new Uint16Array(width * height);
+ inPixel32 = uiImage.getData();
+
+ for (i = 0; i < length; ++i) {
+ tempData[i] =
+ ((((inPixel32[i] >> 0) & 0xFF) >> 4) << 12) | // R
+ ((((inPixel32[i] >> 8) & 0xFF) >> 4) << 8) | // G
+ ((((inPixel32[i] >> 16) & 0xFF) >> 4) << 4) | // B
+ ((((inPixel32[i] >> 24) & 0xFF) >> 4) << 0); // A
+ }
+ } else if (pixelFormat === tex2d.PIXEL_FORMAT_RGB5A1) {
+ // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA"
+ tempData = new Uint16Array(width * height);
+ inPixel32 = uiImage.getData();
+
+ for (i = 0; i < length; ++i) {
+ tempData[i] =
+ ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) | // R
+ ((((inPixel32[i] >> 8) & 0xFF) >> 3) << 6) | // G
+ ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 1) | // B
+ ((((inPixel32[i] >> 24) & 0xFF) >> 7) << 0); // A
+ }
+ } else if (pixelFormat === tex2d.PIXEL_FORMAT_A8) {
+ // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "AAAAAAAA"
+ tempData = new Uint8Array(width * height);
+ inPixel32 = uiImage.getData();
+
+ for (i = 0; i < length; ++i) {
+ tempData[i] = (inPixel32 >> 24) & 0xFF; // A
+ }
+ }
+
+ if (hasAlpha && pixelFormat === tex2d.PIXEL_FORMAT_RGB888) {
+ // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBBB"
+ inPixel32 = uiImage.getData();
+ tempData = new Uint8Array(width * height * 3);
+
+ for (i = 0; i < length; ++i) {
+ tempData[i * 3] = (inPixel32 >> 0) & 0xFF; // R
+ tempData[i * 3 + 1] = (inPixel32 >> 8) & 0xFF; // G
+ tempData[i * 3 + 2] = (inPixel32 >> 16) & 0xFF; // B
+ }
+ }
+
+ this.initWithData(tempData, pixelFormat, width, height, imageSize);
+
+ if (tempData != uiImage.getData())
+ tempData = null;
+
+ this._hasPremultipliedAlpha = uiImage.isPremultipliedAlpha();
+ return true;
+ },
+
+ /**
+ * add listener for loaded event
+ * @param {Function} callback
+ * @param {cc.Node} target
+ * @deprecated since 3.1, please use addEventListener instead
+ */
+ addLoadedEventListener: function (callback, target) {
+ this.addEventListener("load", callback, target);
+ },
+
+ /**
+ * remove listener from listeners by target
+ * @param {cc.Node} target
+ */
+ removeLoadedEventListener: function (target) {
+ this.removeEventTarget("load", target);
+ }
+ });
+};
+
+cc._tmp.WebGLTextureAtlas = function () {
+ var _p = cc.TextureAtlas.prototype;
+ _p._setupVBO = function () {
+ var _t = this;
+ var gl = cc._renderContext;
+ //create WebGLBuffer
+ _t._buffersVBO[0] = gl.createBuffer();
+ _t._buffersVBO[1] = gl.createBuffer();
+
+ _t._quadsWebBuffer = gl.createBuffer();
+ _t._mapBuffers();
+ };
+
+ _p._mapBuffers = function () {
+ var _t = this;
+ var gl = cc._renderContext;
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, _t._quadsWebBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, _t._quadsArrayBuffer, gl.DYNAMIC_DRAW);
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _t._buffersVBO[1]);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, _t._indices, gl.STATIC_DRAW);
+
+ //cc.checkGLErrorDebug();
+ };
+
+ /**
+ * Draws n quads from an index (offset).
+ * n + start can't be greater than the capacity of the atlas
+ * @param {Number} n
+ * @param {Number} start
+ */
+ _p.drawNumberOfQuads = function (n, start) {
+ var _t = this;
+ start = start || 0;
+ if (0 === n || !_t.texture || !_t.texture.isLoaded())
+ return;
+
+ var gl = cc._renderContext;
+ cc.glBindTexture2D(_t.texture);
+
+ //
+ // Using VBO without VAO
+ //
+ //vertices
+ //gl.bindBuffer(gl.ARRAY_BUFFER, _t._buffersVBO[0]);
+ // XXX: update is done in draw... perhaps it should be done in a timer
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, _t._quadsWebBuffer);
+ if (_t.dirty) {
+ gl.bufferData(gl.ARRAY_BUFFER, _t._quadsArrayBuffer, gl.DYNAMIC_DRAW);
+ _t.dirty = false;
+ }
+
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); // vertices
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); // colors
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16); // tex coords
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _t._buffersVBO[1]);
+
+ if (cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP)
+ gl.drawElements(gl.TRIANGLE_STRIP, n * 6, gl.UNSIGNED_SHORT, start * 6 * _t._indices.BYTES_PER_ELEMENT);
+ else
+ gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, start * 6 * _t._indices.BYTES_PER_ELEMENT);
+
+ cc.g_NumberOfDraws++;
+ //cc.checkGLErrorDebug();
+ };
+};
+
+cc._tmp.WebGLTextureCache = function () {
+ var _p = cc.textureCache;
+
+ _p.handleLoadedTexture = function (url, img) {
+ var locTexs = this._textures, tex, ext;
+ //remove judge(webgl)
+ if (!cc.game._rendererInitialized) {
+ locTexs = this._loadedTexturesBefore;
+ }
+ tex = locTexs[url];
+ if (!tex) {
+ tex = locTexs[url] = new cc.Texture2D();
+ tex.url = url;
+ }
+ tex.initWithElement(img);
+ ext = cc.path.extname(url);
+ if (ext === ".png") {
+ tex.handleLoadedTexture(true);
+ }
+ else {
+ tex.handleLoadedTexture();
+ }
+ return tex;
+ };
+
+ /**
+ * Returns a Texture2D object given an file image
+ * If the file image was not previously loaded, it will create a new Texture2D
+ * object and it will return it. It will use the filename as a key.
+ * Otherwise it will return a reference of a previously loaded image.
+ * Supported image extensions: .png, .jpg, .gif
+ * @param {String} url
+ * @param {Function} cb
+ * @param {Object} target
+ * @return {cc.Texture2D}
+ * @example
+ * //example
+ * cc.textureCache.addImage("hello.png");
+ */
+ _p.addImage = function (url, cb, target) {
+ cc.assert(url, cc._LogInfos.Texture2D_addImage_2);
+
+ var locTexs = this._textures;
+ //remove judge(webgl)
+ if (!cc.game._rendererInitialized) {
+ locTexs = this._loadedTexturesBefore;
+ }
+ var tex = locTexs[url] || locTexs[cc.loader._getAliase(url)];
+ if (tex) {
+ if (tex.isLoaded()) {
+ cb && cb.call(target, tex);
+ return tex;
+ }
+ else {
+ tex.addEventListener("load", function () {
+ cb && cb.call(target, tex);
+ }, target);
+ return tex;
+ }
+ }
+
+ tex = locTexs[url] = new cc.Texture2D();
+ tex.url = url;
+ var basePath = cc.loader.getBasePath ? cc.loader.getBasePath() : cc.loader.resPath;
+ cc.loader.loadImg(cc.path.join(basePath || "", url), function (err, img) {
+ if (err)
+ return cb && cb.call(target, err);
+
+ var texResult = cc.textureCache.handleLoadedTexture(url, img);
+ cb && cb.call(target, texResult);
+ });
+
+ return tex;
+ };
+
+ _p.addImageAsync = _p.addImage;
+ _p = null;
+};
diff --git a/cocos2d/core/utils/BinaryLoader.js b/cocos2d/core/utils/BinaryLoader.js
new file mode 100644
index 0000000000..46b82b65cf
--- /dev/null
+++ b/cocos2d/core/utils/BinaryLoader.js
@@ -0,0 +1,155 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+
+/**
+ * Load binary data by url.
+ * @function
+ * @param {String} url
+ * @param {Function} [cb]
+ */
+
+cc.loader.loadBinary = function (url, cb) {
+ var self = this;
+ var xhr = this.getXMLHttpRequest(),
+ errInfo = "load " + url + " failed!";
+ xhr.open("GET", url, true);
+ xhr.responseType = 'arraybuffer';
+ if (cc.loader.loadBinary._IEFilter) {
+ // IE-specific logic here
+ xhr.setRequestHeader("Accept-Charset", "x-user-defined");
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ var fileContents = cc._convertResponseBodyToText(xhr["responseBody"]);
+ cb(null, self._str2Uint8Array(fileContents));
+ } else cb(errInfo);
+ };
+ } else {
+ if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=x-user-defined");
+ xhr.onload = function () {
+ xhr.readyState === 4 && xhr.status === 200 ? cb(null, new Uint8Array(xhr.response)) : cb(errInfo);
+ };
+ }
+ xhr.send(null);
+};
+
+cc.loader.loadBinary._IEFilter = (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) && window.IEBinaryToArray_ByteStr && window.IEBinaryToArray_ByteStr_Last);
+
+cc.loader._str2Uint8Array = function (strData) {
+ if (!strData)
+ return null;
+
+ var arrData = new Uint8Array(strData.length);
+ for (var i = 0; i < strData.length; i++) {
+ arrData[i] = strData.charCodeAt(i) & 0xff;
+ }
+ return arrData;
+};
+
+/**
+ * Load binary data by url synchronously
+ * @function
+ * @param {String} url
+ * @return {Uint8Array}
+ */
+cc.loader.loadBinarySync = function (url) {
+ var self = this;
+ var req = this.getXMLHttpRequest();
+ req.timeout = 0;
+ var errInfo = "load " + url + " failed!";
+ req.open('GET', url, false);
+ var arrayInfo = null;
+ if (cc.loader.loadBinary._IEFilter) {
+ req.setRequestHeader("Accept-Charset", "x-user-defined");
+ req.send(null);
+ if (req.status !== 200) {
+ cc.log(errInfo);
+ return null;
+ }
+
+ var fileContents = cc._convertResponseBodyToText(req["responseBody"]);
+ if (fileContents) {
+ arrayInfo = self._str2Uint8Array(fileContents);
+ }
+ } else {
+ if (req.overrideMimeType)
+ req.overrideMimeType('text\/plain; charset=x-user-defined');
+ req.send(null);
+ if (req.status !== 200) {
+ cc.log(errInfo);
+ return null;
+ }
+
+ arrayInfo = self._str2Uint8Array(req.responseText);
+ }
+ return arrayInfo;
+};
+
+//Compatibility with IE9
+window.Uint8Array = window.Uint8Array || window.Array;
+
+if (cc.loader.loadBinary._IEFilter) {
+ var IEBinaryToArray_ByteStr_Script =
+ "\r\n" +
+ //"\r\n";
+
+ // inject VBScript
+ //document.write(IEBinaryToArray_ByteStr_Script);
+ var myVBScript = document.createElement('script');
+ myVBScript.type = "text/vbscript";
+ myVBScript.textContent = IEBinaryToArray_ByteStr_Script;
+ document.body.appendChild(myVBScript);
+
+ // helper to convert from responseBody to a "responseText" like thing
+ cc._convertResponseBodyToText = function (binary) {
+ var byteMapping = {};
+ for (var i = 0; i < 256; i++) {
+ for (var j = 0; j < 256; j++) {
+ byteMapping[ String.fromCharCode(i + j * 256) ] =
+ String.fromCharCode(i) + String.fromCharCode(j);
+ }
+ }
+ var rawBytes = IEBinaryToArray_ByteStr(binary);
+ var lastChr = IEBinaryToArray_ByteStr_Last(binary);
+ return rawBytes.replace(/[\s\S]/g,
+ function (match) {
+ return byteMapping[match];
+ }) + lastChr;
+ };
+}
diff --git a/cocos2d/core/utils/CCProfiler.js b/cocos2d/core/utils/CCProfiler.js
new file mode 100644
index 0000000000..94d0c41eb4
--- /dev/null
+++ b/cocos2d/core/utils/CCProfiler.js
@@ -0,0 +1,151 @@
+cc.profiler = (function () {
+ var _showFPS = false;
+ var _inited = false;
+ var _frames = 0, _frameRate = 0, _lastSPF = 0, _accumDt = 0;
+ var _afterVisitListener = null,
+ _FPSLabel = document.createElement('div'),
+ _SPFLabel = document.createElement('div'),
+ _drawsLabel = document.createElement('div'),
+ _fps = document.createElement('div');
+
+ var LEVEL_DET_FACTOR = 0.6, _levelDetCycle = 10;
+ var LEVELS = [0, 10, 20, 30];
+ var _fpsCount = [0, 0, 0, 0];
+ var _currLevel = 3, _analyseCount = 0, _totalFPS = 0;
+
+ _fps.id = 'fps';
+ _fps.style.position = 'absolute';
+ _fps.style.padding = '3px';
+ _fps.style.textAlign = 'left';
+ _fps.style.backgroundColor = 'rgb(0, 0, 34)';
+ _fps.style.bottom = cc.DIRECTOR_STATS_POSITION.y + '0px';
+ _fps.style.left = cc.DIRECTOR_STATS_POSITION.x + 'px';
+ _fps.style.width = '45px';
+ _fps.style.height = '80px';
+
+ var labels = [_drawsLabel, _SPFLabel, _FPSLabel];
+ for (var i = 0; i < 3; ++i) {
+ var style = labels[i].style;
+ style.color = 'rgb(0, 255, 255)';
+ style.font = 'bold 12px Helvetica, Arial';
+ style.lineHeight = '20px';
+ style.width = '100%';
+ _fps.appendChild(labels[i]);
+ }
+
+ var analyseFPS = function (fps) {
+ var lastId = LEVELS.length - 1, i = lastId, ratio, average = 0;
+ _analyseCount++;
+ _totalFPS += fps;
+
+ for (; i >= 0; i--) {
+ if (fps >= LEVELS[i]) {
+ _fpsCount[i]++;
+ break;
+ }
+ }
+
+ if (_analyseCount >= _levelDetCycle) {
+ average = _totalFPS / _levelDetCycle;
+ for (i = lastId; i > 0; i--) {
+ ratio = _fpsCount[i] / _levelDetCycle;
+ // Determined level
+ if (ratio >= LEVEL_DET_FACTOR && average >= LEVELS[i]) {
+ // Level changed
+ if (i != _currLevel) {
+ _currLevel = i;
+ profiler.onFrameRateChange && profiler.onFrameRateChange(average.toFixed(2));
+ }
+ break;
+ }
+ // If no level determined, that means the framerate is not stable
+ }
+
+ _changeCount = 0;
+ _analyseCount = 0;
+ _totalFPS = 0;
+ for (i = lastId; i > 0; i--) {
+ _fpsCount[i] = 0;
+ }
+ }
+ };
+
+ var afterVisit = function () {
+ _lastSPF = cc.director.getSecondsPerFrame();
+ _frames++;
+ _accumDt += cc.director.getDeltaTime();
+
+ if (_accumDt > cc.DIRECTOR_FPS_INTERVAL) {
+ _frameRate = _frames / _accumDt;
+ _frames = 0;
+ _accumDt = 0;
+
+ if (profiler.onFrameRateChange) {
+ analyseFPS(_frameRate);
+ }
+
+ if (_showFPS) {
+ var mode = cc._renderType === cc.game.RENDER_TYPE_CANVAS ? "\n canvas" : "\n webgl";
+ _SPFLabel.innerHTML = _lastSPF.toFixed(3);
+ _FPSLabel.innerHTML = _frameRate.toFixed(1).toString() + mode;
+ _drawsLabel.innerHTML = (0 | cc.g_NumberOfDraws).toString();
+ }
+ }
+ };
+
+ var profiler = {
+ onFrameRateChange: null,
+
+ getSecondsPerFrame: function () {
+ return _lastSPF;
+ },
+ getFrameRate: function () {
+ return _frameRate;
+ },
+
+ setProfileDuration: function (duration) {
+ if (!isNaN(duration) && duration > 0) {
+ _levelDetCycle = duration / cc.DIRECTOR_FPS_INTERVAL;
+ }
+ },
+
+ resumeProfiling: function () {
+ cc.eventManager.addListener(_afterVisitListener, 1);
+ },
+
+ stopProfiling: function () {
+ cc.eventManager.removeListener(_afterVisitListener);
+ },
+
+ isShowingStats: function () {
+ return _showFPS;
+ },
+
+ showStats: function () {
+ if (!_inited) {
+ this.init();
+ }
+
+ if (_fps.parentElement === null) {
+ cc.container.appendChild(_fps);
+ }
+ _showFPS = true;
+ },
+
+ hideStats: function () {
+ _showFPS = false;
+ if (_fps.parentElement === cc.container) {
+ cc.container.removeChild(_fps);
+ }
+ },
+
+ init: function () {
+ if (!_inited) {
+ _afterVisitListener = cc.eventManager.addCustomListener(cc.Director.EVENT_AFTER_VISIT, afterVisit);
+ _inited = true;
+ }
+ }
+ };
+
+ return profiler;
+})();
diff --git a/cocos2d/core/utils/CCSimplePool.js b/cocos2d/core/utils/CCSimplePool.js
new file mode 100644
index 0000000000..30fa22cdbc
--- /dev/null
+++ b/cocos2d/core/utils/CCSimplePool.js
@@ -0,0 +1,74 @@
+/****************************************************************************
+ Copyright (c) 2016 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc.SimplePool = function () {
+ this._pool = [];
+};
+cc.SimplePool.prototype = {
+ constructor: cc.SimplePool,
+
+ size: function () {
+ return this._pool.length;
+ },
+
+ put: function (obj) {
+ if (obj && this._pool.indexOf(obj) === -1) {
+ this._pool.unshift(obj);
+ }
+ },
+
+ get: function () {
+ var last = this._pool.length-1;
+ if (last < 0) {
+ return null;
+ }
+ else {
+ var obj = this._pool[last];
+ this._pool.length = last;
+ return obj;
+ }
+ },
+
+ find: function (finder, end) {
+ var found, i, obj, pool = this._pool, last = pool.length-1;
+ for (i = pool.length; i >= 0; --i) {
+ obj = pool[i];
+ found = finder(i, obj);
+ if (found) {
+ pool[i] = pool[last];
+ pool.length = last;
+ return obj;
+ }
+ }
+ if (end) {
+ var index = end();
+ if (index >= 0) {
+ pool[index] = pool[last];
+ pool.length = last;
+ return obj;
+ }
+ }
+ return null;
+ }
+};
\ No newline at end of file
diff --git a/cocos2d/draw_nodes/CCDrawNode.js b/cocos2d/draw_nodes/CCDrawNode.js
deleted file mode 100644
index 78feb2127c..0000000000
--- a/cocos2d/draw_nodes/CCDrawNode.js
+++ /dev/null
@@ -1,473 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
- Copyright (c) 2012 Scott Lembcke and Howling Moon Software
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/*
- * Code copied & pasted from SpacePatrol game https://github.com/slembcke/SpacePatrol
- *
- * Renamed and added some changes for cocos2d
- *
- */
-cc.v2fzero = function () {
- return {x: 0, y: 0};
-};
-
-cc.v2f = function (x, y) {
- return {x: x, y: y};
-};
-
-cc.v2fadd = function (v0, v1) {
- return cc.v2f(v0.x + v1.x, v0.y + v1.y);
-};
-
-cc.v2fsub = function (v0, v1) {
- return cc.v2f(v0.x - v1.x, v0.y - v1.y);
-};
-
-cc.v2fmult = function (v, s) {
- return cc.v2f(v.x * s, v.y * s);
-};
-
-cc.v2fperp = function (p0) {
- return cc.v2f(-p0.y, p0.x);
-};
-
-cc.v2fneg = function (p0) {
- return cc.v2f(-p0.x, -p0.y);
-};
-
-cc.v2fdot = function (p0, p1) {
- return p0.x * p1.x + p0.y * p1.y;
-};
-
-cc.v2fforangle = function (_a_) {
- return cc.v2f(Math.cos(_a_), Math.sin(_a_));
-};
-
-cc.v2fnormalize = function (p) {
- var r = cc.pNormalize(cc.p(p.x, p.y));
- return cc.v2f(r.x, r.y);
-};
-
-cc.__v2f = function (v) {
- return cc.v2f(v.x, v.y);
-};
-
-cc.__t = function (v) {
- return {u: v.x, v: v.y};
-};
-
-/**
- * CCDrawNode for Canvas
- * Node that draws dots, segments and polygons.
- * Faster than the "drawing primitives" since they it draws everything in one single batch.
- * @class
- * @extends cc.Node
- */
-cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{
- _buffer:null,
- _blendFunc:null,
-
- // ----common function start ----
- getBlendFunc:function () {
- return this._blendFunc;
- },
-
- setBlendFunc:function (blendFunc) {
- this._blendFunc = blendFunc;
- },
- // ----common function end ----
-
- ctor:function () {
- cc.Node.prototype.ctor.call(this);
- this._buffer = [];
- this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
- },
-
- draw:function (ctx) {
- var context = ctx || cc.renderContext;
- var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX();
-
- if ((this._blendFunc && (this._blendFunc.src == gl.SRC_ALPHA) && (this._blendFunc.dst == gl.ONE)))
- context.globalCompositeOperation = 'lighter';
-
- for (var i = 0; i < this._buffer.length; i++) {
- var element = this._buffer[i];
- if (element.type === cc.DrawNode.TYPE_DOT) {
- context.fillStyle = "rgba(" + (0 | (element.color.r * 255)) + "," + (0 | (element.color.g * 255)) + "," + (0 | (element.color.b * 255)) + "," + element.color.a + ")";
- cc.drawingUtil.drawPoint(element.position, element.radius);
- }
-
- if (element.type === cc.DrawNode.TYPE_SEGMENT) {
- context.strokeStyle = "rgba(" + (0 | (element.color.r * 255)) + "," + (0 | (element.color.g * 255)) + "," + (0 | (element.color.b * 255)) + "," + element.color.a + ")";
- context.lineWidth = element.radius * 2 * locEGL_ScaleX;
- context.lineCap = "round";
- cc.drawingUtil.drawLine(element.from, element.to);
- }
-
- if (element.type === cc.DrawNode.TYPE_POLY ) {
- context.fillStyle = "rgba(" + (0 | (element.fillColor.r * 255)) + "," + (0 | (element.fillColor.g * 255)) + ","
- + (0 | (element.fillColor.b * 255)) + "," + element.fillColor.a + ")";
- cc.drawingUtil.drawPoly(element.verts, element.count, false, true);
- context.lineWidth = element.borderWidth * 2 * locEGL_ScaleX;
- context.lineCap = "round";
- context.strokeStyle = "rgba(" + (0 | (element.borderColor.r * 255)) + "," + (0 | (element.borderColor.g * 255)) + ","
- + (0 | (element.borderColor.b * 255)) + "," + element.borderColor.a + ")";
- cc.drawingUtil.drawPoly(element.verts, element.count, true, false);
- }
- }
- },
-
- /**
- * draw a dot at a position, with a given radius and color
- * @param {cc.Point} pos
- * @param {Number} radius
- * @param {cc.Color4F} color
- */
- drawDot:function (pos, radius, color) {
- var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_DOT);
- element.position = pos;
- element.radius = radius;
- element.color = color;
- this._buffer.push(element);
- },
-
- /**
- * draw a segment with a radius and color
- * @param {cc.Point} from
- * @param {cc.Point} to
- * @param {Number} radius
- * @param {cc.Color4F} color
- */
- drawSegment:function (from, to, radius, color) {
- var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_SEGMENT);
- element.from = from;
- element.to = to;
- element.radius = radius;
- element.color = color;
- this._buffer.push(element);
- },
-
- /**
- * draw a polygon with a fill color and line color
- * @param {Array} verts
- * @param {cc.Color4F} fillColor
- * @param {Number} borderWidth
- * @param {cc.Color4F} borderColor
- */
- drawPoly:function (verts, fillColor, borderWidth, borderColor) {
- var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY );
- element.verts = verts;
- element.count = verts.length;
- element.fillColor = fillColor;
- element.borderWidth = borderWidth;
- element.borderColor = borderColor;
- this._buffer.push(element);
- },
-
- /**
- * Clear the geometry in the node's buffer.
- */
- clear:function () {
- this._buffer.length = 0;
- }
-});
-
-/**
- * CCDrawNode for WebGL
- * Node that draws dots, segments and polygons.
- * Faster than the "drawing primitives" since they it draws everything in one single batch.
- * @class
- * @extends cc.Node
- */
-cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{
- _bufferCapacity:0,
- _buffer:null,
-
- _trianglesArrayBuffer:null,
- _trianglesWebBuffer:null,
- _trianglesReader:null,
-
- _blendFunc:null,
- _dirty:false,
-
- // ----common function start ----
- getBlendFunc:function () {
- return this._blendFunc;
- },
-
- setBlendFunc:function (blendFunc) {
- this._blendFunc = blendFunc;
- },
- // ----common function end ----
-
- ctor:function () {
- cc.Node.prototype.ctor.call(this);
- this._buffer = [];
- this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
- },
-
- init:function () {
- if (cc.Node.prototype.init.call(this)) {
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_LENGTHTEXTURECOLOR));
- this._ensureCapacity(512);
- this._trianglesWebBuffer = cc.renderContext.createBuffer();
- this._dirty = true;
- return true;
- }
- return false;
- },
-
- _render:function () {
- var gl = cc.renderContext;
-
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX);
- gl.bindBuffer(gl.ARRAY_BUFFER, this._trianglesWebBuffer);
- if (this._dirty) {
- gl.bufferData(gl.ARRAY_BUFFER, this._trianglesArrayBuffer, gl.STREAM_DRAW);
- this._dirty = false;
- }
- var triangleSize = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
-
- // vertex
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, triangleSize, 0);
- // color
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, triangleSize, 8);
- // texcood
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, triangleSize, 12);
-
- gl.drawArrays(gl.TRIANGLES, 0, this._buffer.length * 3);
- cc.INCREMENT_GL_DRAWS(1);
- //cc.CHECK_GL_ERROR_DEBUG();
- },
-
- _ensureCapacity:function(count){
- if(this._buffer.length + count > this._bufferCapacity){
- var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT;
- this._bufferCapacity += Math.max(this._bufferCapacity, count);
- //re alloc
- if((this._buffer == null) || (this._buffer.length === 0)){
- //init
- this._buffer = [];
- this._trianglesArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity);
- this._trianglesReader = new Uint8Array(this._trianglesArrayBuffer);
- } else {
- var newTriangles = [];
- var newArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity);
-
- for(var i = 0; i < this._buffer.length;i++){
- newTriangles[i] = new cc.V2F_C4B_T2F_Triangle(this._buffer[i].a,this._buffer[i].b,this._buffer[i].c,
- newArrayBuffer,i * TriangleLength);
- }
- this._trianglesReader = new Uint8Array(newArrayBuffer);
- this._buffer = newTriangles;
- this._trianglesArrayBuffer = newArrayBuffer;
- }
- }
- },
-
- draw:function () {
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
- this._shaderProgram.use();
- this._shaderProgram.setUniformsForBuiltins();
- this._render();
- },
-
- /**
- * draw a dot at a position, with a given radius and color
- * @param {cc.Point} pos
- * @param {Number} radius
- * @param {cc.Color4F} color
- */
- drawDot:function (pos, radius, color) {
- var c4bColor = {r: 0 | (color.r * 255), g: 0 | (color.g * 255), b: 0 | (color.b * 255), a: 0 | (color.a * 255)};
- var a = {vertices: {x: pos.x - radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: -1.0, v: -1.0}};
- var b = {vertices: {x: pos.x - radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: -1.0, v: 1.0}};
- var c = {vertices: {x: pos.x + radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: 1.0, v: 1.0}};
- var d = {vertices: {x: pos.x + radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: 1.0, v: -1.0}};
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, b, c, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT));
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, c, d, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT));
- this._dirty = true;
- },
-
- /**
- * draw a segment with a radius and color
- * @param {cc.Point} from
- * @param {cc.Point} to
- * @param {Number} radius
- * @param {cc.Color4F} color
- */
- drawSegment:function (from, to, radius, color) {
- var vertexCount = 6*3;
- this._ensureCapacity(vertexCount);
-
- var c4bColor = {r: 0 | (color.r * 255), g: 0 | (color.g * 255), b: 0 | (color.b * 255), a: 0 | (color.a * 255)};
- var a = cc.__v2f(from);
- var b = cc.__v2f(to);
-
- var n = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(b, a)));
- var t = cc.v2fperp(n);
-
- var nw = cc.v2fmult(n, radius);
- var tw = cc.v2fmult(t, radius);
- var v0 = cc.v2fsub(b, cc.v2fadd(nw, tw));
- var v1 = cc.v2fadd(b, cc.v2fsub(nw, tw));
- var v2 = cc.v2fsub(b, nw);
- var v3 = cc.v2fadd(b, nw);
- var v4 = cc.v2fsub(a, nw);
- var v5 = cc.v2fadd(a, nw);
- var v6 = cc.v2fsub(a, cc.v2fsub(nw, tw));
- var v7 = cc.v2fadd(a, cc.v2fadd(nw, tw));
-
- var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, triangleBuffer = this._trianglesArrayBuffer;
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(cc.v2fadd(n, t)))},
- {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
- triangleBuffer, this._buffer.length * TriangleLength));
-
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
- {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
- triangleBuffer, this._buffer.length * TriangleLength));
-
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
- {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
- triangleBuffer, this._buffer.length * TriangleLength));
-
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
- {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
- triangleBuffer, this._buffer.length * TriangleLength));
-
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))},
- {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
- triangleBuffer, this._buffer.length * TriangleLength));
-
- this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))},
- {vertices: v7, colors: c4bColor, texCoords: cc.__t(cc.v2fadd(n, t))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
- triangleBuffer, this._buffer.length * TriangleLength));
- this._dirty = true;
- },
-
- /**
- * draw a polygon with a fill color and line color
- * @param {Array} verts
- * @param {cc.Color4F} fillColor
- * @param {Number} borderWidth
- * @param {cc.Color4F} borderColor
- */
- drawPoly:function (verts, fillColor, borderWidth, borderColor) {
- var c4bFillColor = {r: 0 | (fillColor.r * 255), g: 0 | (fillColor.g * 255), b: 0 | (fillColor.b * 255), a: 0 | (fillColor.a * 255)};
- var c4bBorderColor = {r: 0 | (borderColor.r * 255), g: 0 | (borderColor.g * 255), b: 0 | (borderColor.b * 255), a: 0 | (borderColor.a * 255)};
- var extrude = [], i;
- var v0, v1, v2;
- var count = verts.length;
- for (i = 0; i < count; i++) {
- v0 = cc.__v2f(verts[(i - 1 + count) % count]);
- v1 = cc.__v2f(verts[i]);
- v2 = cc.__v2f(verts[(i + 1) % count]);
- var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0)));
- var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1)));
- var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0));
- extrude[i] = {offset: offset, n: n2};
- }
- var outline = (borderColor.a > 0.0 && borderWidth > 0.0);
-
- var triangleCount = 3 * count -2;
- var vertexCount = 3 * triangleCount;
- this._ensureCapacity(vertexCount);
-
- var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer;
- var locBuffer = this._buffer;
- var inset = (outline == false ? 0.5 : 0.0);
- for (i = 0; i < count - 2; i++) {
- v0 = cc.v2fsub(cc.__v2f(verts[0]), cc.v2fmult(extrude[0].offset, inset));
- v1 = cc.v2fsub(cc.__v2f(verts[i + 1]), cc.v2fmult(extrude[i + 1].offset, inset));
- v2 = cc.v2fsub(cc.__v2f(verts[i + 2]), cc.v2fmult(extrude[i + 2].offset, inset));
- locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
- {vertices: v1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v2, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
- trianglesBuffer, locBuffer.length * triangleBytesLen));
- }
-
- for (i = 0; i < count; i++) {
- var j = (i + 1) % count;
- v0 = cc.__v2f(verts[i]);
- v1 = cc.__v2f(verts[j]);
-
- var n0 = extrude[i].n;
- var offset0 = extrude[i].offset;
- var offset1 = extrude[j].offset;
- var inner0 = outline ? cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fsub(v0, cc.v2fmult(offset0, 0.5));
- var inner1 = outline ? cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fsub(v1, cc.v2fmult(offset1, 0.5));
- var outer0 = outline ? cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fadd(v0, cc.v2fmult(offset0, 0.5));
- var outer1 = outline ? cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fadd(v1, cc.v2fmult(offset1, 0.5));
-
- if (outline) {
- locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
- {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
- trianglesBuffer, locBuffer.length * triangleBytesLen));
- locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
- {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
- trianglesBuffer, locBuffer.length * triangleBytesLen));
- } else {
- locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
- {vertices: inner1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)},
- trianglesBuffer, locBuffer.length * triangleBytesLen));
- locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
- {vertices: outer0, colors: c4bFillColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)},
- trianglesBuffer, locBuffer.length * triangleBytesLen));
- }
- }
- extrude = null;
- this._dirty = true;
- },
-
- /**
- * Clear the geometry in the node's buffer.
- */
- clear:function () {
- this._buffer.length = 0;
- this._dirty = true;
- }
-});
-
-cc.DrawNode = cc.Browser.supportWebGL ? cc.DrawNodeWebGL : cc.DrawNodeCanvas;
-
-/**
- * Creates a DrawNode
- * @return {cc.DrawNode}
- */
-cc.DrawNode.create = function () {
- var ret = new cc.DrawNode();
- if (ret && ret.init())
- return ret;
- return null;
-};
-
-cc._DrawNodeElement = function (type) {
- this.type = type;
-};
-
-cc.DrawNode.TYPE_DOT = 0;
-cc.DrawNode.TYPE_SEGMENT = 1;
-cc.DrawNode.TYPE_POLY = 2;
diff --git a/cocos2d/effects/CCGrabber.js b/cocos2d/effects/CCGrabber.js
index 75eb7cb49b..21380259c3 100644
--- a/cocos2d/effects/CCGrabber.js
+++ b/cocos2d/effects/CCGrabber.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -24,7 +24,11 @@
THE SOFTWARE.
****************************************************************************/
-/** FBO class that grabs the the contents of the screen */
+/**
+ * FBO class that grabs the the contents of the screen
+ * @class
+ * @extends cc.Class
+ */
cc.Grabber = cc.Class.extend({
_FBO:null,
_oldFBO:null,
@@ -32,14 +36,22 @@ cc.Grabber = cc.Class.extend({
_gl:null,
+ /**
+ * constructor of cc.Grabber
+ */
ctor:function () {
- this._gl = cc.renderContext;
+ cc.sys._checkWebGLRenderMode();
+ this._gl = cc._renderContext;
this._oldClearColor = [0, 0, 0, 0];
this._oldFBO = null;
// generate FBO
this._FBO = this._gl.createFramebuffer();
},
+ /**
+ * grab
+ * @param {cc.Texture2D} texture
+ */
grab:function (texture) {
var locGL = this._gl;
this._oldFBO = locGL.getParameter(locGL.FRAMEBUFFER_BINDING);
@@ -50,11 +62,15 @@ cc.Grabber = cc.Class.extend({
// check if it worked (probably worth doing :) )
var status = locGL.checkFramebufferStatus(locGL.FRAMEBUFFER);
- if (status != locGL.FRAMEBUFFER_COMPLETE)
+ if (status !== locGL.FRAMEBUFFER_COMPLETE)
cc.log("Frame Grabber: could not attach texture to frmaebuffer");
locGL.bindFramebuffer(locGL.FRAMEBUFFER, this._oldFBO);
},
+ /**
+ * should be invoked before drawing
+ * @param {cc.Texture2D} texture
+ */
beforeRender:function (texture) {
var locGL = this._gl;
this._oldFBO = locGL.getParameter(locGL.FRAMEBUFFER_BINDING);
@@ -75,12 +91,19 @@ cc.Grabber = cc.Class.extend({
// glColorMask(true, true, true, false); // #631
},
+ /**
+ * should be invoked after drawing
+ * @param {cc.Texture2D} texture
+ */
afterRender:function (texture) {
var locGL = this._gl;
locGL.bindFramebuffer(locGL.FRAMEBUFFER, this._oldFBO);
locGL.colorMask(true, true, true, true); // #631
},
+ /**
+ * delete FBO
+ */
destroy:function(){
this._gl.deleteFramebuffer(this._FBO);
}
diff --git a/cocos2d/effects/CCGrid.js b/cocos2d/effects/CCGrid.js
index f22a863d16..361cba84b3 100644
--- a/cocos2d/effects/CCGrid.js
+++ b/cocos2d/effects/CCGrid.js
@@ -1,8 +1,8 @@
/****************************************************************************
- Copyright (c) 2010-2013 cocos2d-x.org
- Copyright (c) 2009 On-Core
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2009 On-Core
http://www.cocos2d-x.org
@@ -31,36 +31,50 @@
* @extends cc.Class
*/
cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
- _active:false,
- _reuseGrid:0,
- _gridSize:null,
- _texture:null,
- _step:null,
- _grabber:null,
- _isTextureFlipped:false,
- _shaderProgram:null,
- _directorProjection:0,
-
- _dirty:false,
-
- ctor:function () {
- this._active=false;
- this._reuseGrid=0;
- this._gridSize=null;
- this._texture=null;
+ _active: false,
+ _reuseGrid: 0,
+ _gridSize: null,
+ _gridRect: null,
+ _texture: null,
+ _step: null,
+ _grabber: null,
+ _isTextureFlipped: false,
+ _glProgramState: null,
+ _directorProjection: 0,
+
+ _dirty: false,
+
+ /**
+ * create one cc.GridBase Object
+ * Constructor of cc.GridBase
+ * @param {cc.Size} gridSize
+ * @param {cc.Texture2D} [texture=]
+ * @param {Boolean} [flipped=]
+ * @param {cc.Rect} rect
+ */
+ ctor: function (gridSize, texture, flipped, rect) {
+ cc.sys._checkWebGLRenderMode();
+ this._active = false;
+ this._reuseGrid = 0;
+ this._gridSize = null;
+ this._gridRect = new cc.rect();
+ this._texture = null;
this._step = cc.p(0, 0);
- this._grabber=null;
- this._isTextureFlipped=false;
- this._shaderProgram=null;
- this._directorProjection=0;
- this._dirty=false;
+ this._grabber = null;
+ this._isTextureFlipped = false;
+ this._glProgramState = null;
+ this._directorProjection = 0;
+ this._dirty = false;
+
+ if (gridSize !== undefined)
+ this.initWithSize(gridSize, texture, flipped, rect);
},
/**
* whether or not the grid is active
* @return {Boolean}
*/
- isActive:function () {
+ isActive: function () {
return this._active;
},
@@ -68,10 +82,10 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
* whether or not the grid is active
* @param {Number} active
*/
- setActive:function (active) {
+ setActive: function (active) {
this._active = active;
if (!active) {
- var director = cc.Director.getInstance();
+ var director = cc.director;
var proj = director.getProjection();
director.setProjection(proj);
}
@@ -81,14 +95,14 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
* get number of times that the grid will be reused
* @return {Number}
*/
- getReuseGrid:function () {
+ getReuseGrid: function () {
return this._reuseGrid;
},
/**
* set number of times that the grid will be reused
* @param reuseGrid
*/
- setReuseGrid:function (reuseGrid) {
+ setReuseGrid: function (reuseGrid) {
this._reuseGrid = reuseGrid;
},
@@ -96,7 +110,7 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
* get size of the grid
* @return {cc.Size}
*/
- getGridSize:function () {
+ getGridSize: function () {
return cc.size(this._gridSize.width, this._gridSize.height);
},
@@ -104,16 +118,32 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
* set size of the grid
* @param {cc.Size} gridSize
*/
- setGridSize:function (gridSize) {
+ setGridSize: function (gridSize) {
this._gridSize.width = parseInt(gridSize.width);
this._gridSize.height = parseInt(gridSize.height);
},
+ /**
+ * set rect of the grid
+ * @param {cc.Rect} rect
+ */
+ setGridRect: function (rect) {
+ this._gridRect = rect;
+ },
+
+ /**
+ * get rect of the grid
+ * @return {cc.Rect} rect
+ */
+ getGridRect: function () {
+ return this._gridRect;
+ },
+
/**
* get pixels between the grids
* @return {cc.Point}
*/
- getStep:function () {
+ getStep: function () {
return cc.p(this._step.x, this._step.y);
},
@@ -121,25 +151,25 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
* set pixels between the grids
* @param {cc.Point} step
*/
- setStep:function (step) {
+ setStep: function (step) {
this._step.x = step.x;
this._step.y = step.y;
},
/**
- * get wheter or not the texture is flipped
+ * get whether or not the texture is flipped
* @return {Boolean}
*/
- isTextureFlipped:function () {
+ isTextureFlipped: function () {
return this._isTextureFlipped;
},
/**
- * set wheter or not the texture is flipped
+ * set whether or not the texture is flipped
* @param {Boolean} flipped
*/
- setTextureFlipped:function (flipped) {
- if (this._isTextureFlipped != flipped) {
+ setTextureFlipped: function (flipped) {
+ if (this._isTextureFlipped !== flipped) {
this._isTextureFlipped = flipped;
this.calculateVertexPoints();
}
@@ -150,11 +180,12 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
* @param {cc.Size} gridSize
* @param {cc.Texture2D} [texture=]
* @param {Boolean} [flipped=false]
+ * @param {cc.Rect} [rect=]
* @returns {boolean}
*/
- initWithSize:function (gridSize, texture, flipped) {
+ initWithSize: function (gridSize, texture, flipped, rect) {
if (!texture) {
- var director = cc.Director.getInstance();
+ var director = cc.director;
var winSize = director.getWinSizeInPixels();
var POTWide = cc.NextPOT(winSize.width);
@@ -168,7 +199,7 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
texture = new cc.Texture2D();
// we only use rgba8888
- texture.initWithData(data, cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, POTWide, POTHigh, winSize);
+ texture.initWithData(data, cc.Texture2D.PIXEL_FORMAT_RGBA8888, POTWide, POTHigh, winSize);
if (!texture) {
cc.log("cocos2d: CCGrid: error creating texture");
return false;
@@ -182,77 +213,75 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
this._gridSize = gridSize;
this._texture = texture;
this._isTextureFlipped = flipped;
+ if (rect === undefined || cc._rectEqualToZero(rect)) {
+ var size = this._texture.getContentSize();
+ rect = new cc.rect(0, 0, size.width, size.height);
+ }
+
+ this._gridRect = rect;
- var texSize = this._texture.getContentSize();
- this._step.x = texSize.width / gridSize.width;
- this._step.y = texSize.height / gridSize.height;
+ this._step.x = this._gridRect.width / gridSize.width;
+ this._step.y = this._gridRect.height / gridSize.height;
this._grabber = new cc.Grabber();
if (!this._grabber)
return false;
this._grabber.grab(this._texture);
- this._shaderProgram = cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE);
+ this._glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE));
this.calculateVertexPoints();
return true;
},
- beforeDraw:function () {
+ beforeDraw: function () {
// save projection
- this._directorProjection = cc.Director.getInstance().getProjection();
+ this._directorProjection = cc.director.getProjection();
- // 2d projection
- // [director setProjection:kCCDirectorProjection2D];
- this.set2DProjection();
+ //this.set2DProjection(); //TODO why?
+ var size = cc.director.getWinSizeInPixels();
+ gl.viewport(0, 0, size.width, size.height);
this._grabber.beforeRender(this._texture);
},
- afterDraw:function (target) {
+ afterDraw: function (target) {
this._grabber.afterRender(this._texture);
// restore projection
- cc.Director.getInstance().setProjection(this._directorProjection);
-
- if (target.getCamera().isDirty()) {
- var offset = target.getAnchorPointInPoints();
-
- //
- // XXX: Camera should be applied in the AnchorPoint
- //
- cc.kmGLTranslatef(offset.x, offset.y, 0);
- target.getCamera().locate();
- cc.kmGLTranslatef(-offset.x, -offset.y, 0);
- }
+ //cc.director.setProjection(this._directorProjection);
+ cc.director.setViewport();
cc.glBindTexture2D(this._texture);
+ this.beforeBlit();
+ this.blit(target);
+ this.afterBlit();
+ },
+
+ beforeBlit: function () {
+ },
- // restore projection for default FBO .fixed bug #543 #544
- //TODO: CCDirector::sharedDirector().setProjection(CCDirector::sharedDirector().getProjection());
- //TODO: CCDirector::sharedDirector().applyOrientation();
- this.blit();
+ afterBlit: function () {
},
- blit:function () {
- cc.Assert(0, "");
+ blit: function () {
+ cc.log("cc.GridBase.blit(): Shall be overridden in subclass.");
},
- reuse:function () {
- cc.Assert(0, "");
+ reuse: function () {
+ cc.log("cc.GridBase.reuse(): Shall be overridden in subclass.");
},
- calculateVertexPoints:function () {
- cc.Assert(0, "");
+ calculateVertexPoints: function () {
+ cc.log("cc.GridBase.calculateVertexPoints(): Shall be overridden in subclass.");
},
- set2DProjection:function () {
- var winSize = cc.Director.getInstance().getWinSizeInPixels();
+ set2DProjection: function () {
+ var winSize = cc.director.getWinSizeInPixels();
- var gl = cc.renderContext;
- gl.viewport(0, 0, winSize.width , winSize.height);
+ var gl = cc._renderContext;
+ gl.viewport(0, 0, winSize.width, winSize.height);
cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
cc.kmGLLoadIdentity();
- var orthoMatrix = new cc.kmMat4();
- cc.kmMat4OrthographicProjection(orthoMatrix, 0, winSize.width, 0, winSize.height, -1, 1);
+ var orthoMatrix = cc.math.Matrix4.createOrthographicProjection(0, winSize.width, 0, winSize.height, -1, 1);
cc.kmGLMultMatrix(orthoMatrix);
cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
@@ -263,16 +292,15 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{
/**
* create one cc.GridBase Object
+ * @deprecated
* @param {cc.Size} gridSize
* @param {cc.Texture2D} [texture=]
* @param {Boolean} [flipped=]
+ * @param {cc.Rect} [rect=]
* @return {cc.GridBase}
*/
-cc.GridBase.create = function (gridSize, texture, flipped) {
- var gridBase = new cc.GridBase();
- if (gridBase && gridBase.initWithSize(gridSize, texture, flipped))
- return gridBase;
- return null;
+cc.GridBase.create = function (gridSize, texture, flipped, rect) {
+ return new cc.GridBase(gridSize, texture, flipped, rect);
};
/**
@@ -281,25 +309,53 @@ cc.GridBase.create = function (gridSize, texture, flipped) {
* @extends cc.GridBase
*/
cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
- _texCoordinates:null,
- _vertices:null,
- _originalVertices:null,
- _indices:null,
+ _texCoordinates: null,
+ _vertices: null,
+ _originalVertices: null,
+ _indices: null,
+
+ _texCoordinateBuffer: null,
+ _verticesBuffer: null,
+ _indicesBuffer: null,
- _texCoordinateBuffer:null,
- _verticesBuffer:null,
- _indicesBuffer:null,
+ _needDepthTestForBlit: false,
+ _oldDepthTestValue: false,
+ _oldDepthWriteValue: false,
- ctor:function () {
+ /**
+ * create one Grid3D object
+ * Constructor of cc.Grid3D
+ * @param {cc.Size} gridSize
+ * @param {cc.Texture2D} [texture=]
+ * @param {Boolean} [flipped=]
+ * @param {cc.Rect} [rect=]
+ */
+ ctor: function (gridSize, texture, flipped, rect) {
cc.GridBase.prototype.ctor.call(this);
- this._texCoordinates=null;
- this._vertices=null;
- this._originalVertices=null;
- this._indices=null;
+ this._texCoordinates = null;
+ this._vertices = null;
+ this._originalVertices = null;
+ this._indices = null;
+
+ this._texCoordinateBuffer = null;
+ this._verticesBuffer = null;
+ this._indicesBuffer = null;
+
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+
+ if (gridSize !== undefined)
+ this.initWithSize(gridSize, texture, flipped, rect);
+ },
- this._texCoordinateBuffer=null;
- this._verticesBuffer=null;
- this._indicesBuffer=null;
+ /**
+ * returns the vertex at a given position
+ * It will be deprecated in future, please use getVertex instead.
+ * @param {cc.Point} pos
+ * @return {cc.Vertex3F}
+ */
+ vertex: function (pos) {
+ return this.getVertex(pos);
},
/**
@@ -307,20 +363,32 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
* @param {cc.Point} pos
* @return {cc.Vertex3F}
*/
- vertex:function (pos) {
- cc.Assert( pos.x == (0| pos.x) && pos.y == (0| pos.y) , "Numbers must be integers");
+ getVertex: function (pos) {
+ if (pos.x !== (0 | pos.x) || pos.y !== (0 | pos.y))
+ cc.log("cc.Grid3D.vertex() : Numbers must be integers");
var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
var locVertices = this._vertices;
return new cc.Vertex3F(locVertices[index], locVertices[index + 1], locVertices[index + 2]);
},
+ /**
+ * returns the original (non-transformed) vertex at a given position
+ * It will be deprecated in future, please use getOriginalVertex instead.
+ * @param {cc.Point} pos
+ * @return {cc.Vertex3F}
+ */
+ originalVertex: function (pos) {
+ return this.getOriginalVertex(pos);
+ },
+
/**
* returns the original (non-transformed) vertex at a given position
* @param {cc.Point} pos
* @return {cc.Vertex3F}
*/
- originalVertex:function (pos) {
- cc.Assert( pos.x == (0| pos.x) && pos.y == (0| pos.y) , "Numbers must be integers");
+ getOriginalVertex: function (pos) {
+ if (pos.x !== (0 | pos.x) || pos.y !== (0 | pos.y))
+ cc.log("cc.Grid3D.originalVertex() : Numbers must be integers");
var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
var locOriginalVertices = this._originalVertices;
return new cc.Vertex3F(locOriginalVertices[index], locOriginalVertices[index + 1], locOriginalVertices[index + 2]);
@@ -331,8 +399,9 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
* @param {cc.Point} pos
* @param {cc.Vertex3F} vertex
*/
- setVertex:function (pos, vertex) {
- cc.Assert( pos.x == (0| pos.x) && pos.y == (0| pos.y) , "Numbers must be integers");
+ setVertex: function (pos, vertex) {
+ if (pos.x !== (0 | pos.x) || pos.y !== (0 | pos.y))
+ cc.log("cc.Grid3D.setVertex() : Numbers must be integers");
var index = 0 | ((pos.x * (this._gridSize.height + 1) + pos.y) * 3);
var vertArray = this._vertices;
vertArray[index] = vertex.x;
@@ -341,13 +410,45 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
this._dirty = true;
},
- blit:function () {
+ beforeBlit: function () {
+ if (this._needDepthTestForBlit) {
+ var gl = cc._renderContext;
+ this._oldDepthTestValue = gl.isEnabled(gl.DEPTH_TEST);
+ this._oldDepthWriteValue = gl.getParameter(gl.DEPTH_WRITEMASK);
+ //CHECK_GL_ERROR_DEBUG();
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthMask(true);
+ }
+ },
+
+ afterBlit: function () {
+ if (this._needDepthTestForBlit) {
+ var gl = cc._renderContext;
+ if (this._oldDepthTestValue)
+ gl.enable(gl.DEPTH_TEST);
+ else
+ gl.disable(gl.DEPTH_TEST);
+ gl.depthMask(this._oldDepthWriteValue);
+ }
+ },
+
+ blit: function (target) {
var n = this._gridSize.width * this._gridSize.height;
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS);
- this._shaderProgram.use();
- this._shaderProgram.setUniformsForBuiltins();
- var gl = cc.renderContext, locDirty = this._dirty;
+ var wt = target._renderCmd._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ this._glProgramState.apply(this._matrix);
+
+ var gl = cc._renderContext, locDirty = this._dirty;
+
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
//
// Attributes
//
@@ -369,23 +470,23 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
if (locDirty)
this._dirty = false;
- cc.INCREMENT_GL_DRAWS(1);
+ cc.incrementGLDraws(1);
},
- reuse:function () {
+ reuse: function () {
if (this._reuseGrid > 0) {
var locOriginalVertices = this._originalVertices, locVertices = this._vertices;
- for (var i = 0, len = this._vertices.length; i < len; i++)
+ for (var i = 0, len = this._vertices.length; i < len; i++)
locOriginalVertices[i] = locVertices[i];
--this._reuseGrid;
}
},
- calculateVertexPoints:function () {
- var gl = cc.renderContext;
+ calculateVertexPoints: function () {
+ var gl = cc._renderContext;
- var width = this._texture.getPixelsWide();
- var height = this._texture.getPixelsHigh();
+ var width = this._texture.pixelsWidth;
+ var height = this._texture.pixelsHeight;
var imageH = this._texture.getContentSizeInPixels().height;
var locGridSize = this._gridSize;
@@ -394,13 +495,13 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
this._texCoordinates = new Float32Array(numOfPoints * 2);
this._indices = new Uint16Array(locGridSize.width * locGridSize.height * 6);
- if(this._verticesBuffer)
+ if (this._verticesBuffer)
gl.deleteBuffer(this._verticesBuffer);
this._verticesBuffer = gl.createBuffer();
- if(this._texCoordinateBuffer)
+ if (this._texCoordinateBuffer)
gl.deleteBuffer(this._texCoordinateBuffer);
this._texCoordinateBuffer = gl.createBuffer();
- if(this._indicesBuffer)
+ if (this._indicesBuffer)
gl.deleteBuffer(this._indicesBuffer);
this._indicesBuffer = gl.createBuffer();
@@ -409,9 +510,9 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
for (x = 0; x < locGridSize.width; ++x) {
for (y = 0; y < locGridSize.height; ++y) {
var idx = (y * locGridSize.width) + x;
- var x1 = x * this._step.x;
+ var x1 = x * this._step.x + this._gridRect.x;
var x2 = x1 + this._step.x;
- var y1 = y * this._step.y;
+ var y1 = y * this._step.y + this._gridRect.y;
var y2 = y1 + this._step.y;
var a = (x * (locGridSize.height + 1) + y);
@@ -427,10 +528,10 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
locIndices[idx * 6 + 5] = d;
var l1 = [a * 3, b * 3, c * 3, d * 3];
- var e = {x:x1, y:y1, z:0}; //new cc.Vertex3F(x1, y1, 0);
- var f = {x:x2, y:y1, z:0}; //new cc.Vertex3F(x2, y1, 0);
- var g = {x:x2, y:y2, z:0}; // new cc.Vertex3F(x2, y2, 0);
- var h = {x:x1, y:y2, z:0}; //new cc.Vertex3F(x1, y2, 0);
+ var e = {x: x1, y: y1, z: 0}; //new cc.Vertex3F(x1, y1, 0);
+ var f = {x: x2, y: y1, z: 0}; //new cc.Vertex3F(x2, y1, 0);
+ var g = {x: x2, y: y2, z: 0}; // new cc.Vertex3F(x2, y2, 0);
+ var h = {x: x1, y: y2, z: 0}; //new cc.Vertex3F(x1, y2, 0);
var l2 = [e, f, g, h];
var tex1 = [a * 2, b * 2, c * 2, d * 2];
@@ -456,21 +557,27 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
this._dirty = true;
+ },
+
+ setNeedDepthTestForBlit: function (needDepthTest) {
+ this._needDepthTestForBlit = needDepthTest;
+ },
+
+ getNeedDepthTestForBlit: function () {
+ return this._needDepthTestForBlit;
}
});
/**
* create one Grid3D object
+ * @deprecated
* @param {cc.Size} gridSize
* @param {cc.Texture2D} [texture=]
* @param {Boolean} [flipped=]
* @return {cc.Grid3D}
*/
cc.Grid3D.create = function (gridSize, texture, flipped) {
- var grid3D = new cc.Grid3D();
- if (grid3D && grid3D.initWithSize(gridSize, texture, flipped))
- return grid3D;
- return null;
+ return new cc.Grid3D(gridSize, texture, flipped);
};
/**
@@ -480,25 +587,48 @@ cc.Grid3D.create = function (gridSize, texture, flipped) {
* @extends cc.GridBase
*/
cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
- _texCoordinates:null,
- _vertices:null,
- _originalVertices:null,
- _indices:null,
+ _texCoordinates: null,
+ _vertices: null,
+ _originalVertices: null,
+ _indices: null,
- _texCoordinateBuffer:null,
- _verticesBuffer:null,
- _indicesBuffer:null,
+ _texCoordinateBuffer: null,
+ _verticesBuffer: null,
+ _indicesBuffer: null,
- ctor:function () {
+ /**
+ * create one TiledGrid3D object
+ * Constructor of cc.TiledGrid3D
+ * @param {cc.Size} gridSize
+ * @param {cc.Texture2D} [texture=]
+ * @param {Boolean} [flipped=]
+ */
+ ctor: function (gridSize, texture, flipped, rect) {
cc.GridBase.prototype.ctor.call(this);
- this._texCoordinates=null;
- this._vertices=null;
- this._originalVertices=null;
- this._indices=null;
+ this._texCoordinates = null;
+ this._vertices = null;
+ this._originalVertices = null;
+ this._indices = null;
+
+ this._texCoordinateBuffer = null;
+ this._verticesBuffer = null;
+ this._indicesBuffer = null;
- this._texCoordinateBuffer=null;
- this._verticesBuffer=null;
- this._indicesBuffer=null;
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+
+ if (gridSize !== undefined)
+ this.initWithSize(gridSize, texture, flipped, rect);
+ },
+
+ /**
+ * returns the tile at the given position
+ * It will be deprecated in future, please use getTile instead.
+ * @param {cc.Point} pos
+ * @return {cc.Quad3}
+ */
+ tile: function (pos) {
+ return this.getTile(pos);
},
/**
@@ -506,14 +636,15 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
* @param {cc.Point} pos
* @return {cc.Quad3}
*/
- tile:function (pos) {
- cc.Assert( pos.x == (0| pos.x) && pos.y == (0| pos.y) , "Numbers must be integers");
+ getTile: function (pos) {
+ if (pos.x !== (0 | pos.x) || pos.y !== (0 | pos.y))
+ cc.log("cc.TiledGrid3D.tile() : Numbers must be integers");
var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
var locVertices = this._vertices;
return new cc.Quad3(new cc.Vertex3F(locVertices[idx], locVertices[idx + 1], locVertices[idx + 2]),
new cc.Vertex3F(locVertices[idx + 3], locVertices[idx + 4], locVertices[idx + 5]),
- new cc.Vertex3F(locVertices[idx + 6 ], locVertices[idx + 7], locVertices[idx + 8]),
+ new cc.Vertex3F(locVertices[idx + 6], locVertices[idx + 7], locVertices[idx + 8]),
new cc.Vertex3F(locVertices[idx + 9], locVertices[idx + 10], locVertices[idx + 11]));
},
@@ -522,24 +653,36 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
* @param {cc.Point} pos
* @return {cc.Quad3}
*/
- originalTile:function (pos) {
- cc.Assert( pos.x == (0| pos.x) && pos.y == (0| pos.y) , "Numbers must be integers");
+ getOriginalTile: function (pos) {
+ if (pos.x !== (0 | pos.x) || pos.y !== (0 | pos.y))
+ cc.log("cc.TiledGrid3D.originalTile() : Numbers must be integers");
var idx = (this._gridSize.height * pos.x + pos.y) * 4 * 3;
var locOriginalVertices = this._originalVertices;
return new cc.Quad3(new cc.Vertex3F(locOriginalVertices[idx], locOriginalVertices[idx + 1], locOriginalVertices[idx + 2]),
new cc.Vertex3F(locOriginalVertices[idx + 3], locOriginalVertices[idx + 4], locOriginalVertices[idx + 5]),
- new cc.Vertex3F(locOriginalVertices[idx + 6 ], locOriginalVertices[idx + 7], locOriginalVertices[idx + 8]),
+ new cc.Vertex3F(locOriginalVertices[idx + 6], locOriginalVertices[idx + 7], locOriginalVertices[idx + 8]),
new cc.Vertex3F(locOriginalVertices[idx + 9], locOriginalVertices[idx + 10], locOriginalVertices[idx + 11]));
},
+ /**
+ * returns the original tile (untransformed) at the given position.
+ * It will be deprecated in future, please use getOriginalTile instead.
+ * @param {cc.Point} pos
+ * @return {cc.Quad3}
+ */
+ originalTile: function (pos) {
+ return this.getOriginalTile(pos);
+ },
+
/**
* sets a new tile
* @param {cc.Point} pos
* @param {cc.Quad3} coords
*/
- setTile:function (pos, coords) {
- cc.Assert( pos.x == (0| pos.x) && pos.y == (0| pos.y) , "Numbers must be integers");
+ setTile: function (pos, coords) {
+ if (pos.x !== (0 | pos.x) || pos.y !== (0 | pos.y))
+ cc.log("cc.TiledGrid3D.setTile() : Numbers must be integers");
var idx = (this._gridSize.height * pos.x + pos.y) * 12;
var locVertices = this._vertices;
@@ -558,17 +701,25 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
this._dirty = true;
},
- blit:function () {
+ blit: function (target) {
var n = this._gridSize.width * this._gridSize.height;
- this._shaderProgram.use();
- this._shaderProgram.setUniformsForBuiltins();
+ var wt = target._renderCmd._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ this._glProgramState.apply(this._matrix);
//
// Attributes
//
- var gl = cc.renderContext, locDirty = this._dirty;
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS);
+ var gl = cc._renderContext, locDirty = this._dirty;
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
// position
gl.bindBuffer(gl.ARRAY_BUFFER, this._verticesBuffer);
@@ -588,10 +739,10 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
gl.drawElements(gl.TRIANGLES, n * 6, gl.UNSIGNED_SHORT, 0);
if (locDirty)
this._dirty = false;
- cc.INCREMENT_GL_DRAWS(1);
+ cc.incrementGLDraws(1);
},
- reuse:function () {
+ reuse: function () {
if (this._reuseGrid > 0) {
var locVertices = this._vertices, locOriginalVertices = this._originalVertices;
for (var i = 0; i < locVertices.length; i++)
@@ -600,9 +751,9 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
}
},
- calculateVertexPoints:function () {
- var width = this._texture.getPixelsWide();
- var height = this._texture.getPixelsHigh();
+ calculateVertexPoints: function () {
+ var width = this._texture.pixelsWidth;
+ var height = this._texture.pixelsHeight;
var imageH = this._texture.getContentSizeInPixels().height;
var locGridSize = this._gridSize;
@@ -611,14 +762,14 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
this._texCoordinates = new Float32Array(numQuads * 8);
this._indices = new Uint16Array(numQuads * 6);
- var gl = cc.renderContext;
- if(this._verticesBuffer)
+ var gl = cc._renderContext;
+ if (this._verticesBuffer)
gl.deleteBuffer(this._verticesBuffer);
this._verticesBuffer = gl.createBuffer();
- if(this._texCoordinateBuffer)
+ if (this._texCoordinateBuffer)
gl.deleteBuffer(this._texCoordinateBuffer);
this._texCoordinateBuffer = gl.createBuffer();
- if(this._indicesBuffer)
+ if (this._indicesBuffer)
gl.deleteBuffer(this._indicesBuffer);
this._indicesBuffer = gl.createBuffer();
@@ -688,13 +839,12 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{
/**
* create one TiledGrid3D object
+ * @deprecated since v3.0, please use new cc.TiledGrid3D(gridSize, texture, flipped) instead
* @param {cc.Size} gridSize
* @param {cc.Texture2D} [texture=]
* @param {Boolean} [flipped=]
* @return {cc.TiledGrid3D}
*/
cc.TiledGrid3D.create = function (gridSize, texture, flipped) {
- var ret = new cc.TiledGrid3D();
- ret.initWithSize(gridSize, texture, flipped);
- return ret;
+ return new cc.TiledGrid3D(gridSize, texture, flipped);
};
diff --git a/cocos2d/kazmath/GL/matrix.js b/cocos2d/kazmath/GL/matrix.js
deleted file mode 100644
index 571edb16bb..0000000000
--- a/cocos2d/kazmath/GL/matrix.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008, Luke Benstead.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-cc.KM_GL_MODELVIEW = 0x1700;
-
-cc.KM_GL_PROJECTION = 0x1701;
-
-cc.KM_GL_TEXTURE = 0x1702;
-
-cc.modelview_matrix_stack = new cc.km_mat4_stack();
-cc.projection_matrix_stack = new cc.km_mat4_stack();
-cc.texture_matrix_stack = new cc.km_mat4_stack();
-
-cc.current_stack = null;
-
-cc.initialized = false;
-
-cc.lazyInitialize = function () {
- if (!cc.initialized) {
- var identity = new cc.kmMat4(); //Temporary identity matrix
-
- //Initialize all 3 stacks
- cc.km_mat4_stack_initialize(cc.modelview_matrix_stack);
- cc.km_mat4_stack_initialize(cc.projection_matrix_stack);
- cc.km_mat4_stack_initialize(cc.texture_matrix_stack);
-
- cc.current_stack = cc.modelview_matrix_stack;
- cc.initialized = true;
- cc.kmMat4Identity(identity);
-
- //Make sure that each stack has the identity matrix
- cc.km_mat4_stack_push(cc.modelview_matrix_stack, identity);
- cc.km_mat4_stack_push(cc.projection_matrix_stack, identity);
- cc.km_mat4_stack_push(cc.texture_matrix_stack, identity);
- }
-};
-
-cc.lazyInitialize();
-
-cc.kmGLFreeAll = function () {
- //Clear the matrix stacks
- cc.km_mat4_stack_release(cc.modelview_matrix_stack);
- cc.km_mat4_stack_release(cc.projection_matrix_stack);
- cc.km_mat4_stack_release(cc.texture_matrix_stack);
-
- //Delete the matrices
- cc.initialized = false; //Set to uninitialized
- cc.current_stack = null; //Set the current stack to point nowhere
-};
-
-cc.kmGLPushMatrix = function () {
- cc.km_mat4_stack_push(cc.current_stack, cc.current_stack.top);
-};
-
-cc.kmGLPushMatrixWitMat4 = function (saveMat) {
- cc.current_stack.stack.push(cc.current_stack.top);
- cc.kmMat4Assign(saveMat, cc.current_stack.top);
- cc.current_stack.top = saveMat;
-};
-
-cc.kmGLPopMatrix = function () {
- //cc.Assert(cc.initialized , "Cannot Pop empty matrix stack");
- //No need to lazy initialize, you shouldnt be popping first anyway!
- //cc.km_mat4_stack_pop(cc.current_stack, null);
- cc.current_stack.top = cc.current_stack.stack.pop();
-};
-
-cc.kmGLMatrixMode = function (mode) {
- //cc.lazyInitialize();
- switch (mode) {
- case cc.KM_GL_MODELVIEW:
- cc.current_stack = cc.modelview_matrix_stack;
- break;
- case cc.KM_GL_PROJECTION:
- cc.current_stack = cc.projection_matrix_stack;
- break;
- case cc.KM_GL_TEXTURE:
- cc.current_stack = cc.texture_matrix_stack;
- break;
- default:
- cc.Assert(0, "Invalid matrix mode specified"); //TODO: Proper error handling
- break;
- }
-};
-
-cc.kmGLLoadIdentity = function () {
- //cc.lazyInitialize();
- cc.kmMat4Identity(cc.current_stack.top); //Replace the top matrix with the identity matrix
-};
-
-cc.kmGLLoadMatrix = function (pIn) {
- //cc.lazyInitialize();
- cc.kmMat4Assign(cc.current_stack.top, pIn);
-};
-
-cc.kmGLMultMatrix = function (pIn) {
- //cc.lazyInitialize();
- cc.kmMat4Multiply(cc.current_stack.top, cc.current_stack.top, pIn);
-};
-
-cc.kmGLTranslatef = function (x, y, z) {
- var translation = new cc.kmMat4();
-
- //Create a rotation matrix using the axis and the angle
- cc.kmMat4Translation(translation, x, y, z);
-
- //Multiply the rotation matrix by the current matrix
- cc.kmMat4Multiply(cc.current_stack.top, cc.current_stack.top, translation);
-};
-
-cc.kmGLRotatef = function (angle, x, y, z) {
- var axis = new cc.kmVec3(x, y, z);
- var rotation = new cc.kmMat4();
-
- //Create a rotation matrix using the axis and the angle
- cc.kmMat4RotationAxisAngle(rotation, axis, cc.kmDegreesToRadians(angle));
-
- //Multiply the rotation matrix by the current matrix
- cc.kmMat4Multiply(cc.current_stack.top, cc.current_stack.top, rotation);
-};
-
-cc.kmGLScalef = function (x, y, z) {
- var scaling = new cc.kmMat4();
- cc.kmMat4Scaling(scaling, x, y, z);
- cc.kmMat4Multiply(cc.current_stack.top, cc.current_stack.top, scaling);
-};
-
-cc.kmGLGetMatrix = function (mode, pOut) {
- //cc.lazyInitialize();
-
- switch (mode) {
- case cc.KM_GL_MODELVIEW:
- cc.kmMat4Assign(pOut, cc.modelview_matrix_stack.top);
- break;
- case cc.KM_GL_PROJECTION:
- cc.kmMat4Assign(pOut, cc.projection_matrix_stack.top);
- break;
- case cc.KM_GL_TEXTURE:
- cc.kmMat4Assign(pOut, cc.texture_matrix_stack.top);
- break;
- default:
- cc.Assert(1, "Invalid matrix mode specified"); //TODO: Proper error handling
- break;
- }
-};
diff --git a/cocos2d/kazmath/SIMDPolyfill.js b/cocos2d/kazmath/SIMDPolyfill.js
new file mode 100644
index 0000000000..7c65b0a214
--- /dev/null
+++ b/cocos2d/kazmath/SIMDPolyfill.js
@@ -0,0 +1,78 @@
+/**
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2008, Luke Benstead.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function(cc) {
+ var _useSIMD = false;
+
+ var mat4Proto = cc.math.Matrix4.prototype;
+ var mat4Inverse = mat4Proto.inverse;
+ var mat4IsIdentity = mat4Proto.isIdentity;
+ var mat4Transpose = mat4Proto.transpose;
+ var mat4Multiply = mat4Proto.multiply;
+ var mat4GetMat4MultiplyValue = mat4Proto.getMat4MultiplyValue;
+ var mat4AssignFrom = mat4Proto.assignFrom;
+ var mat4Equals = mat4Proto.equals;
+ var mat4LookAt = mat4Proto.lookAt;
+
+ var vec3Proto = cc.math.Vec3.prototype;
+ var vec3TransformCoord = vec3Proto.transformCoord;
+
+ function _isEnabledSIMD () {
+ return _useSIMD;
+ }
+
+ function _enableSIMD (enable) {
+ if(typeof(SIMD) === 'undefined')
+ return;
+
+ if (enable) {
+ mat4Proto.inverse = mat4Proto.inverseSIMD;
+ mat4Proto.isIdentity = mat4Proto.isIdentitySIMD;
+ mat4Proto.transpose = mat4Proto.transposeSIMD;
+ mat4Proto.multiply = mat4Proto.multiplySIMD;
+ mat4Proto.getMat4MultiplyValue = mat4Proto.getMat4MultiplyValueSIMD;
+ mat4Proto.assignFrom = mat4Proto.assignFromSIMD;
+ mat4Proto.equals = mat4Proto.equalsSIMD;
+ mat4Proto.lookAt = mat4Proto.lookAtSIMD;
+ vec3Proto.transformCoord = vec3Proto.transformCoordSIMD;
+ } else {
+ mat4Proto.inverse = mat4Inverse;
+ mat4Proto.isIdentity = mat4IsIdentity;
+ mat4Proto.transpose = mat4Transpose;
+ mat4Proto.multiply = mat4Multiply;
+ mat4Proto.getMat4MultiplyValue = mat4GetMat4MultiplyValue;
+ mat4Proto.assignFrom = mat4AssignFrom;
+ mat4Proto.equals = mat4Equals;
+ mat4Proto.lookAt = mat4LookAt;
+ vec3Proto.transformCoord = vec3TransformCoord;
+ }
+ _useSIMD = enable;
+ }
+
+ cc.defineGetterSetter(cc.sys, "useSIMD", _isEnabledSIMD, _enableSIMD);
+})(cc);
\ No newline at end of file
diff --git a/cocos2d/kazmath/aabb.js b/cocos2d/kazmath/aabb.js
index 20ead8dcc3..8c5dc5b664 100644
--- a/cocos2d/kazmath/aabb.js
+++ b/cocos2d/kazmath/aabb.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -25,43 +27,52 @@
*/
/**
- * A struture that represents an axis-aligned
- * bounding box.
+ * A structure that represents an axis-aligned bounding box.
+ * cc.kmAABB => cc.math.AABB
*/
-cc.kmAABB = function (min, max) {
+cc.math.AABB = function (min, max) {
/** The max corner of the box */
- this.min = min || new cc.kmVec3();
+ this.min = min || new cc.math.Vec3();
/** The min corner of the box */
- this.max = max || new cc.kmVec3();
+ this.max = max || new cc.math.Vec3();
};
/**
- * Returns KM_TRUE if point is in the specified AABB, returns
- * KM_FALSE otherwise.
+ * Returns true if point is in the specified AABB, returns false otherwise.
+ * @param {cc.math.Vec3} point
+ * @returns {boolean}
*/
-cc.kmAABBContainsPoint = function (pPoint, pBox) {
- if (pPoint.x >= pBox.min.x && pPoint.x <= pBox.max.x &&
+cc.math.AABB.prototype.containsPoint = function (point) {
+ return (point.x >= this.min.x && point.x <= this.max.x &&
+ point.y >= this.min.y && point.y <= this.max.y &&
+ point.z >= this.min.z && point.z <= this.max.z);
+};
+
+/**
+ * Returns true if point is in the specified AABB, returns
+ * false otherwise.
+ */
+cc.math.AABB.containsPoint = function (pPoint, pBox) {
+ return (pPoint.x >= pBox.min.x && pPoint.x <= pBox.max.x &&
pPoint.y >= pBox.min.y && pPoint.y <= pBox.max.y &&
- pPoint.z >= pBox.min.z && pPoint.z <= pBox.max.z) {
- return cc.KM_TRUE;
- }
- return cc.KM_FALSE;
+ pPoint.z >= pBox.min.z && pPoint.z <= pBox.max.z);
};
/**
- * Assigns pIn to pOut, returns pOut.
+ * Assigns aabb to current AABB object
+ * @param {cc.math.AABB} aabb
*/
-cc.kmAABBAssign = function (pOut, pIn) {
- cc.kmVec3Assign(pOut.min, pIn.min);
- cc.kmVec3Assign(pOut.max, pIn.max);
- return pOut;
+cc.math.AABB.prototype.assignFrom = function(aabb){
+ this.min.assignFrom(aabb.min);
+ this.max.assignFrom(aabb.max);
};
/**
- * Scales pIn by s, stores the resulting AABB in pOut. Returns pOut
+ * Assigns pIn to pOut, returns pOut.
*/
-cc.kmAABBScale = function (pOut, pIn, s) {
- cc.Assert(0, "Not implemented");
- return 0;
+cc.math.AABB.assign = function (pOut, pIn) { //cc.kmAABBAssign
+ pOut.min.assignFrom(pIn.min);
+ pOut.max.assignFrom(pIn.max);
+ return pOut;
};
diff --git a/cocos2d/kazmath/gl/mat4stack.js b/cocos2d/kazmath/gl/mat4stack.js
new file mode 100644
index 0000000000..cd339423e2
--- /dev/null
+++ b/cocos2d/kazmath/gl/mat4stack.js
@@ -0,0 +1,99 @@
+/**
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2008, Luke Benstead.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function (cc) {
+ /**
+ * The stack of cc.math.Matrix4
+ * @param {cc.math.Matrix4} [top]
+ * @param {Array} [stack]
+ * @constructor
+ */
+ cc.math.Matrix4Stack = function (top, stack) {
+ this.top = top;
+ this.stack = stack || [];
+ this.lastUpdated = 0;
+ //this._matrixPool = []; // use pool in next version
+ };
+ cc.km_mat4_stack = cc.math.Matrix4Stack;
+ var proto = cc.math.Matrix4Stack.prototype;
+
+ proto.initialize = function () { //cc.km_mat4_stack_initialize
+ this.stack.length = 0;
+ this.top = null;
+ };
+
+ //for compatibility
+ cc.km_mat4_stack_push = function (stack, item) {
+ stack.stack.push(stack.top);
+ stack.top = new cc.math.Matrix4(item);
+ };
+
+ cc.km_mat4_stack_pop = function (stack, pOut) {
+ stack.top = stack.stack.pop();
+ };
+
+ cc.km_mat4_stack_release = function (stack) {
+ stack.stack = null;
+ stack.top = null;
+ };
+
+ proto.push = function (item) {
+ item = item || this.top;
+ this.stack.push(this.top);
+ this.top = new cc.math.Matrix4(item);
+ //this.top = this._getFromPool(item);
+ };
+
+ proto.pop = function () {
+ //this._putInPool(this.top);
+ this.top = this.stack.pop();
+ };
+
+ proto.release = function () {
+ this.stack = null;
+ this.top = null;
+ this._matrixPool = null;
+ };
+
+ proto._getFromPool = function (item) {
+ var pool = this._matrixPool;
+ if (pool.length === 0)
+ return new cc.math.Matrix4(item);
+ var ret = pool.pop();
+ ret.assignFrom(item);
+ return ret;
+ };
+
+ proto._putInPool = function (matrix) {
+ this._matrixPool.push(matrix);
+ };
+})(cc);
+
+
+
+
diff --git a/cocos2d/kazmath/gl/matrix.js b/cocos2d/kazmath/gl/matrix.js
new file mode 100644
index 0000000000..13c9798125
--- /dev/null
+++ b/cocos2d/kazmath/gl/matrix.js
@@ -0,0 +1,168 @@
+/**
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2008, Luke Benstead.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function (cc) {
+ cc.KM_GL_MODELVIEW = 0x1700;
+ cc.KM_GL_PROJECTION = 0x1701;
+ cc.KM_GL_TEXTURE = 0x1702;
+
+ cc.modelview_matrix_stack = new cc.math.Matrix4Stack();
+ cc.projection_matrix_stack = new cc.math.Matrix4Stack();
+ cc.texture_matrix_stack = new cc.math.Matrix4Stack();
+
+ cc.current_stack = null;
+ var initialized = false;
+
+ cc.lazyInitialize = function () {
+ if (!initialized) {
+ var identity = new cc.math.Matrix4(); //Temporary identity matrix
+
+ //Initialize all 3 stacks
+ cc.modelview_matrix_stack.initialize();
+ cc.projection_matrix_stack.initialize();
+ cc.texture_matrix_stack.initialize();
+
+ cc.current_stack = cc.modelview_matrix_stack;
+ cc.initialized = true;
+ identity.identity();
+
+ //Make sure that each stack has the identity matrix
+ cc.modelview_matrix_stack.push(identity);
+ cc.projection_matrix_stack.push(identity);
+ cc.texture_matrix_stack.push(identity);
+ }
+ };
+
+ cc.lazyInitialize();
+
+ cc.kmGLFreeAll = function () {
+ //Clear the matrix stacks
+ cc.modelview_matrix_stack.release();
+ cc.modelview_matrix_stack = null;
+ cc.projection_matrix_stack.release();
+ cc.projection_matrix_stack = null;
+ cc.texture_matrix_stack.release();
+ cc.texture_matrix_stack = null;
+
+ //Delete the matrices
+ cc.initialized = false; //Set to uninitialized
+ cc.current_stack = null; //Set the current stack to point nowhere
+ };
+
+ cc.kmGLPushMatrix = function () {
+ cc.current_stack.push(cc.current_stack.top);
+ };
+
+ cc.kmGLPushMatrixWitMat4 = function (saveMat) {
+ cc.current_stack.stack.push(cc.current_stack.top);
+ saveMat.assignFrom(cc.current_stack.top);
+ cc.current_stack.top = saveMat;
+ };
+
+ cc.kmGLPopMatrix = function () {
+ //No need to lazy initialize, you shouldn't be popping first anyway!
+ //cc.km_mat4_stack_pop(cc.current_stack, null);
+ cc.current_stack.top = cc.current_stack.stack.pop();
+ };
+
+ cc.kmGLMatrixMode = function (mode) {
+ //cc.lazyInitialize();
+ switch (mode) {
+ case cc.KM_GL_MODELVIEW:
+ cc.current_stack = cc.modelview_matrix_stack;
+ break;
+ case cc.KM_GL_PROJECTION:
+ cc.current_stack = cc.projection_matrix_stack;
+ break;
+ case cc.KM_GL_TEXTURE:
+ cc.current_stack = cc.texture_matrix_stack;
+ break;
+ default:
+ throw new Error("Invalid matrix mode specified"); //TODO: Proper error handling
+ break;
+ }
+ cc.current_stack.lastUpdated = cc.director.getTotalFrames();
+ };
+
+ cc.kmGLLoadIdentity = function () {
+ //cc.lazyInitialize();
+ cc.current_stack.top.identity(); //Replace the top matrix with the identity matrix
+ };
+
+ cc.kmGLLoadMatrix = function (pIn) {
+ //cc.lazyInitialize();
+ cc.current_stack.top.assignFrom(pIn);
+ };
+
+ cc.kmGLMultMatrix = function (pIn) {
+ //cc.lazyInitialize();
+ cc.current_stack.top.multiply(pIn);
+ };
+
+ var tempMatrix = new cc.math.Matrix4(); //an internal matrix
+ cc.kmGLTranslatef = function (x, y, z) {
+ //Create a rotation matrix using translation
+ var translation = cc.math.Matrix4.createByTranslation(x, y, z, tempMatrix);
+
+ //Multiply the rotation matrix by the current matrix
+ cc.current_stack.top.multiply(translation);
+ };
+
+ var tempVector3 = new cc.math.Vec3();
+ cc.kmGLRotatef = function (angle, x, y, z) {
+ tempVector3.fill(x, y, z);
+ //Create a rotation matrix using the axis and the angle
+ var rotation = cc.math.Matrix4.createByAxisAndAngle(tempVector3, cc.degreesToRadians(angle), tempMatrix);
+
+ //Multiply the rotation matrix by the current matrix
+ cc.current_stack.top.multiply(rotation);
+ };
+
+ cc.kmGLScalef = function (x, y, z) {
+ var scaling = cc.math.Matrix4.createByScale(x, y, z, tempMatrix);
+ cc.current_stack.top.multiply(scaling);
+ };
+
+ cc.kmGLGetMatrix = function (mode, pOut) {
+ //cc.lazyInitialize();
+ switch (mode) {
+ case cc.KM_GL_MODELVIEW:
+ pOut.assignFrom(cc.modelview_matrix_stack.top);
+ break;
+ case cc.KM_GL_PROJECTION:
+ pOut.assignFrom(cc.projection_matrix_stack.top);
+ break;
+ case cc.KM_GL_TEXTURE:
+ pOut.assignFrom(cc.texture_matrix_stack.top);
+ break;
+ default:
+ throw new Error("Invalid matrix mode specified"); //TODO: Proper error handling
+ break;
+ }
+ };
+})(cc);
diff --git a/cocos2d/kazmath/mat3.js b/cocos2d/kazmath/mat3.js
index 7e6f60bf0d..d3023f0d58 100644
--- a/cocos2d/kazmath/mat3.js
+++ b/cocos2d/kazmath/mat3.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,301 +26,332 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-var Float32Array = Float32Array || Array;
-
-cc.kmMat3 = function () {
- this.mat = new Float32Array([0, 0, 0,
- 0, 0, 0,
- 0, 0, 0]);
-};
-
-cc.kmMat3Fill = function (pOut, pMat) {
- for (var i = 0; i < 9; i++) {
- pOut.mat[i] = pMat;
- }
- return pOut;
-};
-
-cc.kmMat3Adjugate = function (pOut, pIn) {
- pOut.mat[0] = pIn.mat[4] * pIn.mat[8] - pIn.mat[5] * pIn.mat[7];
- pOut.mat[1] = pIn.mat[2] * pIn.mat[7] - pIn.mat[1] * pIn.mat[8];
- pOut.mat[2] = pIn.mat[1] * pIn.mat[5] - pIn.mat[2] * pIn.mat[4];
- pOut.mat[3] = pIn.mat[5] * pIn.mat[6] - pIn.mat[3] * pIn.mat[8];
- pOut.mat[4] = pIn.mat[0] * pIn.mat[8] - pIn.mat[2] * pIn.mat[6];
- pOut.mat[5] = pIn.mat[2] * pIn.mat[3] - pIn.mat[0] * pIn.mat[5];
- pOut.mat[6] = pIn.mat[3] * pIn.mat[7] - pIn.mat[4] * pIn.mat[6];
-
- // XXX: pIn.mat[9] is invalid!
-// pOut.mat[7] = pIn.mat[1] * pIn.mat[6] - pIn.mat[9] * pIn.mat[7];
- pOut.mat[8] = pIn.mat[0] * pIn.mat[4] - pIn.mat[1] * pIn.mat[3];
-
- return pOut;
-};
-
-cc.kmMat3Identity = function (pOut) {
- pOut.mat[1] = pOut.mat[2] = pOut.mat[3] =
- pOut.mat[5] = pOut.mat[6] = pOut.mat[7] = 0;
- pOut.mat[0] = pOut.mat[4] = pOut.mat[8] = 1.0;
- return pOut;
-};
-
-cc.kmMat3Inverse = function (pOut, pDeterminate, pM) {
- var detInv;
- var adjugate = new cc.kmMat3();
-
- if (pDeterminate === 0.0)
- return null;
-
- detInv = 1.0 / pDeterminate;
-
- cc.kmMat3Adjugate(adjugate, pM);
- cc.kmMat3ScalarMultiply(pOut, adjugate, detInv);
-
- return pOut;
-};
-
-cc.kmMat3._identity =
- new Float32Array([1.0, 0.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 0.0, 1.0]);
-
-cc.kmMat3IsIdentity = function (pIn) {
- for (var i = 0; i < 9; i++) {
- if (cc.kmMat3._identity[i] !== pIn.mat[i])
- return false;
- }
- return true;
-};
-
-cc.kmMat3Transpose = function (pOut, pIn) {
- var z, x;
- for (z = 0; z < 3; ++z) {
- for (x = 0; x < 3; ++x)
- pOut.mat[(z * 3) + x] = pIn.mat[(x * 3) + z];
- }
-
- return pOut;
-};
-
-cc.kmMat3Determinant = function (pIn) {
- var output;
- /*
- calculating the determinant following the rule of sarus,
- | 0 3 6 | 0 3 |
- m = | 1 4 7 | 1 4 |
- | 2 5 8 | 2 5 |
- now sum up the products of the diagonals going to the right (i.e. 0,4,8)
- and substract the products of the other diagonals (i.e. 2,4,6)
+window.Uint16Array = window.Uint16Array || window.Array;
+window.Float32Array = window.Float32Array || window.Array;
+(function(cc){
+ /**
+ *
+ * A 3x3 matrix
+ *
+ * @class
+ * @param {cc.math.Matrix3} [mat3]
*/
-
- output = pIn.mat[0] * pIn.mat[4] * pIn.mat[8] + pIn.mat[1] * pIn.mat[5] * pIn.mat[6] + pIn.mat[2] * pIn.mat[3] * pIn.mat[7];
- output -= pIn.mat[2] * pIn.mat[4] * pIn.mat[6] + pIn.mat[0] * pIn.mat[5] * pIn.mat[7] + pIn.mat[1] * pIn.mat[3] * pIn.mat[8];
-
- return output;
-};
-
-cc.kmMat3Multiply = function (pOut, pM1, pM2) {
- var m1 = pM1.mat, m2 = pM2.mat;
-
- pOut.mat[0] = m1[0] * m2[0] + m1[3] * m2[1] + m1[6] * m2[2];
- pOut.mat[1] = m1[1] * m2[0] + m1[4] * m2[1] + m1[7] * m2[2];
- pOut.mat[2] = m1[2] * m2[0] + m1[5] * m2[1] + m1[8] * m2[2];
-
- pOut.mat[3] = m1[0] * m2[3] + m1[3] * m2[4] + m1[6] * m2[5];
- pOut.mat[4] = m1[1] * m2[3] + m1[4] * m2[4] + m1[7] * m2[5];
- pOut.mat[5] = m1[2] * m2[3] + m1[5] * m2[4] + m1[8] * m2[5];
-
- pOut.mat[6] = m1[0] * m2[6] + m1[3] * m2[7] + m1[6] * m2[8];
- pOut.mat[7] = m1[1] * m2[6] + m1[4] * m2[7] + m1[7] * m2[8];
- pOut.mat[8] = m1[2] * m2[6] + m1[5] * m2[7] + m1[8] * m2[8];
-
- return pOut;
-};
-
-cc.kmMat3ScalarMultiply = function (pOut, pM, pFactor) {
- for (var i = 0; i < 9; i++) {
- pOut.mat[i] = pM.mat[i] * pFactor;
- }
- return pOut;
-};
-
-cc.kmMat3RotationAxisAngle = function (pOut, axis, radians) {
- var rcos = Math.cos(radians);
- var rsin = Math.sin(radians);
-
- pOut.mat[0] = rcos + axis.x * axis.x * (1 - rcos);
- pOut.mat[1] = axis.z * rsin + axis.y * axis.x * (1 - rcos);
- pOut.mat[2] = -axis.y * rsin + axis.z * axis.x * (1 - rcos);
-
- pOut.mat[3] = -axis.z * rsin + axis.x * axis.y * (1 - rcos);
- pOut.mat[4] = rcos + axis.y * axis.y * (1 - rcos);
- pOut.mat[5] = axis.x * rsin + axis.z * axis.y * (1 - rcos);
-
- pOut.mat[6] = axis.y * rsin + axis.x * axis.z * (1 - rcos);
- pOut.mat[7] = -axis.x * rsin + axis.y * axis.z * (1 - rcos);
- pOut.mat[8] = rcos + axis.z * axis.z * (1 - rcos);
-
- return pOut;
-};
-
-cc.kmMat3Assign = function (pOut, pIn) {
- cc.Assert(pOut != pIn, "Is same object"); //You have tried to self-assign!!
-
- for (var i = 0; i < 9; i++)
- pOut.mat[i] = pIn.mat[i];
- return pOut;
-};
-
-cc.kmMat3AreEqual = function (pMat1, pMat2) {
- if (pMat1 == pMat2)
- return true;
-
- for (var i = 0; i < 9; ++i) {
- if (!(pMat1.mat[i] + cc.kmEpsilon > pMat2.mat[i] &&
- pMat1.mat[i] - cc.kmEpsilon < pMat2.mat[i])) {
- return false;
+ cc.math.Matrix3 = function(mat3) {
+ if (mat3 && mat3.mat) {
+ this.mat = new Float32Array(mat3.mat);
+ } else {
+ this.mat = new Float32Array(9);
}
- }
-
- return true;
-};
-
-cc.kmMat3RotationX = function (pOut, radians) {
- /*
- | 1 0 0 |
- M = | 0 cos(A) -sin(A) |
- | 0 sin(A) cos(A) |
-
- */
-
- pOut.mat[0] = 1.0;
- pOut.mat[1] = 0.0;
- pOut.mat[2] = 0.0;
-
- pOut.mat[3] = 0.0;
- pOut.mat[4] = Math.cos(radians);
- pOut.mat[5] = Math.sin(radians);
-
- pOut.mat[6] = 0.0;
- pOut.mat[7] = -Math.sin(radians);
- pOut.mat[8] = Math.cos(radians);
-
- return pOut;
-};
-
-cc.kmMat3RotationY = function (pOut, radians) {
- /*
- | cos(A) 0 sin(A) |
- M = | 0 1 0 |
- | -sin(A) 0 cos(A) |
- */
-
- pOut.mat[0] = Math.cos(radians);
- pOut.mat[1] = 0.0;
- pOut.mat[2] = -Math.sin(radians);
-
- pOut.mat[3] = 0.0;
- pOut.mat[4] = 1.0;
- pOut.mat[5] = 0.0;
-
- pOut.mat[6] = Math.sin(radians);
- pOut.mat[7] = 0.0;
- pOut.mat[8] = Math.cos(radians);
-
- return pOut;
-};
-
-cc.kmMat3RotationZ = function (pOut, radians) {
- /*
- | cos(A) -sin(A) 0 |
- M = | sin(A) cos(A) 0 |
- | 0 0 1 |
+ };
+ cc.kmMat3 = cc.math.Matrix3;
+ var _p = cc.math.Matrix3.prototype;
+
+ /**
+ * Copy matrix.
+ * @fn fill
+ * @memberof cc.math.Matrix3
+ * @param {cc.math.Matrix3} mat3 Matrix to copy
+ * @return {cc.math.Matrix3} this
*/
- pOut.mat[0] = Math.cos(radians);
- pOut.mat[1] = -Math.sin(radians);
- pOut.mat[2] = 0.0;
-
- pOut.mat[3] = Math.sin(radians);
- pOut.mat[4] = Math.cos(radians);
- pOut.mat[5] = 0.0;
-
- pOut.mat[6] = 0.0;
- pOut.mat[7] = 0.0;
- pOut.mat[8] = 1.0;
-
- return pOut;
-};
-
-cc.kmMat3Rotation = function (pOut, radians) {
- /*
- | cos(A) -sin(A) 0 |
- M = | sin(A) cos(A) 0 |
- | 0 0 1 |
+ _p.fill = function(mat3) { //cc.kmMat3Fill
+ var mat = this.mat, matIn = mat3.mat;
+ mat[0] = matIn[0];
+ mat[1] = matIn[1];
+ mat[2] = matIn[2];
+ mat[3] = matIn[3];
+ mat[4] = matIn[4];
+ mat[5] = matIn[5];
+ mat[6] = matIn[6];
+ mat[7] = matIn[7];
+ mat[8] = matIn[8];
+ return this;
+ };
+
+ _p.adjugate = function(){ //= cc.kmMat3Adjugate
+ var mat = this.mat;
+ var m0 = mat[0], m1 = mat[1], m2 = mat[2], m3 = mat[3], m4 = mat[4],
+ m5 = mat[5], m6 = mat[6], m7 = mat[7], m8 = mat[8];
+ mat[0] = m4 * m8 - m5 * m7;
+ mat[1] = m2 * m7 - m1 * m8;
+ mat[2] = m1 * m5 - m2 * m4;
+ mat[3] = m5 * m6 - m3 * m8;
+ mat[4] = m0 * m8 - m2 * m6;
+ mat[5] = m2 * m3 - m0 * m5;
+ mat[6] = m3 * m7 - m4 * m6;
+
+ // XXX: pIn.mat[9] is invalid!
+ //mat[7] = m1 * m6 - pIn.mat[9] * m7;
+ mat[8] = m0 * m4 - m1 * m3;
+ return this;
+ };
+
+ /**
+ * Sets pOut to an identity matrix returns pOut
+ * @memberof cc.math.Matrix3
+ * @param {cc.math.Matrix3} pOut - A pointer to the matrix to set to identity
+ * @return {cc.math.Matrix3} this
*/
- pOut.mat[0] = Math.cos(radians);
- pOut.mat[1] = Math.sin(radians);
- pOut.mat[2] = 0.0;
-
- pOut.mat[3] = -Math.sin(radians);
- pOut.mat[4] = Math.cos(radians);
- pOut.mat[5] = 0.0;
-
- pOut.mat[6] = 0.0;
- pOut.mat[7] = 0.0;
- pOut.mat[8] = 1.0;
- return pOut;
-};
-
-cc.kmMat3Scaling = function (pOut, x, y) {
-// memset(pOut.mat, 0, sizeof(float) * 9);
- cc.kmMat3Identity(pOut);
- pOut.mat[0] = x;
- pOut.mat[4] = y;
-
- return pOut;
-};
-
-cc.kmMat3Translation = function (pOut, x, y) {
-// memset(pOut.mat, 0, sizeof(float) * 9);
- cc.kmMat3Identity(pOut);
- pOut.mat[6] = x;
- pOut.mat[7] = y;
-// pOut.mat[8] = 1.0;
-
- return pOut;
-};
-
-cc.kmMat3RotationQuaternion = function (pOut, pIn) {
- if (!pIn || !pOut)
- return null;
-
- // First row
- pOut.mat[0] = 1.0 - 2.0 * (pIn.y * pIn.y + pIn.z * pIn.z);
- pOut.mat[1] = 2.0 * (pIn.x * pIn.y - pIn.w * pIn.z);
- pOut.mat[2] = 2.0 * (pIn.x * pIn.z + pIn.w * pIn.y);
-
- // Second row
- pOut.mat[3] = 2.0 * (pIn.x * pIn.y + pIn.w * pIn.z);
- pOut.mat[4] = 1.0 - 2.0 * (pIn.x * pIn.x + pIn.z * pIn.z);
- pOut.mat[5] = 2.0 * (pIn.y * pIn.z - pIn.w * pIn.x);
-
- // Third row
- pOut.mat[6] = 2.0 * (pIn.x * pIn.z - pIn.w * pIn.y);
- pOut.mat[7] = 2.0 * (pIn.y * pIn.z + pIn.w * pIn.x);
- pOut.mat[8] = 1.0 - 2.0 * (pIn.x * pIn.x + pIn.y * pIn.y);
-
- return pOut;
-};
-
-cc.kmMat3RotationToAxisAngle = function (pAxis, radians, pIn) {
- /*Surely not this easy?*/
- var temp;
- cc.kmQuaternionRotationMatrix(temp, pIn);
- cc.kmQuaternionToAxisAngle(temp, pAxis, radians);
- return pAxis;
-};
-
-
-
-
-
+ _p.identity = function() { //cc.kmMat3Identity
+ var mat = this.mat;
+ mat[1] = mat[2] = mat[3] =
+ mat[5] = mat[6] = mat[7] = 0;
+ mat[0] = mat[4] = mat[8] = 1.0;
+ return this;
+ };
+
+ var tmpMatrix = new cc.math.Matrix3(); // internal matrix
+
+ _p.inverse = function(determinate){ //cc.kmMat3Inverse
+ if (determinate === 0.0)
+ return this;
+ tmpMatrix.assignFrom(this);
+ var detInv = 1.0 / determinate;
+ this.adjugate();
+ this.multiplyScalar(detInv);
+ return this;
+ };
+
+ _p.isIdentity = function(){ //= cc.kmMat3IsIdentity
+ var mat = this.mat;
+ return (mat[0] === 1 && mat[1] === 0 && mat[2] === 0
+ && mat[3] === 0 && mat[4] === 1 && mat[5] === 0
+ && mat[6] === 0 && mat[7] === 0 && mat[8] === 1);
+ };
+
+ _p.transpose = function(){ // cc.kmMat3Transpose
+ var mat = this.mat;
+ var m1 = mat[1], m2 = mat[2], m3 = mat[3], m5 = mat[5],
+ m6 = mat[6], m7 = mat[7];
+ // m0 = mat[0],m8 = mat[8], m4 = mat[4];
+ //mat[0] = m0;
+ //mat[8] = m8;
+ //mat[4] = m4
+ mat[1] = m3;
+ mat[2] = m6;
+ mat[3] = m1;
+ mat[5] = m7;
+ mat[6] = m2;
+ mat[7] = m5;
+ return this;
+ };
+
+ _p.determinant = function(){
+ var mat = this.mat;
+ /*
+ calculating the determinant following the rule of sarus,
+ | 0 3 6 | 0 3 |
+ m = | 1 4 7 | 1 4 |
+ | 2 5 8 | 2 5 |
+ now sum up the products of the diagonals going to the right (i.e. 0,4,8)
+ and subtract the products of the other diagonals (i.e. 2,4,6)
+ */
+ var output = mat[0] * mat[4] * mat[8] + mat[1] * mat[5] * mat[6] + mat[2] * mat[3] * mat[7];
+ output -= mat[2] * mat[4] * mat[6] + mat[0] * mat[5] * mat[7] + mat[1] * mat[3] * mat[8];
+ return output;
+ };
+
+ _p.multiply = function(mat3){
+ var m1 = this.mat, m2 = mat3.mat;
+ var a0 = m1[0], a1 = m1[1], a2 = m1[2], a3 = m1[3], a4 = m1[4], a5 = m1[5],
+ a6 = m1[6], a7 = m1[7], a8 = m1[8];
+ var b0 = m2[0], b1 = m2[1], b2 = m2[2], b3 = m2[3], b4 = m2[4], b5 = m2[5],
+ b6 = m2[6], b7 = m2[7], b8 = m2[8];
+
+ m1[0] = a0 * b0 + a3 * b1 + a6 * b2;
+ m1[1] = a1 * b0 + a4 * b1 + a7 * b2;
+ m1[2] = a2 * b0 + a5 * b1 + a8 * b2;
+
+ m1[3] = a2 * b0 + a5 * b1 + a8 * b2;
+ m1[4] = a1 * b3 + a4 * b4 + a7 * b5;
+ m1[5] = a2 * b3 + a5 * b4 + a8 * b5;
+
+ m1[6] = a0 * b6 + a3 * b7 + a6 * b8;
+ m1[7] = a1 * b6 + a4 * b7 + a7 * b8;
+ m1[8] = a2 * b6 + a5 * b7 + a8 * b8;
+ return this;
+ };
+
+ _p.multiplyScalar = function(factor) {
+ var mat = this.mat;
+ mat[0] *= factor;
+ mat[1] *= factor;
+ mat[2] *= factor;
+ mat[3] *= factor;
+ mat[4] *= factor;
+ mat[5] *= factor;
+ mat[6] *= factor;
+ mat[7] *= factor;
+ mat[8] *= factor;
+ return this;
+ };
+
+ cc.math.Matrix3.rotationAxisAngle = function(axis, radians) { //cc.kmMat3RotationAxisAngle
+ var rcos = Math.cos(radians), rsin = Math.sin(radians);
+ var retMat = new cc.math.Matrix3();
+ var mat = retMat.mat;
+
+ mat[0] = rcos + axis.x * axis.x * (1 - rcos);
+ mat[1] = axis.z * rsin + axis.y * axis.x * (1 - rcos);
+ mat[2] = -axis.y * rsin + axis.z * axis.x * (1 - rcos);
+
+ mat[3] = -axis.z * rsin + axis.x * axis.y * (1 - rcos);
+ mat[4] = rcos + axis.y * axis.y * (1 - rcos);
+ mat[5] = axis.x * rsin + axis.z * axis.y * (1 - rcos);
+
+ mat[6] = axis.y * rsin + axis.x * axis.z * (1 - rcos);
+ mat[7] = -axis.x * rsin + axis.y * axis.z * (1 - rcos);
+ mat[8] = rcos + axis.z * axis.z * (1 - rcos);
+
+ return retMat;
+ };
+
+ _p.assignFrom = function(matIn){ // cc.kmMat3Assign
+ if(this === matIn) {
+ cc.log("cc.math.Matrix3.assign(): current matrix equals matIn");
+ return this;
+ }
+ var mat = this.mat, m2 = matIn.mat;
+ mat[0] = m2[0];
+ mat[1] = m2[1];
+ mat[2] = m2[2];
+ mat[3] = m2[3];
+ mat[4] = m2[4];
+ mat[5] = m2[5];
+ mat[6] = m2[6];
+ mat[7] = m2[7];
+ mat[8] = m2[8];
+ return this;
+ };
+
+ _p.equals = function(mat3) {
+ if (this === mat3)
+ return true;
+ var EPSILON = cc.math.EPSILON,m1 = this.mat, m2 = mat3.mat;
+ for (var i = 0; i < 9; ++i) {
+ if (!(m1[i] + EPSILON > m2[i] && m1[i] - EPSILON < m2[i]))
+ return false;
+ }
+ return true;
+ };
+
+ cc.math.Matrix3.createByRotationX = function(radians) {
+ var retMat = new cc.math.Matrix3(), mat = retMat.mat;
+ mat[0] = 1.0;
+ mat[1] = 0.0;
+ mat[2] = 0.0;
+
+ mat[3] = 0.0;
+ mat[4] = Math.cos(radians);
+ mat[5] = Math.sin(radians);
+
+ mat[6] = 0.0;
+ mat[7] = -Math.sin(radians);
+ mat[8] = Math.cos(radians);
+ return retMat;
+ };
+
+ cc.math.Matrix3.createByRotationY = function(radians) {
+ /*
+ | cos(A) 0 sin(A) |
+ M = | 0 1 0 |
+ | -sin(A) 0 cos(A) |
+ */
+ var retMat = new cc.math.Matrix3(), mat = retMat.mat;
+ mat[0] = Math.cos(radians);
+ mat[1] = 0.0;
+ mat[2] = -Math.sin(radians);
+
+ mat[3] = 0.0;
+ mat[4] = 1.0;
+ mat[5] = 0.0;
+
+ mat[6] = Math.sin(radians);
+ mat[7] = 0.0;
+ mat[8] = Math.cos(radians);
+ return retMat;
+ };
+
+ cc.math.Matrix3.createByRotationZ = function(radians) {
+ /*
+ | cos(A) -sin(A) 0 |
+ M = | sin(A) cos(A) 0 |
+ | 0 0 1 |
+ */
+ var retMat = new cc.math.Matrix3(), mat = retMat.mat;
+ mat[0] = Math.cos(radians);
+ mat[1] = -Math.sin(radians);
+ mat[2] = 0.0;
+
+ mat[3] = Math.sin(radians);
+ mat[4] = Math.cos(radians);
+ mat[5] = 0.0;
+
+ mat[6] = 0.0;
+ mat[7] = 0.0;
+ mat[8] = 1.0;
+ return retMat;
+ };
+
+ cc.math.Matrix3.createByRotation = function(radians) {
+ /*
+ | cos(A) -sin(A) 0 |
+ M = | sin(A) cos(A) 0 |
+ | 0 0 1 |
+ */
+ var retMat = new cc.math.Matrix3(), mat = retMat.mat;
+ mat[0] = Math.cos(radians);
+ mat[1] = Math.sin(radians);
+ mat[2] = 0.0;
+
+ mat[3] = -Math.sin(radians);
+ mat[4] = Math.cos(radians);
+ mat[5] = 0.0;
+
+ mat[6] = 0.0;
+ mat[7] = 0.0;
+ mat[8] = 1.0;
+ return retMat;
+ };
+
+ cc.math.Matrix3.createByScale = function(x, y) {
+ var ret = new cc.math.Matrix3();
+ ret.identity();
+ ret.mat[0] = x;
+ ret.mat[4] = y;
+ return ret;
+ };
+
+ cc.math.Matrix3.createByTranslation = function(x, y){
+ var ret = new cc.math.Matrix3();
+ ret.identity();
+ ret.mat[6] = x;
+ ret.mat[7] = y;
+ return ret;
+ };
+
+ cc.math.Matrix3.createByQuaternion = function(quaternion) { //cc.kmMat3RotationQuaternion
+ if(!quaternion)
+ return null;
+
+ var ret = new cc.math.Matrix3(), mat = ret.mat;
+ // First row
+ mat[0] = 1.0 - 2.0 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z);
+ mat[1] = 2.0 * (quaternion.x * quaternion.y - quaternion.w * quaternion.z);
+ mat[2] = 2.0 * (quaternion.x * quaternion.z + quaternion.w * quaternion.y);
+
+ // Second row
+ mat[3] = 2.0 * (quaternion.x * quaternion.y + quaternion.w * quaternion.z);
+ mat[4] = 1.0 - 2.0 * (quaternion.x * quaternion.x + quaternion.z * quaternion.z);
+ mat[5] = 2.0 * (quaternion.y * quaternion.z - quaternion.w * quaternion.x);
+
+ // Third row
+ mat[6] = 2.0 * (quaternion.x * quaternion.z - quaternion.w * quaternion.y);
+ mat[7] = 2.0 * (quaternion.y * quaternion.z + quaternion.w * quaternion.x);
+ mat[8] = 1.0 - 2.0 * (quaternion.x * quaternion.x + quaternion.y * quaternion.y);
+ return ret;
+ };
+
+ _p.rotationToAxisAngle = function() { //cc.kmMat3RotationToAxisAngle
+ return cc.math.Quaternion.rotationMatrix(this).toAxisAndAngle();
+ }
+})(cc);
diff --git a/cocos2d/kazmath/mat4.js b/cocos2d/kazmath/mat4.js
index 74e88b88e9..35a56e1050 100644
--- a/cocos2d/kazmath/mat4.js
+++ b/cocos2d/kazmath/mat4.js
@@ -1,5 +1,7 @@
-/*
- Copyright (c) 2010-2012 cocos2d-x.org
+/**
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,776 +26,986 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- A 4x4 matrix
-
- mat =
- | 0 4 8 12 |
- | 1 5 9 13 |
- | 2 6 10 14 |
- | 3 7 11 15 |
- */
-cc.kmMat4 = function () {
- this.mat = new Float32Array([0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0]);
-};
+(function(cc) {
+ /**
+ *
+ * A 4x4 matrix
+ *
+ * mat =
+ * | 0 4 8 12 |
+ * | 1 5 9 13 |
+ * | 2 6 10 14 |
+ * | 3 7 11 15 |
+ *
+ * @class
+ * @param {cc.math.Matrix4} [mat4]
+ */
+ cc.math.Matrix4 = function (mat4) {
+ if(mat4 && mat4.mat){
+ this.mat = new Float32Array(mat4.mat);
+ } else {
+ this.mat = new Float32Array(16);
+ }
+ };
+ cc.kmMat4 = cc.math.Matrix4;
+ var proto = cc.math.Matrix4.prototype;
-/**
- * Fills a kmMat4 structure with the values from a 16 element array of floats
- * @Params pOut - A pointer to the destination matrix
- * @Params pMat - A 16 element array of floats
- * @Return Returns pOut so that the call can be nested
- */
-cc.kmMat4Fill = function (pOut, pMat) {
- pOut.mat[0] = pOut.mat[1] = pOut.mat[2] =pOut.mat[3] =
- pOut.mat[4] =pOut.mat[5] =pOut.mat[6] =pOut.mat[7] =
- pOut.mat[8] =pOut.mat[9] =pOut.mat[10] =pOut.mat[11] =
- pOut.mat[12] =pOut.mat[13] =pOut.mat[14] =pOut.mat[15] =pMat;
-};
+ /**
+ * Fills a cc.math.Matrix4 structure with the values from a 16 element array of floats
+ * @param {Array} scalarArr
+ */
+ proto.fill = function(scalarArr){ //cc.kmMat4Fill
+ var mat = this.mat;
+ for(var i = 0; i < 16; i++){
+ mat[i] = scalarArr[i];
+ }
+ return this;
+ };
-/**
- * Sets pOut to an identity matrix returns pOut
- * @Params pOut - A pointer to the matrix to set to identity
- * @Return Returns pOut so that the call can be nested
- */
-cc.kmMat4Identity = function (pOut) {
- pOut.mat[1] = pOut.mat[2] = pOut.mat[3]
- = pOut.mat[4] = pOut.mat[6] = pOut.mat[7]
- = pOut.mat[8] = pOut.mat[9] = pOut.mat[11]
- = pOut.mat[12] = pOut.mat[13] = pOut.mat[14] = 0;
- pOut.mat[0] = pOut.mat[5] = pOut.mat[10] = pOut.mat[15] = 1.0;
- return pOut;
-};
-
-cc.kmMat4._get = function (pIn, row, col) {
- return pIn.mat[row + 4 * col];
-};
-
-cc.kmMat4._set = function (pIn, row, col, value) {
- pIn.mat[row + 4 * col] = value;
-};
-
-cc.kmMat4._swap = function (pIn, r1, c1, r2, c2) {
- var tmp = cc.kmMat4._get(pIn, r1, c1);
- cc.kmMat4._set(pIn, r1, c1, cc.kmMat4._get(pIn, r2, c2));
- cc.kmMat4._set(pIn, r2, c2, tmp);
-};
-
-//Returns an upper and a lower triangular matrix which are L and R in the Gauss algorithm
-cc.kmMat4._gaussj = function (a, b) {
- var i, icol = 0, irow = 0, j, k, l, ll, n = 4, m = 4;
- var big, dum, pivinv;
- var indxc = [0, 0, 0, 0];
- var indxr = [0, 0, 0, 0];
- var ipiv = [0, 0, 0, 0];
-
- /* for (j = 0; j < n; j++) {
- ipiv[j] = 0;
- }*/
-
- for (i = 0; i < n; i++) {
- big = 0.0;
- for (j = 0; j < n; j++) {
- if (ipiv[j] != 1) {
- for (k = 0; k < n; k++) {
- if (ipiv[k] == 0) {
- if (Math.abs(cc.kmMat4._get(a, j, k)) >= big) {
- big = Math.abs(cc.kmMat4._get(a, j, k));
- irow = j;
- icol = k;
+ /**
+ * Sets pOut to an identity matrix returns pOut
+ * @param pOut - A pointer to the matrix to set to identity
+ * @returns Returns pOut so that the call can be nested
+ */
+ cc.kmMat4Identity = function (pOut) {
+ var mat = pOut.mat;
+ mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7]
+ = mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
+ mat[0] = mat[5] = mat[10] = mat[15] = 1.0;
+ return pOut;
+ };
+
+ /**
+ * Sets matrix to identity value.
+ * @returns {cc.math.Matrix4}
+ */
+ proto.identity = function(){
+ var mat = this.mat;
+ mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7]
+ = mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
+ mat[0] = mat[5] = mat[10] = mat[15] = 1.0;
+ return this;
+ };
+
+ proto.get = function(row, col){
+ return this.mat[row + 4 * col];
+ };
+
+ proto.set = function(row, col, value){
+ this.mat[row + 4 * col] = value;
+ };
+
+ proto.swap = function(r1, c1, r2, c2) {
+/* var tmp = this.get(r1, c1);
+ this.set(r1, c1, this.get(r2, c2));
+ this.set(r2, c2, tmp);*/
+ var mat = this.mat, tmp = mat[r1 + 4 * c1];
+ mat[r1 + 4 * c1] = mat[r2 + 4 * c2];
+ mat[r2 + 4 * c2] = tmp;
+ };
+
+ //Returns an upper and a lower triangular matrix which are L and R in the Gauss algorithm
+ cc.math.Matrix4._gaussj = function (a, b) {
+ var i, icol = 0, irow = 0, j, k, l, ll, n = 4, m = 4, selElement;
+ var big, dumb, pivinv;
+ var indxc = [0, 0, 0, 0], indxr = [0, 0, 0, 0], ipiv = [0, 0, 0, 0];
+
+ /* for (j = 0; j < n; j++) {
+ ipiv[j] = 0;
+ }*/
+
+ for (i = 0; i < n; i++) {
+ big = 0.0;
+ for (j = 0; j < n; j++) {
+ if (ipiv[j] !== 1) {
+ for (k = 0; k < n; k++) {
+ if (ipiv[k] === 0) {
+ selElement = Math.abs(a.get(j, k));
+ if (selElement >= big) {
+ big = selElement;
+ irow = j;
+ icol = k;
+ }
}
}
}
}
- }
- ++(ipiv[icol]);
- if (irow != icol) {
- for (l = 0; l < n; l++)
- cc.kmMat4._swap(a, irow, l, icol, l);
- for (l = 0; l < m; l++)
- cc.kmMat4._swap(b, irow, l, icol, l);
- }
- indxr[i] = irow;
- indxc[i] = icol;
- if (cc.kmMat4._get(a, icol, icol) == 0.0)
- return cc.KM_FALSE;
-
- pivinv = 1.0 / cc.kmMat4._get(a, icol, icol);
- cc.kmMat4._set(a, icol, icol, 1.0);
- for (l = 0; l < n; l++)
- cc.kmMat4._set(a, icol, l, cc.kmMat4._get(a, icol, l) * pivinv);
-
- for (l = 0; l < m; l++)
- cc.kmMat4._set(b, icol, l, cc.kmMat4._get(b, icol, l) * pivinv);
-
- for (ll = 0; ll < n; ll++) {
- if (ll != icol) {
- dum = cc.kmMat4._get(a, ll, icol);
- cc.kmMat4._set(a, ll, icol, 0.0);
+ ++(ipiv[icol]);
+ if (irow !== icol) {
for (l = 0; l < n; l++)
- cc.kmMat4._set(a, ll, l, cc.kmMat4._get(a, ll, l) - cc.kmMat4._get(a, icol, l) * dum);
-
+ a.swap(irow, l, icol, l);
for (l = 0; l < m; l++)
- cc.kmMat4._set(b, ll, l, cc.kmMat4._get(a, ll, l) - cc.kmMat4._get(b, icol, l) * dum);
+ b.swap(irow, l, icol, l);
}
- }
- }
-// This is the end of the main loop over columns of the reduction. It only remains to unscram-
-// ble the solution in view of the column interchanges. We do this by interchanging pairs of
-// columns in the reverse order that the permutation was built up.
- for (l = n - 1; l >= 0; l--) {
- if (indxr[l] != indxc[l]) {
- for (k = 0; k < n; k++)
- cc.kmMat4._swap(a, k, indxr[l], k, indxc[l]);
- }
- }
- return cc.KM_TRUE;
-};
-
-cc.kmMat4._identity =
- new Float32Array([1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0]);
-
-/**
- * Calculates the inverse of pM and stores the result in
- * pOut.
- * @Return Returns NULL if there is no inverse, else pOut
- */
-cc.kmMat4Inverse = function (pOut, pM) {
- var inv = new cc.kmMat4();
- var tmp = new cc.kmMat4();
-
- cc.kmMat4Assign(inv, pM);
- cc.kmMat4Identity(tmp);
-
- if (cc.kmMat4._gaussj(inv, tmp) == cc.KM_FALSE)
- return null;
-
- cc.kmMat4Assign(pOut, inv);
- return pOut;
-};
+ indxr[i] = irow;
+ indxc[i] = icol;
+ if (a.get(icol, icol) === 0.0)
+ return false;
-/**
- * Returns KM_TRUE if pIn is an identity matrix
- * KM_FALSE otherwise
- */
-cc.kmMat4IsIdentity = function (pIn) {
- for (var i = 0; i < 16; i++) {
- if (cc.kmMat4._identity[i] != pIn.mat[i])
- return false;
- }
- return true;
-};
+ pivinv = 1.0 / a.get(icol, icol);
+ a.set(icol, icol, 1.0);
+ for (l = 0; l < n; l++)
+ a.set(icol, l, a.get(icol, l) * pivinv);
-/**
- * Sets pOut to the transpose of pIn, returns pOut
- */
-cc.kmMat4Transpose = function (pOut, pIn) {
- var x, z, outArr = pOut.mat,inArr = pIn.mat;
- for (z = 0; z < 4; ++z) {
- for (x = 0; x < 4; ++x)
- outArr[(z * 4) + x] = inArr[(x * 4) + z];
- }
- return pOut;
-};
+ for (l = 0; l < m; l++)
+ b.set(icol, l, b.get(icol, l) * pivinv);
-/**
- * Multiplies pM1 with pM2, stores the result in pOut, returns pOut
- */
-cc.kmMat4Multiply = function (pOut, pM1, pM2) {
- // Cache the matrix values (makes for huge speed increases!)
- var outArray = pOut.mat;
- var a00 = pM1.mat[0], a01 = pM1.mat[1], a02 = pM1.mat[2], a03 = pM1.mat[3];
- var a10 = pM1.mat[4], a11 = pM1.mat[5], a12 = pM1.mat[6], a13 = pM1.mat[7];
- var a20 = pM1.mat[8], a21 = pM1.mat[9], a22 = pM1.mat[10], a23 = pM1.mat[11];
- var a30 = pM1.mat[12], a31 = pM1.mat[13], a32 = pM1.mat[14], a33 = pM1.mat[15];
-
- var b00 = pM2.mat[0], b01 = pM2.mat[1], b02 = pM2.mat[2], b03 = pM2.mat[3];
- var b10 = pM2.mat[4], b11 = pM2.mat[5], b12 = pM2.mat[6], b13 = pM2.mat[7];
- var b20 = pM2.mat[8], b21 = pM2.mat[9], b22 = pM2.mat[10], b23 = pM2.mat[11];
- var b30 = pM2.mat[12], b31 = pM2.mat[13], b32 = pM2.mat[14], b33 = pM2.mat[15];
-
- outArray[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
- outArray[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
- outArray[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
- outArray[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
- outArray[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
- outArray[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
- outArray[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
- outArray[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
- outArray[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
- outArray[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
- outArray[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
- outArray[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
- outArray[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
- outArray[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
- outArray[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
- outArray[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
- return pOut;
-};
-
-cc.getMat4MultiplyValue = function (pM1, pM2) {
- var m1 = pM1.mat, m2 = pM2.mat;
- var mat = new Float32Array(16);
-
- mat[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
- mat[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
- mat[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
- mat[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
-
- mat[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
- mat[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
- mat[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
- mat[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
-
- mat[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
- mat[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
- mat[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
- mat[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
-
- mat[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
- mat[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
- mat[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
- mat[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
-
- return mat;
-};
-
-cc.getMat4MultiplyWithMat4 = function (pM1, pM2, swapMat) {
- var m1 = pM1.mat, m2 = pM2.mat;
- var mat = swapMat.mat;
-
- mat[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
- mat[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
- mat[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
- mat[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
-
- mat[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
- mat[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
- mat[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
- mat[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
-
- mat[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
- mat[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
- mat[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
- mat[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
-
- mat[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
- mat[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
- mat[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
- mat[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
-
- return swapMat.mat;
-};
+ for (ll = 0; ll < n; ll++) {
+ if (ll !== icol) {
+ dumb = a.get(ll, icol);
+ a.set(ll, icol, 0.0);
+ for (l = 0; l < n; l++)
+ a.set(ll, l, a.get(ll, l) - a.get(icol, l) * dumb);
-/**
- * Assigns the value of pIn to pOut
- */
-cc.kmMat4Assign = function (pOut, pIn) {
- //cc.Assert(pOut != pIn, "You have tried to self-assign!!");
- if(pOut == pIn)
- return;
- var outArr = pOut.mat;
- var inArr = pIn.mat;
-
- outArr[0] = inArr[0];
- outArr[1] = inArr[1];
- outArr[2] = inArr[2];
- outArr[3] = inArr[3];
-
- outArr[4] = inArr[4];
- outArr[5] = inArr[5];
- outArr[6] = inArr[6];
- outArr[7] = inArr[7];
-
- outArr[8] = inArr[8];
- outArr[9] = inArr[9];
- outArr[10] = inArr[10];
- outArr[11] = inArr[11];
-
- outArr[12] = inArr[12];
- outArr[13] = inArr[13];
- outArr[14] = inArr[14];
- outArr[15] = inArr[15];
- return pOut;
-};
-
-/**
- * Returns KM_TRUE if the 2 matrices are equal (approximately)
- */
-cc.kmMat4AreEqual = function (pMat1, pMat2) {
- cc.Assert(pMat1 != pMat2, "You are comparing the same thing!");
- for (var i = 0; i < 16; i++) {
- if (!(pMat1.mat[i] + cc.kmEpsilon > pMat2.mat[i] &&
- pMat1.mat[i] - cc.kmEpsilon < pMat2.mat[i])) {
- return false;
+ for (l = 0; l < m; l++)
+ b.set(ll, l, a.get(ll, l) - b.get(icol, l) * dumb);
+ }
+ }
}
- }
- return true;
-};
-
-/**
- * Builds an X-axis rotation matrix and stores it in pOut, returns pOut
- */
-cc.kmMat4RotationX = function (pOut, radians) {
- /*
- | 1 0 0 0 |
- M = | 0 cos(A) -sin(A) 0 |
- | 0 sin(A) cos(A) 0 |
- | 0 0 0 1 |
-
+ // This is the end of the main loop over columns of the reduction. It only remains to unscram-
+ // ble the solution in view of the column interchanges. We do this by interchanging pairs of
+ // columns in the reverse order that the permutation was built up.
+ for (l = n - 1; l >= 0; l--) {
+ if (indxr[l] !== indxc[l]) {
+ for (k = 0; k < n; k++)
+ a.swap(k, indxr[l], k, indxc[l]);
+ }
+ }
+ return true;
+ };
+
+ var identityMatrix = new cc.math.Matrix4().identity();
+ /**
+ * Calculates the inverse of pM and stores the result in pOut.
+ * Please use matrix4's inverse function instead.
+ * @Return Returns NULL if there is no inverse, else pOut
*/
+ cc.kmMat4Inverse = function (pOut, pM) {
+ var inv = new cc.math.Matrix4(pM);
+ var tmp = new cc.math.Matrix4(identityMatrix);
+ if (cc.math.Matrix4._gaussj(inv, tmp) === false)
+ return null;
+ pOut.assignFrom(inv);
+ return pOut;
+ };
+
+ /**
+ * Calculates the inverse of current matrix.
+ * @returns {cc.math.Matrix4} Returns null if there is no inverse, else returns a new inverse matrix object
+ */
+ proto.inverse = function(){ //cc.kmMat4Inverse
+ var inv = new cc.math.Matrix4(this);
+ var tmp = new cc.math.Matrix4(identityMatrix);
+ if (cc.math.Matrix4._gaussj(inv, tmp) === false)
+ return null;
+ return inv;
+ };
+
+ /**
+ * Returns true if current matrix is an identity matrix, false otherwise
+ */
+ proto.isIdentity = function () { // cc.kmMat4IsIdentity
+ var mat = this.mat;
+ return (mat[0] === 1 && mat[1] === 0 && mat[2] === 0 && mat[3] === 0
+ && mat[4] === 0 && mat[5] === 1 && mat[6] === 0 && mat[7] === 0
+ && mat[8] === 0 && mat[9] === 0 && mat[10] === 1 && mat[11] === 0
+ && mat[12] === 0 && mat[13] === 0 && mat[14] === 0 && mat[15] === 1);
+ };
+
+ /**
+ * transpose the current matrix
+ */
+ proto.transpose = function() { // cc.kmMat4Transpose
+ var mat = this.mat;
+ var m1 = mat[1], m2 = mat[2], m3 = mat[3],
+ m4 = mat[4], m6 = mat[6], m7 = mat[7],
+ m8 = mat[8], m9 = mat[9], m11 = mat[11],
+ m12 = mat[12], m13 = mat[13], m14 = mat[14];
+ mat[1] = m4;
+ mat[2] = m8;
+ mat[3] = m12;
+
+ mat[4] = m1;
+ mat[6] = m9;
+ mat[7] = m13;
+
+ mat[8] = m2;
+ mat[9] = m6;
+ mat[11] = m14;
+
+ mat[12] = m3;
+ mat[13] = m7;
+ mat[14] = m11;
+ return this;
+ };
+
+ /**
+ * Multiplies pM1 with pM2, stores the result in pOut, returns pOut
+ */
+ cc.kmMat4Multiply = function (pOut, pM1, pM2) {
+ // Cache the matrix values (makes for huge speed increases!)
+ var outArray = pOut.mat, mat1 = pM1.mat, mat2 = pM2.mat;
+ var a00 = mat1[0], a01 = mat1[1], a02 = mat1[2], a03 = mat1[3];
+ var a10 = mat1[4], a11 = mat1[5], a12 = mat1[6], a13 = mat1[7];
+ var a20 = mat1[8], a21 = mat1[9], a22 = mat1[10], a23 = mat1[11];
+ var a30 = mat1[12], a31 = mat1[13], a32 = mat1[14], a33 = mat1[15];
+
+ var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3];
+ var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7];
+ var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11];
+ var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
+
+ outArray[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
+ outArray[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
+ outArray[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
+ outArray[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
+ outArray[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
+ outArray[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
+ outArray[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
+ outArray[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
+ outArray[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
+ outArray[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
+ outArray[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
+ outArray[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
+ outArray[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
+ outArray[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
+ outArray[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
+ outArray[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
+ return pOut;
+ };
+
+ /**
+ * current matrix multiplies with other matrix mat4
+ * @param {cc.math.Matrix4} mat4
+ * @returns {cc.math.Matrix4}
+ */
+ proto.multiply = function(mat4){
+ // Cache the matrix values (makes for huge speed increases!)
+ var mat = this.mat, mat2 = mat4.mat;
+ 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];
+
+ var b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3];
+ var b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7];
+ var b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11];
+ var b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
+
+ mat[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
+ mat[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
+ mat[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
+ mat[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
+ mat[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
+ mat[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
+ mat[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
+ mat[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
+ mat[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
+ mat[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
+ mat[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
+ mat[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
+ mat[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
+ mat[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
+ mat[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
+ mat[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
+ return this;
+ };
+
+ cc.getMat4MultiplyValue = function (pM1, pM2) {
+ var m1 = pM1.mat, m2 = pM2.mat;
+ var mat = new Float32Array(16);
+
+ mat[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
+ mat[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
+ mat[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
+ mat[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
+
+ mat[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
+ mat[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
+ mat[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
+ mat[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
+
+ mat[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
+ mat[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
+ mat[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
+ mat[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
+
+ mat[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
+ mat[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
+ mat[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
+ mat[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
+
+ return mat;
+ };
+
+ /**
+ * Assigns the value of pIn to pOut
+ */
+ cc.kmMat4Assign = function (pOut, pIn) {
+ if (pOut === pIn) {
+ cc.log("cc.kmMat4Assign(): pOut equals pIn");
+ return pOut;
+ }
- pOut.mat[0] = 1.0;
- pOut.mat[1] = 0.0;
- pOut.mat[2] = 0.0;
- pOut.mat[3] = 0.0;
-
- pOut.mat[4] = 0.0;
- pOut.mat[5] = Math.cos(radians);
- pOut.mat[6] = Math.sin(radians);
- pOut.mat[7] = 0.0;
-
- pOut.mat[8] = 0.0;
- pOut.mat[9] = -Math.sin(radians);
- pOut.mat[10] = Math.cos(radians);
- pOut.mat[11] = 0.0;
-
- pOut.mat[12] = 0.0;
- pOut.mat[13] = 0.0;
- pOut.mat[14] = 0.0;
- pOut.mat[15] = 1.0;
-
- return pOut;
-};
-
-/**
- * Builds a rotation matrix using the rotation around the Y-axis
- * The result is stored in pOut, pOut is returned.
- */
-cc.kmMat4RotationY = function (pOut, radians) {
- /*
- | cos(A) 0 sin(A) 0 |
- M = | 0 1 0 0 |
- | -sin(A) 0 cos(A) 0 |
- | 0 0 0 1 |
- */
- pOut.mat[0] = Math.cos(radians);
- pOut.mat[1] = 0.0;
- pOut.mat[2] = -Math.sin(radians);
- pOut.mat[3] = 0.0;
-
- pOut.mat[4] = 0.0;
- pOut.mat[5] = 1.0;
- pOut.mat[6] = 0.0;
- pOut.mat[7] = 0.0;
-
- pOut.mat[8] = Math.sin(radians);
- pOut.mat[9] = 0.0;
- pOut.mat[10] = Math.cos(radians);
- pOut.mat[11] = 0.0;
-
- pOut.mat[12] = 0.0;
- pOut.mat[13] = 0.0;
- pOut.mat[14] = 0.0;
- pOut.mat[15] = 1.0;
-
- return pOut;
-};
-
-/**
- * Builds a rotation matrix around the Z-axis. The resulting
- * matrix is stored in pOut. pOut is returned.
- */
-cc.kmMat4RotationZ = function (pOut, radians) {
- /*
- | cos(A) -sin(A) 0 0 |
- M = | sin(A) cos(A) 0 0 |
- | 0 0 1 0 |
- | 0 0 0 1 |
- */
- pOut.mat[0] = Math.cos(radians);
- pOut.mat[1] = Math.sin(radians);
- pOut.mat[2] = 0.0;
- pOut.mat[3] = 0.0;
-
- pOut.mat[4] = -Math.sin(radians);
- pOut.mat[5] = Math.cos(radians);
- pOut.mat[6] = 0.0;
- pOut.mat[7] = 0.0;
-
- pOut.mat[8] = 0.0;
- pOut.mat[9] = 0.0;
- pOut.mat[10] = 1.0;
- pOut.mat[11] = 0.0;
-
- pOut.mat[12] = 0.0;
- pOut.mat[13] = 0.0;
- pOut.mat[14] = 0.0;
- pOut.mat[15] = 1.0;
-
- return pOut;
-};
-
-/**
- * Builds a rotation matrix from pitch, yaw and roll. The resulting
- * matrix is stored in pOut and pOut is returned
- */
-cc.kmMat4RotationPitchYawRoll = function (pOut, pitch, yaw, roll) {
- var cr = Math.cos(pitch);
- var sr = Math.sin(pitch);
- var cp = Math.cos(yaw);
- var sp = Math.sin(yaw);
- var cy = Math.cos(roll);
- var sy = Math.sin(roll);
- var srsp = sr * sp;
- var crsp = cr * sp;
-
- pOut.mat[0] = cp * cy;
- pOut.mat[4] = cp * sy;
- pOut.mat[8] = -sp;
-
- pOut.mat[1] = srsp * cy - cr * sy;
- pOut.mat[5] = srsp * sy + cr * cy;
- pOut.mat[9] = sr * cp;
-
- pOut.mat[2] = crsp * cy + sr * sy;
- pOut.mat[6] = crsp * sy - sr * cy;
- pOut.mat[10] = cr * cp;
-
- pOut.mat[3] = pOut.mat[7] = pOut.mat[11] = 0.0;
- pOut.mat[15] = 1.0;
-
- return pOut;
-};
-
-/** Converts a quaternion to a rotation matrix,
- * the result is stored in pOut, returns pOut
- */
-cc.kmMat4RotationQuaternion = function (pOut, pQ) {
- pOut.mat[0] = 1.0 - 2.0 * (pQ.y * pQ.y + pQ.z * pQ.z );
- pOut.mat[1] = 2.0 * (pQ.x * pQ.y + pQ.z * pQ.w);
- pOut.mat[2] = 2.0 * (pQ.x * pQ.z - pQ.y * pQ.w);
- pOut.mat[3] = 0.0;
-
- // Second row
- pOut.mat[4] = 2.0 * ( pQ.x * pQ.y - pQ.z * pQ.w );
- pOut.mat[5] = 1.0 - 2.0 * ( pQ.x * pQ.x + pQ.z * pQ.z );
- pOut.mat[6] = 2.0 * (pQ.z * pQ.y + pQ.x * pQ.w );
- pOut.mat[7] = 0.0;
-
- // Third row
- pOut.mat[8] = 2.0 * ( pQ.x * pQ.z + pQ.y * pQ.w );
- pOut.mat[9] = 2.0 * ( pQ.y * pQ.z - pQ.x * pQ.w );
- pOut.mat[10] = 1.0 - 2.0 * ( pQ.x * pQ.x + pQ.y * pQ.y );
- pOut.mat[11] = 0.0;
-
- // Fourth row
- pOut.mat[12] = 0;
- pOut.mat[13] = 0;
- pOut.mat[14] = 0;
- pOut.mat[15] = 1.0;
-
- return pOut;
-};
-
-/** Build a 4x4 OpenGL transformation matrix using a 3x3 rotation matrix,
- * and a 3d vector representing a translation. Assign the result to pOut,
- * pOut is also returned.
- */
-cc.kmMat4RotationTranslation = function (pOut, rotation, translation) {
- pOut.mat[0] = rotation.mat[0];
- pOut.mat[1] = rotation.mat[1];
- pOut.mat[2] = rotation.mat[2];
- pOut.mat[3] = 0.0;
-
- pOut.mat[4] = rotation.mat[3];
- pOut.mat[5] = rotation.mat[4];
- pOut.mat[6] = rotation.mat[5];
- pOut.mat[7] = 0.0;
-
- pOut.mat[8] = rotation.mat[6];
- pOut.mat[9] = rotation.mat[7];
- pOut.mat[10] = rotation.mat[8];
- pOut.mat[11] = 0.0;
-
- pOut.mat[12] = translation.x;
- pOut.mat[13] = translation.y;
- pOut.mat[14] = translation.z;
- pOut.mat[15] = 1.0;
-
- return pOut;
-};
-
-/** Builds a scaling matrix */
-cc.kmMat4Scaling = function (pOut, x, y, z) {
- pOut.mat[0] = x;
- pOut.mat[5] = y;
- pOut.mat[10] = z;
- pOut.mat[15] = 1.0;
- pOut.mat[1] = pOut.mat[2] = pOut.mat[3] =
- pOut.mat[4] = pOut.mat[6] = pOut.mat[7] =
- pOut.mat[8] = pOut.mat[9] = pOut.mat[11] =
- pOut.mat[12] = pOut.mat[13] = pOut.mat[14] = 0;
- return pOut;
-};
-
-/**
- * Builds a translation matrix. All other elements in the matrix
- * will be set to zero except for the diagonal which is set to 1.0
- */
-cc.kmMat4Translation = function (pOut, x, y, z) {
- //FIXME: Write a test for this
- pOut.mat[0] = pOut.mat[5] = pOut.mat[10] = pOut.mat[15] = 1.0;
- pOut.mat[1] = pOut.mat[2] = pOut.mat[3] =
- pOut.mat[4] = pOut.mat[6] = pOut.mat[7] =
- pOut.mat[8] = pOut.mat[9] = pOut.mat[11] = 0.0;
- pOut.mat[12] = x;
- pOut.mat[13] = y;
- pOut.mat[14] = z;
- return pOut;
-};
-
-/**
- * Get the up vector from a matrix. pIn is the matrix you
- * wish to extract the vector from. pOut is a pointer to the
- * kmVec3 structure that should hold the resulting vector
- */
-cc.kmMat4GetUpVec3 = function (pOut, pIn) {
- pOut.x = pIn.mat[4];
- pOut.y = pIn.mat[5];
- pOut.z = pIn.mat[6];
- cc.kmVec3Normalize(pOut, pOut);
- return pOut;
-};
-
-/** Extract the right vector from a 4x4 matrix. The result is
- * stored in pOut. Returns pOut.
- */
-cc.kmMat4GetRightVec3 = function (pOut, pIn) {
- pOut.x = pIn.mat[0];
- pOut.y = pIn.mat[1];
- pOut.z = pIn.mat[2];
- cc.kmVec3Normalize(pOut, pOut);
- return pOut;
-};
-
-/**
- * Extract the forward vector from a 4x4 matrix. The result is
- * stored in pOut. Returns pOut.
- */
-cc.kmMat4GetForwardVec3 = function (pOut, pIn) {
- pOut.x = pIn.mat[8];
- pOut.y = pIn.mat[9];
- pOut.z = pIn.mat[10];
- cc.kmVec3Normalize(pOut, pOut);
- return pOut;
-};
-
-/**
- * Creates a perspective projection matrix in the
- * same way as gluPerspective
- */
-cc.kmMat4PerspectiveProjection = function (pOut, fovY, aspect, zNear, zFar) {
- var r = cc.kmDegreesToRadians(fovY / 2);
- var deltaZ = zFar - zNear;
- var s = Math.sin(r);
-
- if (deltaZ == 0 || s == 0 || aspect == 0)
- return null;
-
- //cos(r) / sin(r) = cot(r)
- var cotangent = Math.cos(r) / s;
-
- cc.kmMat4Identity(pOut);
- pOut.mat[0] = cotangent / aspect;
- pOut.mat[5] = cotangent;
- pOut.mat[10] = -(zFar + zNear) / deltaZ;
- pOut.mat[11] = -1;
- pOut.mat[14] = -2 * zNear * zFar / deltaZ;
- pOut.mat[15] = 0;
-
- return pOut;
-};
-
-/** Creates an orthographic projection matrix like glOrtho */
-cc.kmMat4OrthographicProjection = function (pOut, left, right, bottom, top, nearVal, farVal) {
- cc.kmMat4Identity(pOut);
- pOut.mat[0] = 2 / (right - left);
- pOut.mat[5] = 2 / (top - bottom);
- pOut.mat[10] = -2 / (farVal - nearVal);
- pOut.mat[12] = -((right + left) / (right - left));
- pOut.mat[13] = -((top + bottom) / (top - bottom));
- pOut.mat[14] = -((farVal + nearVal) / (farVal - nearVal));
- return pOut;
-};
-
-/**
- * Builds a translation matrix in the same way as gluLookAt()
- * the resulting matrix is stored in pOut. pOut is returned.
- */
-cc.kmMat4LookAt = function (pOut, pEye, pCenter, pUp) {
- var f = new cc.kmVec3(), up = new cc.kmVec3(), s = new cc.kmVec3(), u = new cc.kmVec3();
- var translate = new cc.kmMat4();
-
- cc.kmVec3Subtract(f, pCenter, pEye);
- cc.kmVec3Normalize(f, f);
-
- cc.kmVec3Assign(up, pUp);
- cc.kmVec3Normalize(up, up);
-
- cc.kmVec3Cross(s, f, up);
- cc.kmVec3Normalize(s, s);
-
- cc.kmVec3Cross(u, s, f);
- cc.kmVec3Normalize(s, s);
-
- cc.kmMat4Identity(pOut);
-
- pOut.mat[0] = s.x;
- pOut.mat[4] = s.y;
- pOut.mat[8] = s.z;
-
- pOut.mat[1] = u.x;
- pOut.mat[5] = u.y;
- pOut.mat[9] = u.z;
-
- pOut.mat[2] = -f.x;
- pOut.mat[6] = -f.y;
- pOut.mat[10] = -f.z;
-
- cc.kmMat4Translation(translate, -pEye.x, -pEye.y, -pEye.z);
- cc.kmMat4Multiply(pOut, pOut, translate);
-
- return pOut;
-};
-
-/**
- * Build a rotation matrix from an axis and an angle. Result is stored in pOut.
- * pOut is returned.
- */
-cc.kmMat4RotationAxisAngle = function (pOut, axis, radians) {
- var rcos = Math.cos(radians);
- var rsin = Math.sin(radians);
-
- var normalizedAxis = new cc.kmVec3();
- cc.kmVec3Normalize(normalizedAxis, axis);
-
- pOut.mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos);
- pOut.mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos);
- pOut.mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos);
- pOut.mat[3] = 0.0;
-
- pOut.mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos);
- pOut.mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos);
- pOut.mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos);
- pOut.mat[7] = 0.0;
-
- pOut.mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos);
- pOut.mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos);
- pOut.mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos);
- pOut.mat[11] = 0.0;
-
- pOut.mat[12] = 0.0;
- pOut.mat[13] = 0.0;
- pOut.mat[14] = 0.0;
- pOut.mat[15] = 1.0;
-
- return pOut;
-};
-
-/**
- * Extract a 3x3 rotation matrix from the input 4x4 transformation.
- * Stores the result in pOut, returns pOut
- */
-cc.kmMat4ExtractRotation = function (pOut, pIn) {
- pOut.mat[0] = pIn.mat[0];
- pOut.mat[1] = pIn.mat[1];
- pOut.mat[2] = pIn.mat[2];
-
- pOut.mat[3] = pIn.mat[4];
- pOut.mat[4] = pIn.mat[5];
- pOut.mat[5] = pIn.mat[6];
-
- pOut.mat[6] = pIn.mat[8];
- pOut.mat[7] = pIn.mat[9];
- pOut.mat[8] = pIn.mat[10];
-
- return pOut;
-};
-
-cc.kmMat4ExtractPlane = function (pOut, pIn, plane) {
- switch (plane) {
- case cc.KM_PLANE_RIGHT:
- pOut.a = pIn.mat[3] - pIn.mat[0];
- pOut.b = pIn.mat[7] - pIn.mat[4];
- pOut.c = pIn.mat[11] - pIn.mat[8];
- pOut.d = pIn.mat[15] - pIn.mat[12];
- break;
- case cc.KM_PLANE_LEFT:
- pOut.a = pIn.mat[3] + pIn.mat[0];
- pOut.b = pIn.mat[7] + pIn.mat[4];
- pOut.c = pIn.mat[11] + pIn.mat[8];
- pOut.d = pIn.mat[15] + pIn.mat[12];
- break;
- case cc.KM_PLANE_BOTTOM:
- pOut.a = pIn.mat[3] + pIn.mat[1];
- pOut.b = pIn.mat[7] + pIn.mat[5];
- pOut.c = pIn.mat[11] + pIn.mat[9];
- pOut.d = pIn.mat[15] + pIn.mat[13];
- break;
- case cc.KM_PLANE_TOP:
- pOut.a = pIn.mat[3] - pIn.mat[1];
- pOut.b = pIn.mat[7] - pIn.mat[5];
- pOut.c = pIn.mat[11] - pIn.mat[9];
- pOut.d = pIn.mat[15] - pIn.mat[13];
- break;
- case cc.KM_PLANE_FAR:
- pOut.a = pIn.mat[3] - pIn.mat[2];
- pOut.b = pIn.mat[7] - pIn.mat[6];
- pOut.c = pIn.mat[11] - pIn.mat[10];
- pOut.d = pIn.mat[15] - pIn.mat[14];
- break;
- case cc.KM_PLANE_NEAR:
- pOut.a = pIn.mat[3] + pIn.mat[2];
- pOut.b = pIn.mat[7] + pIn.mat[6];
- pOut.c = pIn.mat[11] + pIn.mat[10];
- pOut.d = pIn.mat[15] + pIn.mat[14];
- break;
- default:
- cc.Assert(0, "Invalid plane index");
- }
-
- var t = Math.sqrt(pOut.a * pOut.a +
- pOut.b * pOut.b +
- pOut.c * pOut.c);
- pOut.a /= t;
- pOut.b /= t;
- pOut.c /= t;
- pOut.d /= t;
-
- return pOut;
-};
-
-/**
- * Take the rotation from a 4x4 transformation matrix, and return it as an axis and an angle (in radians)
- * returns the output axis.
- */
-cc.kmMat4RotationToAxisAngle = function (pAxis, radians, pIn) {
- /*Surely not this easy?*/
- var temp = new cc.kmQuaternion();
- var rotation = new cc.kmMat3();
- cc.kmMat4ExtractRotation(rotation, pIn);
- cc.kmQuaternionRotationMatrix(temp, rotation);
- cc.kmQuaternionToAxisAngle(temp, pAxis, radians);
- return pAxis;
-};
-
-
-
-
+ var outArr = pOut.mat;
+ var inArr = pIn.mat;
+
+ outArr[0] = inArr[0];
+ outArr[1] = inArr[1];
+ outArr[2] = inArr[2];
+ outArr[3] = inArr[3];
+
+ outArr[4] = inArr[4];
+ outArr[5] = inArr[5];
+ outArr[6] = inArr[6];
+ outArr[7] = inArr[7];
+
+ outArr[8] = inArr[8];
+ outArr[9] = inArr[9];
+ outArr[10] = inArr[10];
+ outArr[11] = inArr[11];
+
+ outArr[12] = inArr[12];
+ outArr[13] = inArr[13];
+ outArr[14] = inArr[14];
+ outArr[15] = inArr[15];
+ return pOut;
+ };
+
+ /**
+ * Assigns the value of current matrix from mat4
+ * @param {cc.math.Matrix4} mat4
+ * @returns {cc.math.Matrix4}
+ */
+ proto.assignFrom = function(mat4) {
+ if (this === mat4) {
+ cc.log("cc.mat.Matrix4.assignFrom(): mat4 equals current matrix");
+ return this;
+ }
+ var outArr = this.mat, inArr = mat4.mat;
+
+ outArr[0] = inArr[0];
+ outArr[1] = inArr[1];
+ outArr[2] = inArr[2];
+ outArr[3] = inArr[3];
+
+ outArr[4] = inArr[4];
+ outArr[5] = inArr[5];
+ outArr[6] = inArr[6];
+ outArr[7] = inArr[7];
+
+ outArr[8] = inArr[8];
+ outArr[9] = inArr[9];
+ outArr[10] = inArr[10];
+ outArr[11] = inArr[11];
+
+ outArr[12] = inArr[12];
+ outArr[13] = inArr[13];
+ outArr[14] = inArr[14];
+ outArr[15] = inArr[15];
+ return this;
+ };
+
+ /**
+ * Returns true if current matrix equal mat4 (approximately)
+ * @param {cc.math.Matrix4} mat4
+ * @returns {boolean}
+ */
+ proto.equals = function(mat4) {
+ if (this === mat4) {
+ cc.log("cc.kmMat4AreEqual(): pMat1 and pMat2 are same object.");
+ return true;
+ }
+ var matA = this.mat, matB = mat4.mat, EPSILON = cc.math.EPSILON;
+ for (var i = 0; i < 16; i++) {
+ if (!(matA[i] + EPSILON > matB[i] && matA[i] - EPSILON < matB[i]))
+ return false;
+ }
+ return true;
+ };
+
+ /**
+ * Builds an X-axis rotation matrix and stores it in matrix, returns matrix, if matrix is null, create a new matrix
+ * @param {Number} radians
+ * @param {cc.math.Matrix4} [matrix]
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByRotationX = function(radians, matrix) { //cc.kmMat4RotationX
+ /*
+ | 1 0 0 0 |
+ M = | 0 cos(A) -sin(A) 0 |
+ | 0 sin(A) cos(A) 0 |
+ | 0 0 0 1 |
+ */
+ matrix = matrix || new cc.math.Matrix4();
+ var mat = matrix.mat;
+ mat[0] = 1.0;
+ mat[3] = mat[2] = mat[1] = 0.0;
+
+ mat[4] = 0.0;
+ mat[5] = Math.cos(radians);
+ mat[6] = Math.sin(radians);
+ mat[7] = 0.0;
+
+ mat[8] = 0.0;
+ mat[9] = -Math.sin(radians);
+ mat[10] = Math.cos(radians);
+ mat[11] = 0.0;
+
+ mat[14] = mat[13] = mat[12] = 0.0;
+ mat[15] = 1.0;
+ return matrix;
+ };
+
+ /**
+ * Builds a rotation matrix using the rotation around the Y-axis, The result is stored in matrix, matrix is returned.
+ * @param {Number} radians
+ * @param {cc.math.Matrix4} [matrix]
+ * @returns {*}
+ */
+ cc.math.Matrix4.createByRotationY = function(radians, matrix) { // cc.kmMat4RotationY
+ /*
+ | cos(A) 0 sin(A) 0 |
+ M = | 0 1 0 0 |
+ | -sin(A) 0 cos(A) 0 |
+ | 0 0 0 1 |
+ */
+ matrix = matrix || new cc.math.Matrix4();
+ var mat = matrix.mat;
+ mat[0] = Math.cos(radians);
+ mat[1] = 0.0;
+ mat[2] = -Math.sin(radians);
+ mat[3] = 0.0;
+
+ mat[7] = mat[6] = mat[4] = 0.0;
+ mat[5] = 1.0;
+
+ mat[8] = Math.sin(radians);
+ mat[9] = 0.0;
+ mat[10] = Math.cos(radians);
+ mat[11] = 0.0;
+
+ mat[14] = mat[13] = mat[12] = 0.0;
+ mat[15] = 1.0;
+ return matrix;
+ };
+
+ /**
+ * Builds a rotation matrix around the Z-axis. The resulting matrix is stored in matrix. matrix is returned.
+ * @param {Number} radians
+ * @param {cc.math.Matrix4} matrix
+ * @return {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByRotationZ = function(radians, matrix){ // cc.kmMat4RotationZ
+ /*
+ | cos(A) -sin(A) 0 0 |
+ M = | sin(A) cos(A) 0 0 |
+ | 0 0 1 0 |
+ | 0 0 0 1 |
+ */
+ matrix = matrix || new cc.math.Matrix4();
+ var mat = matrix.mat;
+ mat[0] = Math.cos(radians);
+ mat[1] = Math.sin(radians);
+ mat[3] = mat[2] = 0.0;
+
+ mat[4] = -Math.sin(radians);
+ mat[5] = Math.cos(radians);
+ mat[7] = mat[6] = 0.0;
+
+ mat[11] = mat[9] = mat[8] = 0.0;
+ mat[10] = 1.0;
+
+ mat[14] = mat[13] = mat[12] = 0.0;
+ mat[15] = 1.0;
+
+ return matrix;
+ };
+
+ /**
+ * Builds a rotation matrix from pitch, yaw and roll. The resulting matrix is stored in parameter matrix and returns.
+ * @param {Number} pitch
+ * @param {Number} yaw
+ * @param {Number} roll
+ * @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByPitchYawRoll = function(pitch, yaw, roll, matrix) {
+ matrix = matrix || new cc.math.Matrix4();
+ var cr = Math.cos(pitch), sr = Math.sin(pitch);
+ var cp = Math.cos(yaw), sp = Math.sin(yaw);
+ var cy = Math.cos(roll), sy = Math.sin(roll);
+ var srsp = sr * sp, crsp = cr * sp;
+ var mat = matrix.mat;
+
+ mat[0] = cp * cy;
+ mat[4] = cp * sy;
+ mat[8] = -sp;
+
+ mat[1] = srsp * cy - cr * sy;
+ mat[5] = srsp * sy + cr * cy;
+ mat[9] = sr * cp;
+
+ mat[2] = crsp * cy + sr * sy;
+ mat[6] = crsp * sy - sr * cy;
+ mat[10] = cr * cp;
+
+ mat[3] = mat[7] = mat[11] = 0.0;
+ mat[15] = 1.0;
+ return matrix;
+ };
+
+ /**
+ * Builds a matrix by a quaternion.
+ * @param {cc.math.Quaternion} quaternion
+ * @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByQuaternion = function(quaternion, matrix) {
+ matrix = matrix || new cc.math.Matrix4();
+ var mat = matrix.mat;
+ mat[0] = 1.0 - 2.0 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z );
+ mat[1] = 2.0 * (quaternion.x * quaternion.y + quaternion.z * quaternion.w);
+ mat[2] = 2.0 * (quaternion.x * quaternion.z - quaternion.y * quaternion.w);
+ mat[3] = 0.0;
+
+ // Second row
+ mat[4] = 2.0 * ( quaternion.x * quaternion.y - quaternion.z * quaternion.w );
+ mat[5] = 1.0 - 2.0 * ( quaternion.x * quaternion.x + quaternion.z * quaternion.z );
+ mat[6] = 2.0 * (quaternion.z * quaternion.y + quaternion.x * quaternion.w );
+ mat[7] = 0.0;
+
+ // Third row
+ mat[8] = 2.0 * ( quaternion.x * quaternion.z + quaternion.y * quaternion.w );
+ mat[9] = 2.0 * ( quaternion.y * quaternion.z - quaternion.x * quaternion.w );
+ mat[10] = 1.0 - 2.0 * ( quaternion.x * quaternion.x + quaternion.y * quaternion.y );
+ mat[11] = 0.0;
+
+ // Fourth row
+ mat[14] = mat[13] = mat[12] = 0;
+ mat[15] = 1.0;
+ return matrix;
+ };
+
+ /**
+ * Build a 4x4 OpenGL transformation matrix using a 3x3 rotation matrix, and a 3d vector representing a translation.
+ * @param {cc.math.Matrix3} rotation
+ * @param {cc.math.Vec3} translation
+ * @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByRotationTranslation = function(rotation, translation, matrix) {
+ matrix = matrix || new cc.math.Matrix4();
+ var mat = matrix.mat, rMat = rotation.mat;
+ mat[0] = rMat[0];
+ mat[1] = rMat[1];
+ mat[2] = rMat[2];
+ mat[3] = 0.0;
+
+ mat[4] = rMat[3];
+ mat[5] = rMat[4];
+ mat[6] = rMat[5];
+ mat[7] = 0.0;
+
+ mat[8] = rMat[6];
+ mat[9] = rMat[7];
+ mat[10] = rMat[8];
+ mat[11] = 0.0;
+
+ mat[12] = translation.x;
+ mat[13] = translation.y;
+ mat[14] = translation.z;
+ mat[15] = 1.0;
+ return matrix;
+ };
+
+ /**
+ * Builds a scaling matrix
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByScale = function(x, y, z, matrix) { //cc.kmMat4Scaling
+ matrix = matrix || new cc.math.Matrix4();
+ var mat = matrix.mat;
+ mat[0] = x;
+ mat[5] = y;
+ mat[10] = z;
+ mat[15] = 1.0;
+ mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7] =
+ mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
+ return matrix;
+ };
+
+ /**
+ * Builds a translation matrix. All other elements in the matrix
+ * will be set to zero except for the diagonal which is set to 1.0
+ */
+ cc.kmMat4Translation = function (pOut, x, y, z) {
+ //FIXME: Write a test for this
+ pOut.mat[0] = pOut.mat[5] = pOut.mat[10] = pOut.mat[15] = 1.0;
+ pOut.mat[1] = pOut.mat[2] = pOut.mat[3] =
+ pOut.mat[4] = pOut.mat[6] = pOut.mat[7] =
+ pOut.mat[8] = pOut.mat[9] = pOut.mat[11] = 0.0;
+ pOut.mat[12] = x;
+ pOut.mat[13] = y;
+ pOut.mat[14] = z;
+ return pOut;
+ };
+
+ /**
+ * Builds a translation matrix.
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Number} z
+ * @param {cc.math.Matrix4} [matrix] if matrix is undefined, creates a new matrix.
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByTranslation = function(x, y, z, matrix){ //cc.kmMat4Translation
+ matrix = matrix || new cc.math.Matrix4();
+ matrix.identity();
+ matrix.mat[12] = x;
+ matrix.mat[13] = y;
+ matrix.mat[14] = z;
+ return matrix;
+ };
+
+ /**
+ * Get the up vector from a matrix.
+ * @returns {cc.math.Vec3}
+ */
+ proto.getUpVec3 = function() {
+ var mat = this.mat;
+ var ret = new cc.math.Vec3(mat[4],mat[5], mat[6]);
+ return ret.normalize();
+ };
+
+ /**
+ * Extract the right vector from a 4x4 matrix.
+ * @returns {cc.math.Vec3}
+ */
+ proto.getRightVec3 = function(){
+ var mat = this.mat;
+ var ret = new cc.math.Vec3(mat[0],mat[1], mat[2]);
+ return ret.normalize();
+ };
+
+ /**
+ * Extract the forward vector from a 4x4 matrix.
+ * @returns {cc.math.Vec3}
+ */
+ proto.getForwardVec3 = function() {
+ var mat = this.mat;
+ var ret = new cc.math.Vec3(mat[8],mat[9], mat[10]);
+ return ret.normalize();
+ };
+
+ /**
+ * Creates a perspective projection matrix in the
+ * same way as gluPerspective
+ */
+ cc.kmMat4PerspectiveProjection = function (pOut, fovY, aspect, zNear, zFar) {
+ var r = cc.degreesToRadians(fovY / 2);
+ var deltaZ = zFar - zNear;
+ var s = Math.sin(r);
+
+ if (deltaZ === 0 || s === 0 || aspect === 0)
+ return null;
+
+ //cos(r) / sin(r) = cot(r)
+ var cotangent = Math.cos(r) / s;
+ pOut.identity();
+ pOut.mat[0] = cotangent / aspect;
+ pOut.mat[5] = cotangent;
+ pOut.mat[10] = -(zFar + zNear) / deltaZ;
+ pOut.mat[11] = -1;
+ pOut.mat[14] = -2 * zNear * zFar / deltaZ;
+ pOut.mat[15] = 0;
+
+ return pOut;
+ };
+
+ /**
+ * Creates a perspective projection matrix in the same way as gluPerspective
+ * @param {Number} fovY
+ * @param {Number} aspect
+ * @param {Number} zNear
+ * @param {Number} zFar
+ * @returns {cc.math.Matrix4|Null}
+ */
+ cc.math.Matrix4.createPerspectiveProjection = function(fovY, aspect, zNear, zFar){
+ var r = cc.degreesToRadians(fovY / 2), deltaZ = zFar - zNear;
+ var s = Math.sin(r);
+
+ if (deltaZ === 0 || s === 0 || aspect === 0)
+ return null;
+
+ //cos(r) / sin(r) = cot(r)
+ var cotangent = Math.cos(r) / s;
+ var matrix = new cc.math.Matrix4(), mat = matrix.mat;
+ matrix.identity();
+ mat[0] = cotangent / aspect;
+ mat[5] = cotangent;
+ mat[10] = -(zFar + zNear) / deltaZ;
+ mat[11] = -1;
+ mat[14] = -2 * zNear * zFar / deltaZ;
+ mat[15] = 0;
+ return matrix;
+ };
+
+ /** Creates an orthographic projection matrix like glOrtho */
+ cc.kmMat4OrthographicProjection = function (pOut, left, right, bottom, top, nearVal, farVal) {
+ pOut.identity();
+ pOut.mat[0] = 2 / (right - left);
+ pOut.mat[5] = 2 / (top - bottom);
+ pOut.mat[10] = -2 / (farVal - nearVal);
+ pOut.mat[12] = -((right + left) / (right - left));
+ pOut.mat[13] = -((top + bottom) / (top - bottom));
+ pOut.mat[14] = -((farVal + nearVal) / (farVal - nearVal));
+ return pOut;
+ };
+
+ /**
+ * Creates an orthographic projection matrix like glOrtho
+ * @param {Number} left
+ * @param {Number} right
+ * @param {Number} bottom
+ * @param {Number} top
+ * @param {Number} nearVal
+ * @param {Number} farVal
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createOrthographicProjection = function (left, right, bottom, top, nearVal, farVal) {
+ var matrix = new cc.math.Matrix4(), mat = matrix.mat;
+ matrix.identity();
+ mat[0] = 2 / (right - left);
+ mat[5] = 2 / (top - bottom);
+ mat[10] = -2 / (farVal - nearVal);
+ mat[12] = -((right + left) / (right - left));
+ mat[13] = -((top + bottom) / (top - bottom));
+ mat[14] = -((farVal + nearVal) / (farVal - nearVal));
+ return matrix;
+ };
+
+ /**
+ * Builds a translation matrix in the same way as gluLookAt()
+ * the resulting matrix is stored in pOut. pOut is returned.
+ */
+ cc.kmMat4LookAt = function (pOut, pEye, pCenter, pUp) {
+ var f = new cc.math.Vec3(pCenter), up = new cc.math.Vec3(pUp);
+ f.subtract(pEye);
+ f.normalize();
+ up.normalize();
+
+ var s = new cc.math.Vec3(f);
+ s.cross(up);
+ s.normalize();
+
+ var u = new cc.math.Vec3(s);
+ u.cross(f);
+ s.normalize();
+
+ pOut.identity();
+
+ pOut.mat[0] = s.x;
+ pOut.mat[4] = s.y;
+ pOut.mat[8] = s.z;
+
+ pOut.mat[1] = u.x;
+ pOut.mat[5] = u.y;
+ pOut.mat[9] = u.z;
+
+ pOut.mat[2] = -f.x;
+ pOut.mat[6] = -f.y;
+ pOut.mat[10] = -f.z;
+
+ var translate = cc.math.Matrix4.createByTranslation(-pEye.x, -pEye.y, -pEye.z);
+ pOut.multiply(translate);
+ return pOut;
+ };
+
+ var tempMatrix = new cc.math.Matrix4(); // an internal matrix
+ proto.lookAt = function(eyeVec, centerVec, upVec) {
+ var f = new cc.math.Vec3(centerVec), up = new cc.math.Vec3(upVec), mat = this.mat;
+ f.subtract(eyeVec);
+ f.normalize();
+ up.normalize();
+
+ var s = new cc.math.Vec3(f);
+ s.cross(up);
+ s.normalize();
+
+ var u = new cc.math.Vec3(s);
+ u.cross(f);
+ s.normalize();
+
+ this.identity();
+ mat[0] = s.x;
+ mat[4] = s.y;
+ mat[8] = s.z;
+
+ mat[1] = u.x;
+ mat[5] = u.y;
+ mat[9] = u.z;
+
+ mat[2] = -f.x;
+ mat[6] = -f.y;
+ mat[10] = -f.z;
+
+ tempMatrix = cc.math.Matrix4.createByTranslation(-eyeVec.x, -eyeVec.y, -eyeVec.z, tempMatrix);
+ this.multiply(tempMatrix);
+ return this;
+ };
+
+ /**
+ * Build a rotation matrix from an axis and an angle. Result is stored in pOut.
+ * pOut is returned.
+ */
+ cc.kmMat4RotationAxisAngle = function (pOut, axis, radians) {
+ var rcos = Math.cos(radians), rsin = Math.sin(radians);
+
+ var normalizedAxis = new cc.math.Vec3(axis);
+ normalizedAxis.normalize();
+
+ pOut.mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos);
+ pOut.mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos);
+ pOut.mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos);
+ pOut.mat[3] = 0.0;
+
+ pOut.mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos);
+ pOut.mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos);
+ pOut.mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos);
+ pOut.mat[7] = 0.0;
+
+ pOut.mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos);
+ pOut.mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos);
+ pOut.mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos);
+ pOut.mat[11] = 0.0;
+
+ pOut.mat[12] = 0.0;
+ pOut.mat[13] = 0.0;
+ pOut.mat[14] = 0.0;
+ pOut.mat[15] = 1.0;
+
+ return pOut;
+ };
+
+ /**
+ * Build a rotation matrix from an axis and an angle.
+ * @param {cc.math.Vec3} axis
+ * @param {Number} radians
+ * @param {cc.math.Matrix4} [matrix]
+ * @returns {cc.math.Matrix4}
+ */
+ cc.math.Matrix4.createByAxisAndAngle = function(axis, radians, matrix) {
+ matrix = matrix || new cc.math.Matrix4();
+ var mat = this.mat, rcos = Math.cos(radians), rsin = Math.sin(radians) ;
+
+ var normalizedAxis = new cc.math.Vec3(axis);
+ normalizedAxis.normalize();
+
+ mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos);
+ mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos);
+ mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos);
+ mat[3] = 0.0;
+
+ mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos);
+ mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos);
+ mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos);
+ mat[7] = 0.0;
+
+ mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos);
+ mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos);
+ mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos);
+ mat[11] = 0.0;
+
+ mat[12] = mat[13] = mat[14] = 0.0;
+ mat[15] = 1.0;
+ return matrix;
+ };
+
+ /**
+ * Extract a 3x3 rotation matrix from the input 4x4 transformation.
+ * @returns {cc.math.Matrix3}
+ */
+ proto.extractRotation = function(){
+ var matrix = new cc.math.Matrix3(), mat4 = this.mat, mat3 = matrix.mat;
+ mat3[0] = mat4[0];
+ mat3[1] = mat4[1];
+ mat3[2] = mat4[2];
+
+ mat3[3] = mat4[4];
+ mat3[4] = mat4[5];
+ mat3[5] = mat4[6];
+
+ mat3[6] = mat4[8];
+ mat3[7] = mat4[9];
+ mat3[8] = mat4[10];
+ return matrix;
+ };
+
+ proto.extractPlane = function(planeType) {
+ var plane = new cc.math.Plane(), mat = this.mat;
+ switch (planeType) {
+ case cc.math.Plane.RIGHT:
+ plane.a = mat[3] - mat[0];
+ plane.b = mat[7] - mat[4];
+ plane.c = mat[11] - mat[8];
+ plane.d = mat[15] - mat[12];
+ break;
+ case cc.math.Plane.LEFT:
+ plane.a = mat[3] + mat[0];
+ plane.b = mat[7] + mat[4];
+ plane.c = mat[11] + mat[8];
+ plane.d = mat[15] + mat[12];
+ break;
+ case cc.math.Plane.BOTTOM:
+ plane.a = mat[3] + mat[1];
+ plane.b = mat[7] + mat[5];
+ plane.c = mat[11] + mat[9];
+ plane.d = mat[15] + mat[13];
+ break;
+ case cc.math.Plane.TOP:
+ plane.a = mat[3] - mat[1];
+ plane.b = mat[7] - mat[5];
+ plane.c = mat[11] - mat[9];
+ plane.d = mat[15] - mat[13];
+ break;
+ case cc.math.Plane.FAR:
+ plane.a = mat[3] - mat[2];
+ plane.b = mat[7] - mat[6];
+ plane.c = mat[11] - mat[10];
+ plane.d = mat[15] - mat[14];
+ break;
+ case cc.math.Plane.NEAR:
+ plane.a = mat[3] + mat[2];
+ plane.b = mat[7] + mat[6];
+ plane.c = mat[11] + mat[10];
+ plane.d = mat[15] + mat[14];
+ break;
+ default:
+ cc.log("cc.math.Matrix4.extractPlane: Invalid plane index");
+ break;
+ }
+ var t = Math.sqrt(plane.a * plane.a + plane.b * plane.b + plane.c * plane.c);
+ plane.a /= t;
+ plane.b /= t;
+ plane.c /= t;
+ plane.d /= t;
+ return plane;
+ };
+
+ /**
+ * Take the rotation from a 4x4 transformation matrix, and return it as an axis and an angle (in radians)
+ * @returns {*|{axis: cc.math.Vec3, angle: number}}
+ */
+ proto.toAxisAndAngle = function() {
+ /*Surely not this easy?*/
+ var rotation = this.extractRotation();
+ var temp = cc.math.Quaternion.rotationMatrix(rotation);
+ return temp.toAxisAndAngle();
+ };
+})(cc);
diff --git a/cocos2d/kazmath/mat4SIMD.js b/cocos2d/kazmath/mat4SIMD.js
new file mode 100644
index 0000000000..f716de796b
--- /dev/null
+++ b/cocos2d/kazmath/mat4SIMD.js
@@ -0,0 +1,428 @@
+/**
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2008, Luke Benstead.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function(cc) {
+ var proto = cc.math.Matrix4.prototype;
+
+ cc.kmMat4InverseSIMD = function (pOut, pM) {
+ pOut = pM.inverseSIMD();
+ return pOut;
+ };
+
+ proto.inverseSIMD = function(){
+ var inv = new cc.math.Matrix4();
+ var src = this.mat;
+ var dest = inv.mat;
+ var src0, src1, src2, src3;
+ var row0, row1, row2, row3;
+ var tmp1;
+ var minor0, minor1, minor2, minor3;
+ var det;
+
+ // Load the 4 rows
+ var src0 = SIMD.float32x4.load(src, 0);
+ var src1 = SIMD.float32x4.load(src, 4);
+ var src2 = SIMD.float32x4.load(src, 8);
+ var src3 = SIMD.float32x4.load(src, 12);
+
+ // Transpose the source matrix. Sort of. Not a true transpose operation
+
+ tmp1 = SIMD.float32x4.shuffle(src0, src1, 0, 1, 4, 5);
+ row1 = SIMD.float32x4.shuffle(src2, src3, 0, 1, 4, 5);
+ row0 = SIMD.float32x4.shuffle(tmp1, row1, 0, 2, 4, 6);
+ row1 = SIMD.float32x4.shuffle(row1, tmp1, 1, 3, 5, 7);
+
+ tmp1 = SIMD.float32x4.shuffle(src0, src1, 2, 3, 6, 7);
+ row3 = SIMD.float32x4.shuffle(src2, src3, 2, 3, 6, 7);
+ row2 = SIMD.float32x4.shuffle(tmp1, row3, 0, 2, 4, 6);
+ row3 = SIMD.float32x4.shuffle(row3, tmp1, 1, 3, 5, 7);
+
+ // ----
+ tmp1 = SIMD.float32x4.mul(row2, row3);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+ minor0 = SIMD.float32x4.mul(row1, tmp1);
+ minor1 = SIMD.float32x4.mul(row0, tmp1);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+ minor0 = SIMD.float32x4.sub(SIMD.float32x4.mul(row1, tmp1), minor0);
+ minor1 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor1);
+ minor1 = SIMD.float32x4.swizzle(minor1, 2, 3, 0, 1); // 0x4E = 01001110
+
+ // ----
+ tmp1 = SIMD.float32x4.mul(row1, row2);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+ minor0 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor0);
+ minor3 = SIMD.float32x4.mul(row0, tmp1);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+ minor0 = SIMD.float32x4.sub(minor0, SIMD.float32x4.mul(row3, tmp1));
+ minor3 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor3);
+ minor3 = SIMD.float32x4.swizzle(minor3, 2, 3, 0, 1); // 0x4E = 01001110
+
+ // ----
+ tmp1 = SIMD.float32x4.mul(SIMD.float32x4.swizzle(row1, 2, 3, 0, 1), row3); // 0x4E = 01001110
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+ row2 = SIMD.float32x4.swizzle(row2, 2, 3, 0, 1); // 0x4E = 01001110
+ minor0 = SIMD.float32x4.add(SIMD.float32x4.mul(row2, tmp1), minor0);
+ minor2 = SIMD.float32x4.mul(row0, tmp1);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+ minor0 = SIMD.float32x4.sub(minor0, SIMD.float32x4.mul(row2, tmp1));
+ minor2 = SIMD.float32x4.sub(SIMD.float32x4.mul(row0, tmp1), minor2);
+ minor2 = SIMD.float32x4.swizzle(minor2, 2, 3, 0, 1); // 0x4E = 01001110
+
+ // ----
+ tmp1 = SIMD.float32x4.mul(row0, row1);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+ minor2 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor2);
+ minor3 = SIMD.float32x4.sub(SIMD.float32x4.mul(row2, tmp1), minor3);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+ minor2 = SIMD.float32x4.sub(SIMD.float32x4.mul(row3, tmp1), minor2);
+ minor3 = SIMD.float32x4.sub(minor3, SIMD.float32x4.mul(row2, tmp1));
+
+ // ----
+ tmp1 = SIMD.float32x4.mul(row0, row3);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+ minor1 = SIMD.float32x4.sub(minor1, SIMD.float32x4.mul(row2, tmp1));
+ minor2 = SIMD.float32x4.add(SIMD.float32x4.mul(row1, tmp1), minor2);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+ minor1 = SIMD.float32x4.add(SIMD.float32x4.mul(row2, tmp1), minor1);
+ minor2 = SIMD.float32x4.sub(minor2, SIMD.float32x4.mul(row1, tmp1));
+
+ // ----
+ tmp1 = SIMD.float32x4.mul(row0, row2);
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 1, 0, 3, 2); // 0xB1 = 10110001
+ minor1 = SIMD.float32x4.add(SIMD.float32x4.mul(row3, tmp1), minor1);
+ minor3 = SIMD.float32x4.sub(minor3, SIMD.float32x4.mul(row1, tmp1));
+ tmp1 = SIMD.float32x4.swizzle(tmp1, 2, 3, 0, 1); // 0x4E = 01001110
+ minor1 = SIMD.float32x4.sub(minor1, SIMD.float32x4.mul(row3, tmp1));
+ minor3 = SIMD.float32x4.add(SIMD.float32x4.mul(row1, tmp1), minor3);
+
+ // Compute determinant
+ det = SIMD.float32x4.mul(row0, minor0);
+ det = SIMD.float32x4.add(SIMD.float32x4.swizzle(det, 2, 3, 0, 1), det); // 0x4E = 01001110
+ det = SIMD.float32x4.add(SIMD.float32x4.swizzle(det, 1, 0, 3, 2), det); // 0xB1 = 10110001
+ tmp1 = SIMD.float32x4.reciprocalApproximation(det);
+ det = SIMD.float32x4.sub(SIMD.float32x4.add(tmp1, tmp1), SIMD.float32x4.mul(det, SIMD.float32x4.mul(tmp1, tmp1)));
+ det = SIMD.float32x4.swizzle(det, 0, 0, 0, 0);
+
+ // Compute final values by multiplying with 1/det
+ minor0 = SIMD.float32x4.mul(det, minor0);
+ minor1 = SIMD.float32x4.mul(det, minor1);
+ minor2 = SIMD.float32x4.mul(det, minor2);
+ minor3 = SIMD.float32x4.mul(det, minor3);
+
+ SIMD.float32x4.store(dest, 0, minor0);
+ SIMD.float32x4.store(dest, 4, minor1);
+ SIMD.float32x4.store(dest, 8, minor2);
+ SIMD.float32x4.store(dest, 12, minor3);
+
+ return inv;
+ };
+
+ var identityMatrix = new cc.math.Matrix4().identity();
+ proto.isIdentitySIMD = function () {
+ var inx4 = SIMD.float32x4.load(this.mat, 0);
+ var identityx4 = SIMD.float32x4.load(identityMatrix.mat, 0);
+ var ret = SIMD.float32x4.equal(inx4, identityx4);
+ if(ret.signMask === 0x00)
+ return false;
+
+ inx4 = SIMD.float32x4.load(this.mat, 4);
+ identityx4 = SIMD.float32x4.load(identityMatrix.mat, 4);
+ ret = SIMD.float32x4.equal(inx4, identityx4);
+ if(ret.signMask === 0x00)
+ return false;
+
+ inx4 = SIMD.float32x4.load(this.mat, 8);
+ identityx4 = SIMD.float32x4.load(identityMatrix.mat, 8);
+ ret = SIMD.float32x4.equal(inx4, identityx4);
+ if(ret.signMask === 0x00)
+ return false;
+
+ inx4 = SIMD.float32x4.load(this.mat, 12);
+ identityx4 = SIMD.float32x4.load(identityMatrix.mat, 12);
+ ret = SIMD.float32x4.equal(inx4, identityx4);
+ if(ret.signMask === 0x00)
+ return false;
+ return true;
+ };
+
+ proto.transposeSIMD = function () {
+ var outArr = this.mat, inArr = this.mat;
+ var src0 = SIMD.float32x4.load(inArr, 0);
+ var src1 = SIMD.float32x4.load(inArr, 4);
+ var src2 = SIMD.float32x4.load(inArr, 8);
+ var src3 = SIMD.float32x4.load(inArr, 12);
+ var dst0;
+ var dst1;
+ var dst2;
+ var dst3;
+ var tmp01;
+ var tmp23;
+
+ tmp01 = SIMD.float32x4.shuffle(src0, src1, 0, 1, 4, 5);
+ tmp23 = SIMD.float32x4.shuffle(src2, src3, 0, 1, 4, 5);
+ dst0 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
+ dst1 = SIMD.float32x4.shuffle(tmp01, tmp23, 1, 3, 5, 7);
+
+ tmp01 = SIMD.float32x4.shuffle(src0, src1, 2, 3, 6, 7);
+ tmp23 = SIMD.float32x4.shuffle(src2, src3, 2, 3, 6, 7);
+ dst2 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
+ dst3 = SIMD.float32x4.shuffle(tmp01, tmp23, 1, 3, 5, 7);
+
+ SIMD.float32x4.store(outArr, 0, dst0);
+ SIMD.float32x4.store(outArr, 4, dst1);
+ SIMD.float32x4.store(outArr, 8, dst2);
+ SIMD.float32x4.store(outArr, 12, dst3);
+ return this;
+ };
+
+ cc.kmMat4MultiplySIMD = function (pOut, pM1, pM2) {
+ pOut = new cc.math.Matrix4(pM1);
+ return pOut.multiplySIMD(pM2);
+ };
+
+ proto.multiplySIMD = function(mat4) {
+ var a = this.mat;
+ var b = mat4.mat;
+ var out = this.mat;
+
+ var a0 = SIMD.float32x4.load(a,0);
+ var a1 = SIMD.float32x4.load(a,4);
+ var a2 = SIMD.float32x4.load(a,8);
+ var a3 = SIMD.float32x4.load(a,12);
+ var b0 = SIMD.float32x4.load(b, 0);
+ SIMD.float32x4.store(out, 0, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b0, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 3, 3, 3, 3), a3)))));
+ var b1 = SIMD.float32x4.load(b, 4);
+ SIMD.float32x4.store(out, 4, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b1, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 3, 3, 3, 3), a3)))));
+ var b2 = SIMD.float32x4.load(b, 8);
+ SIMD.float32x4.store(out, 8, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b2, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 3, 3, 3, 3), a3)))));
+ var b3 = SIMD.float32x4.load(b, 12);
+ SIMD.float32x4.store(out, 12, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b3, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 3, 3, 3, 3), a3)))));
+
+ return this;
+ };
+
+ cc.getMat4MultiplyValueSIMD = function (pM1, pM2) {
+ var mat = new cc.math.Matrix4(pM1);
+ return mat.multiplySIMD(pM2);
+ };
+
+ cc.kmMat4AssignSIMD = function (pOut, pIn) {
+ if(pOut == pIn) {
+ cc.log("cc.kmMat4Assign(): pOut equals pIn");//TODO: ADD SIMD?
+ return pOut;
+ }
+
+ return pOut.assignFromSIMD(pIn);
+ };
+
+ proto.assignFromSIMD = function (mat4) {
+ if(this == mat4) {
+ cc.log("cc.mat.Matrix4.assignFrom(): mat4 equals current matrix");//TODO: ADD SIMD?
+ return this;
+ }
+
+ var outArr = this.mat;
+ var inArr = mat4.mat;
+
+ SIMD.float32x4.store(outArr, 0, SIMD.float32x4.load(inArr, 0));
+ SIMD.float32x4.store(outArr, 4, SIMD.float32x4.load(inArr, 4));
+ SIMD.float32x4.store(outArr, 8, SIMD.float32x4.load(inArr, 8));
+ SIMD.float32x4.store(outArr, 12, SIMD.float32x4.load(inArr, 12));
+
+ return this;
+ };
+
+ proto.equalsSIMD = function (mat4) {
+ if(this === mat4){
+ cc.log("cc.kmMat4AreEqual(): pMat1 and pMat2 are same object.");
+ return true;
+ }
+ var m10 = SIMD.float32x4.load(this.mat, 0);
+ var m20 = SIMD.float32x4.load(mat4.mat, 0);
+
+ var epsilon = SIMD.float32x4.splat(cc.math.EPSILON);
+
+ var ret = SIMD.float32x4.lessThanOrEqual(SIMD.float32x4.abs(SIMD.float32x4.sub(m10, m20)), epsilon);
+ if (ret.signMask === 0)
+ return false;
+
+ var m11 = SIMD.float32x4.load(this.mat, 4);
+ var m21 = SIMD.float32x4.load(mat4.mat, 4);
+ ret = SIMD.float32x4.lessThanOrEqual(SIMD.float32x4.abs(SIMD.float32x4.sub(m11, m21)), epsilon);
+ if (ret.signMask === 0)
+ return false;
+
+ var m12 = SIMD.float32x4.load(this.mat, 8);
+ var m22 = SIMD.float32x4.load(mat4.mat, 8);
+ ret = SIMD.float32x4.lessThanOrEqual(SIMD.float32x4.abs(SIMD.float32x4.sub(m12, m22)), epsilon);
+ if (ret.signMask === 0)
+ return false;
+
+ var m13 = SIMD.float32x4.load(this.mat, 12);
+ var m23 = SIMD.float32x4.load(mat4.mat, 12);
+ ret = SIMD.float32x4.lessThanOrEqual(SIMD.float32x4.abs(SIMD.float32x4.sub(m13, m23)), epsilon);
+ if (ret.signMask === 0)
+ return false;
+ return true;
+ };
+
+ cc.kmMat4LookAtSIMD = function (pOut, pEye, pCenter, pUp) {
+ return pOut.lookAtSIMD(pEye, pCenter, pUp);
+ };
+
+ proto.lookAtSIMD = function(eyeVec, centerVec, upVec) {
+ var out = this.mat;
+
+ var center = SIMD.float32x4(centerVec.x, centerVec.y, centerVec.z, 0.0);
+ var eye = SIMD.float32x4(eyeVec.x, eyeVec.y, eyeVec.z, 0.0);
+ var up = SIMD.float32x4(upVec.x, upVec.y, upVec.z, 0.0);
+
+ // cc.kmVec3Subtract(f, pCenter, pEye);
+ var f = SIMD.float32x4.sub(center, eye);
+ // cc.kmVec3Normalize(f, f);
+ var tmp = SIMD.float32x4.mul(f, f);
+ tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
+ f = SIMD.float32x4.mul(f, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+
+ // cc.kmVec3Assign(up, pUp);
+ // cc.kmVec3Normalize(up, up);
+ tmp = SIMD.float32x4.mul(up, up);
+ tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
+ up = SIMD.float32x4.mul(up, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+
+ // cc.kmVec3Cross(s, f, up);
+ var s = SIMD.float32x4.sub(SIMD.float32x4.mul(SIMD.float32x4.swizzle(f, 1, 2, 0, 3), SIMD.float32x4.swizzle(up, 2, 0, 1, 3)),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(f, 2, 0, 1, 3), SIMD.float32x4.swizzle(up, 1, 2, 0, 3)));
+ // cc.kmVec3Normalize(s, s);
+ tmp = SIMD.float32x4.mul(s, s);
+ tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
+ s = SIMD.float32x4.mul(s, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+
+ // cc.kmVec3Cross(u, s, f);
+ var u = SIMD.float32x4.sub(SIMD.float32x4.mul(SIMD.float32x4.swizzle(s, 1, 2, 0, 3), SIMD.float32x4.swizzle(f, 2, 0, 1, 3)),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(s, 2, 0, 1, 3), SIMD.float32x4.swizzle(f, 1, 2, 0, 3)));
+ // cc.kmVec3Normalize(s, s);
+ tmp = SIMD.float32x4.mul(s, s);
+ tmp = SIMD.float32x4.add(tmp, SIMD.float32x4.add(SIMD.float32x4.swizzle(tmp, 1, 2, 0, 3), SIMD.float32x4.swizzle(tmp, 2, 0, 1, 3)));
+ s = SIMD.float32x4.mul(s, SIMD.float32x4.reciprocalSqrtApproximation(tmp));
+
+ //cc.kmMat4Identity(pOut);
+ //pOut.mat[0] = s.x;
+ //pOut.mat[4] = s.y;
+ //pOut.mat[8] = s.z;
+ //pOut.mat[1] = u.x;
+ //pOut.mat[5] = u.y;
+ //pOut.mat[9] = u.z;
+ //pOut.mat[2] = -f.x;
+ //pOut.mat[6] = -f.y;
+ //pOut.mat[10] = -f.z;
+ var zero = SIMD.float32x4.splat(0.0);
+ f = SIMD.float32x4.neg(f);
+ var tmp01 = SIMD.float32x4.shuffle(s, u, 0, 1, 4, 5);
+ var tmp23 = SIMD.float32x4.shuffle(f, zero, 0, 1, 4, 5);
+ var a0 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
+ var a1 = SIMD.float32x4.shuffle(tmp01, tmp23, 1, 3, 5, 7);
+
+ var tmp01 = SIMD.float32x4.shuffle(s, u, 2, 3, 6, 7);
+ var tmp23 = SIMD.float32x4.shuffle(f, zero, 2, 3, 6, 7);
+ var a2 = SIMD.float32x4.shuffle(tmp01, tmp23, 0, 2, 4, 6);
+ var a3 = SIMD.float32x4(0.0, 0.0, 0.0, 1.0);
+
+ // cc.kmMat4Translation(translate, -pEye.x, -pEye.y, -pEye.z);
+ var b0 = SIMD.float32x4(1.0, 0.0, 0.0, 0.0);
+ var b1 = SIMD.float32x4(0.0, 1.0, 0.0, 0.0);
+ var b2 = SIMD.float32x4(0.0, 0.0, 1.0, 0.0);
+ var b3 = SIMD.float32x4.neg(eye);
+ b3 = SIMD.float32x4.withW(b3, 1.0);
+
+ // cc.kmMat4Multiply(pOut, pOut, translate);
+ SIMD.float32x4.store(out, 0, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b0, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b0, 3, 3, 3, 3), a3)))));
+ SIMD.float32x4.store(out, 4, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b1, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b1, 3, 3, 3, 3), a3)))));
+ SIMD.float32x4.store(out, 8, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b2, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b2, 3, 3, 3, 3), a3)))));
+ SIMD.float32x4.store(out, 12, SIMD.float32x4.add(
+ SIMD.float32x4.mul(
+ SIMD.float32x4.swizzle(b3, 0, 0, 0, 0), a0),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 1, 1, 1, 1), a1),
+ SIMD.float32x4.add(
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 2, 2, 2, 2), a2),
+ SIMD.float32x4.mul(SIMD.float32x4.swizzle(b3, 3, 3, 3, 3), a3)))));
+ return this;
+ };
+
+
+})(cc);
diff --git a/cocos2d/kazmath/plane.js b/cocos2d/kazmath/plane.js
index 73c4e75339..db5f9dd1e6 100644
--- a/cocos2d/kazmath/plane.js
+++ b/cocos2d/kazmath/plane.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,157 +26,112 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.KM_PLANE_LEFT = 0;
-
-cc.KM_PLANE_RIGHT = 1;
-
-cc.KM_PLANE_BOTTOM = 2;
-
-cc.KM_PLANE_TOP = 3;
-
-cc.KM_PLANE_NEAR = 4;
-
-cc.KM_PLANE_FAR = 5;
-
-cc.kmPlane = function (a, b, c, d) {
- this.a = a || 0;
- this.b = b || 0;
- this.c = c || 0;
- this.d = d || 0;
-};
-
-cc.POINT_INFRONT_OF_PLANE = 0;
-
-cc.POINT_BEHIND_PLANE = 1;
-
-cc.POINT_ON_PLANE = 2;
-
-cc.kmPlaneDot = function(pP, pV){
- //a*x + b*y + c*z + d*w
- return (pP.a * pV.x +
- pP.b * pV.y +
- pP.c * pV.z +
- pP.d * pV.w);
-};
-
-cc.kmPlaneDotCoord = function(pP, pV){
- return (pP.a * pV.x +
- pP.b * pV.y +
- pP.c * pV.z + pP.d);
-};
-
-cc.kmPlaneDotNormal = function(pP, pV){
- return (pP.a * pV.x +
- pP.b * pV.y +
- pP.c * pV.z);
-};
-
-cc.kmPlaneFromPointNormal = function(pOut, pPoint, pNormal){
- /*
- Planea = Nx
- Planeb = Ny
- Planec = Nz
- Planed = −N⋅P
- */
- pOut.a = pNormal.x;
- pOut.b = pNormal.y;
- pOut.c = pNormal.z;
- pOut.d = -cc.kmVec3Dot(pNormal, pPoint);
-
- return pOut;
-};
-
/**
- * Creates a plane from 3 points. The result is stored in pOut.
- * pOut is returned.
+ * @ignore
*/
-cc.kmPlaneFromPoints = function(pOut, p1, p2, p3){
- /*
- v = (B − A) × (C − A)
- n = 1â„|v| v
- Outa = nx
- Outb = ny
- Outc = nz
- Outd = −n⋅A
- */
-
- var n = new cc.kmVec3(), v1 = new cc.kmVec3(), v2 = new cc.kmVec3();
- cc.kmVec3Subtract(v1, p2, p1); //Create the vectors for the 2 sides of the triangle
- cc.kmVec3Subtract(v2, p3, p1);
- cc.kmVec3Cross(n, v1, v2); //Use the cross product to get the normal
-
- cc.kmVec3Normalize(n, n); //Normalize it and assign to pOut.m_N
-
- pOut.a = n.x;
- pOut.b = n.y;
- pOut.c = n.z;
- pOut.d = cc.kmVec3Dot(cc.kmVec3Scale(n, n, -1.0), p1);
-
- return pOut;
-};
-
-cc.kmPlaneIntersectLine = function(pOut, pP, pV1, pV2){
- /*
- n = (Planea, Planeb, Planec)
- d = V − U
- Out = U − dâ‹…(Pd + nâ‹…U)â„(dâ‹…n) [iff dâ‹…n ≠0]
- */
- var d = new cc.kmVec3();
- cc.Assert(0 , "Not implemented");
-
- cc.kmVec3Subtract(d, pV2, pV1); //Get the direction vector
-
- //TODO: Continue here!
- /*if (fabs(kmVec3Dot(&pP.m_N, &d)) > kmEpsilon)
- {
- //If we get here then the plane and line are parallel (i.e. no intersection)
- pOut = nullptr; //Set to nullptr
-
- return pOut;
- } */
-
- return null;
-};
-
-cc.kmPlaneNormalize = function(pOut, pP){
- var n = new cc.kmVec3();
-
- n.x = pP.a;
- n.y = pP.b;
- n.z = pP.c;
-
- var l = 1.0 / cc.kmVec3Length(n); //Get 1/length
- cc.kmVec3Normalize(n, n); //Normalize the vector and assign to pOut
-
- pOut.a = n.x;
- pOut.b = n.y;
- pOut.c = n.z;
-
- pOut.d = pP.d * l; //Scale the D value and assign to pOut
-
- return pOut;
-};
-
-cc.kmPlaneScale = function(pOut, pP, s){
- cc.Assert(0 , "Not implemented");
- return null;
-};
+(function(cc){
+ cc.math.Plane = function (a, b, c, d) {
+ if (a && b === undefined) {
+ this.a = a.a;
+ this.b = a.b;
+ this.c = a.c;
+ this.d = a.d;
+ } else {
+ this.a = a || 0;
+ this.b = b || 0;
+ this.c = c || 0;
+ this.d = d || 0;
+ }
+ };
+ cc.kmPlane = cc.math.Plane;
+ var proto = cc.math.Plane.prototype;
+
+ cc.math.Plane.LEFT = 0;
+
+ cc.math.Plane.RIGHT = 1;
+
+ cc.math.Plane.BOTTOM = 2;
+
+ cc.math.Plane.TOP = 3;
+
+ cc.math.Plane.NEAR = 4;
+
+ cc.math.Plane.FAR = 5;
+
+ cc.math.Plane.POINT_INFRONT_OF_PLANE = 0;
+
+ cc.math.Plane.POINT_BEHIND_PLANE = 1;
+
+ cc.math.Plane.POINT_ON_PLANE = 2;
+
+ proto.dot = function(vec4){ //cc.kmPlaneDot
+ return (this.a * vec4.x + this.b * vec4.y + this.c * vec4.z + this.d * vec4.w);
+ };
+
+ proto.dotCoord = function(vec3) { //=cc.kmPlaneDotCoord
+ return (this.a * vec3.x + this.b * vec3.y + this.c * vec3.z + this.d);
+ };
+
+ proto.dotNormal = function(vec3) { //=cc.kmPlaneDotNormal
+ return (this.a * vec3.x + this.b * vec3.y + this.c * vec3.z);
+ };
+
+ cc.math.Plane.fromPointNormal = function(vec3, normal) { //cc.kmPlaneFromPointNormal
+ /*
+ Planea = Nx
+ Planeb = Ny
+ Planec = Nz
+ Planned = −N⋅P
+ */
+ return new cc.math.Plane(normal.x, normal.y, normal.z, -normal.dot(vec3));
+ };
+
+ cc.math.Plane.fromPoints = function(vec1, vec2, vec3) { //cc.kmPlaneFromPoints
+ /*
+ v = (B − A) × (C − A)
+ n = 1â„|v| v
+ Outa = nx
+ Outb = ny
+ Outc = nz
+ Outd = −n⋅A
+ */
+ var v1 = new cc.math.Vec3(vec2), v2 = new cc.math.Vec3(vec3), plane = new cc.math.Plane();
+ v1.subtract(vec1); //Create the vectors for the 2 sides of the triangle
+ v2.subtract(vec1);
+ v1.cross(v2); // Use the cross product to get the normal
+ v1.normalize(); //Normalize it and assign to pOut.m_N
+
+ plane.a = v1.x;
+ plane.b = v1.y;
+ plane.c = v1.z;
+ plane.d = v1.scale(-1.0).dot(vec1);
+ return plane;
+ };
+
+ proto.normalize = function(){ //cc.kmPlaneNormalize
+ var n = new cc.math.Vec3(this.a, this.b, this.c), l = 1.0 / n.length(); //Get 1/length
+ n.normalize(); //Normalize the vector and assign to pOut
+ this.a = n.x;
+ this.b = n.y;
+ this.c = n.z;
+ this.d = this.d * l; //Scale the D value and assign to pOut
+ return this;
+ };
+
+ proto.classifyPoint = function(vec3) {
+ // This function will determine if a point is on, in front of, or behind
+ // the plane. First we store the dot product of the plane and the point.
+ var distance = this.a * vec3.x + this.b * vec3.y + this.c * vec3.z + this.d;
+
+ // Simply put if the dot product is greater than 0 then it is infront of it.
+ // If it is less than 0 then it is behind it. And if it is 0 then it is on it.
+ if(distance > 0.001)
+ return cc.math.Plane.POINT_INFRONT_OF_PLANE;
+ if(distance < -0.001)
+ return cc.math.Plane.POINT_BEHIND_PLANE;
+ return cc.math.Plane.POINT_ON_PLANE;
+ };
+})(cc);
-/**
- * Returns POINT_INFRONT_OF_PLANE if pP is infront of pIn. Returns
- * POINT_BEHIND_PLANE if it is behind. Returns POINT_ON_PLANE otherwise
- */
-cc.kmPlaneClassifyPoint = function(pIn, pP){
- // This function will determine if a point is on, in front of, or behind
- // the plane. First we store the dot product of the plane and the point.
- var distance = pIn.a * pP.x + pIn.b * pP.y + pIn.c * pP.z + pIn.d;
-
- // Simply put if the dot product is greater than 0 then it is infront of it.
- // If it is less than 0 then it is behind it. And if it is 0 then it is on it.
- if(distance > 0.001) return cc.POINT_INFRONT_OF_PLANE;
- if(distance < -0.001) return cc.POINT_BEHIND_PLANE;
-
- return cc.POINT_ON_PLANE;
-};
diff --git a/cocos2d/kazmath/quaternion.js b/cocos2d/kazmath/quaternion.js
index 1c234fb0e7..fcbd652da9 100644
--- a/cocos2d/kazmath/quaternion.js
+++ b/cocos2d/kazmath/quaternion.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,454 +26,425 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.kmQuaternion = function (x, y, z, w) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- this.w = w || 0;
-};
-
-///< Returns pOut, sets pOut to the conjugate of pIn
-cc.kmQuaternionConjugate = function (pOut, pIn) {
- pOut.x = -pIn.x;
- pOut.y = -pIn.y;
- pOut.z = -pIn.z;
- pOut.w = pIn.w;
-
- return pOut;
-};
-
-///< Returns the dot product of the 2 quaternions
-cc.kmQuaternionDot = function (q1, q2) {
- // A dot B = B dot A = AtBt + AxBx + AyBy + AzBz
- return (q1.w * q2.w +
- q1.x * q2.x +
- q1.y * q2.y +
- q1.z * q2.z);
-};
-
-///< Returns the exponential of the quaternion
-cc.kmQuaternionExp = function (pOut, pIn) {
- //TODO not implement
- //cc.assert(0);
- return pOut;
-};
-
-///< Makes the passed quaternion an identity quaternion
-cc.kmQuaternionIdentity = function (pOut) {
- pOut.x = 0.0;
- pOut.y = 0.0;
- pOut.z = 0.0;
- pOut.w = 1.0;
-
- return pOut;
-};
-
-///< Returns the inverse of the passed Quaternion
-cc.kmQuaternionInverse = function (pOut, pIn) {
- var l = cc.kmQuaternionLength(pIn);
- var tmp = new cc.kmQuaternion();
-
- if (Math.abs(l) > cc.kmEpsilon) {
- pOut.x = 0.0;
- pOut.y = 0.0;
- pOut.z = 0.0;
- pOut.w = 0.0;
- return pOut;
- }
-
- ///Get the conjugute and divide by the length
- cc.kmQuaternionScale(pOut,
- cc.kmQuaternionConjugate(tmp, pIn), 1.0 / l);
-
- return pOut;
-};
-
-///< Returns true if the quaternion is an identity quaternion
-cc.kmQuaternionIsIdentity = function (pIn) {
- return (pIn.x == 0.0 && pIn.y == 0.0 && pIn.z == 0.0 &&
- pIn.w == 1.0);
-};
-
-///< Returns the length of the quaternion
-cc.kmQuaternionLength = function (pIn) {
- return Math.sqrt(cc.kmQuaternionLengthSq(pIn));
-};
-
-///< Returns the length of the quaternion squared (prevents a sqrt)
-cc.kmQuaternionLengthSq = function (pIn) {
- return pIn.x * pIn.x + pIn.y * pIn.y +
- pIn.z * pIn.z + pIn.w * pIn.w;
-};
-
-///< Returns the natural logarithm
-cc.kmQuaternionLn = function (pOut, pIn) {
- /*
- A unit quaternion, is defined by:
- Q == (cos(theta), sin(theta) * v) where |v| = 1
- The natural logarithm of Q is, ln(Q) = (0, theta * v)
+(function(cc) {
+ /**
+ * The Quaternion class
+ * @param {Number|cc.math.Quaternion} [x=0]
+ * @param {Number} [y=0]
+ * @param {Number} [z=0]
+ * @param {Number} [w=0]
+ * @constructor
*/
- //assert(0);
- //TODO not implement
- return pOut;
-};
-
-///< Multiplies 2 quaternions together
-cc.kmQuaternionMultiply = function (pOut, q1, q2) {
- pOut.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
- pOut.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
- pOut.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z;
- pOut.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x;
-
- return pOut;
-};
-
-///< Normalizes a quaternion
-cc.kmQuaternionNormalize = function (pOut, pIn) {
- var length = cc.kmQuaternionLength(pIn);
- cc.Assert(Math.abs(length) > cc.kmEpsilon, "");
- cc.kmQuaternionScale(pOut, pIn, 1.0 / length);
-
- return pOut;
-};
-
-///< Rotates a quaternion around an axis
-cc.kmQuaternionRotationAxis = function (pOut, pV, angle) {
- var rad = angle * 0.5;
- var scale = Math.sin(rad);
-
- pOut.w = Math.cos(rad);
- pOut.x = pV.x * scale;
- pOut.y = pV.y * scale;
- pOut.z = pV.z * scale;
-
- return pOut;
-};
-
-///< Creates a quaternion from a rotation matrix
-cc.kmQuaternionRotationMatrix = function (pOut, pIn) {
- /*
- Note: The OpenGL matrices are transposed from the description below
- taken from the Matrix and Quaternion FAQ
-
- if ( mat[0] > mat[5] && mat[0] > mat[10] ) { // Column 0:
- S = sqrt( 1.0 + mat[0] - mat[5] - mat[10] ) * 2;
- X = 0.25 * S;
- Y = (mat[4] + mat[1] ) / S;
- Z = (mat[2] + mat[8] ) / S;
- W = (mat[9] - mat[6] ) / S;
- } else if ( mat[5] > mat[10] ) { // Column 1:
- S = sqrt( 1.0 + mat[5] - mat[0] - mat[10] ) * 2;
- X = (mat[4] + mat[1] ) / S;
- Y = 0.25 * S;
- Z = (mat[9] + mat[6] ) / S;
- W = (mat[2] - mat[8] ) / S;
- } else { // Column 2:
- S = sqrt( 1.0 + mat[10] - mat[0] - mat[5] ) * 2;
- X = (mat[2] + mat[8] ) / S;
- Y = (mat[9] + mat[6] ) / S;
- Z = 0.25 * S;
- W = (mat[4] - mat[1] ) / S;
- }
- */
- var x, y, z, w;
- var m4x4 = [];
- var scale = 0.0;
- var diagonal = 0.0;
-
- if (!pIn) {
- return null;
- }
-
- /* 0 3 6
- 1 4 7
- 2 5 8
-
- 0 1 2 3
- 4 5 6 7
- 8 9 10 11
- 12 13 14 15*/
-
- m4x4[0] = pIn.mat[0];
- m4x4[1] = pIn.mat[3];
- m4x4[2] = pIn.mat[6];
- m4x4[4] = pIn.mat[1];
- m4x4[5] = pIn.mat[4];
- m4x4[6] = pIn.mat[7];
- m4x4[8] = pIn.mat[2];
- m4x4[9] = pIn.mat[5];
- m4x4[10] = pIn.mat[8];
- m4x4[15] = 1;
- var pMatrix = m4x4[0];
-
- diagonal = pMatrix[0] + pMatrix[5] + pMatrix[10] + 1;
-
- if (diagonal > cc.kmEpsilon) {
- // Calculate the scale of the diagonal
- scale = Math.sqrt(diagonal) * 2;
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = ( pMatrix[9] - pMatrix[6] ) / scale;
- y = ( pMatrix[2] - pMatrix[8] ) / scale;
- z = ( pMatrix[4] - pMatrix[1] ) / scale;
- w = 0.25 * scale;
- } else {
- // If the first element of the diagonal is the greatest value
- if (pMatrix[0] > pMatrix[5] && pMatrix[0] > pMatrix[10]) {
- // Find the scale according to the first element, and double that value
- scale = Math.sqrt(1.0 + pMatrix[0] - pMatrix[5] - pMatrix[10]) * 2.0;
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = 0.25 * scale;
- y = (pMatrix[4] + pMatrix[1] ) / scale;
- z = (pMatrix[2] + pMatrix[8] ) / scale;
- w = (pMatrix[9] - pMatrix[6] ) / scale;
- }
- // Else if the second element of the diagonal is the greatest value
- else if (pMatrix[5] > pMatrix[10]) {
- // Find the scale according to the second element, and double that value
- scale = Math.sqrt(1.0 + pMatrix[5] - pMatrix[0] - pMatrix[10]) * 2.0;
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = (pMatrix[4] + pMatrix[1] ) / scale;
- y = 0.25 * scale;
- z = (pMatrix[9] + pMatrix[6] ) / scale;
- w = (pMatrix[2] - pMatrix[8] ) / scale;
+ cc.math.Quaternion = function (x, y, z, w) {
+ if (x && y === undefined) {
+ this.x = x.x;
+ this.y = x.y;
+ this.z = x.z;
+ this.w = x.w;
} else {
- // Else the third element of the diagonal is the greatest value
-
- // Find the scale according to the third element, and double that value
- scale = Math.sqrt(1.0 + pMatrix[10] - pMatrix[0] - pMatrix[5]) * 2.0;
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = (pMatrix[2] + pMatrix[8] ) / scale;
- y = (pMatrix[9] + pMatrix[6] ) / scale;
- z = 0.25 * scale;
- w = (pMatrix[4] - pMatrix[1] ) / scale;
+ this.x = x || 0;
+ this.y = y || 0;
+ this.z = z || 0;
+ this.w = w || 0;
}
- }
-
- pOut.x = x;
- pOut.y = y;
- pOut.z = z;
- pOut.w = w;
-
- return pOut;
-};
-
-///< Create a quaternion from yaw, pitch and roll
-cc.kmQuaternionRotationYawPitchRoll = function (pOut, yaw, pitch, roll) {
- var ex, ey, ez; // temp half euler angles
- var cr, cp, cy, sr, sp, sy, cpcy, spsy; // temp vars in roll,pitch yaw
-
- ex = cc.kmDegreesToRadians(pitch) / 2.0; // convert to rads and half them
- ey = cc.kmDegreesToRadians(yaw) / 2.0;
- ez = cc.kmDegreesToRadians(roll) / 2.0;
-
- cr = Math.cos(ex);
- cp = Math.cos(ey);
- cy = Math.cos(ez);
-
- sr = Math.sin(ex);
- sp = Math.sin(ey);
- sy = Math.sin(ez);
+ };
+ cc.kmQuaternion = cc.math.Quaternion;
+ var proto = cc.math.Quaternion.prototype;
- cpcy = cp * cy;
- spsy = sp * sy;
-
- pOut.w = cr * cpcy + sr * spsy;
-
- pOut.x = sr * cpcy - cr * spsy;
- pOut.y = cr * sp * cy + sr * cp * sy;
- pOut.z = cr * cp * sy - sr * sp * cy;
-
- cc.kmQuaternionNormalize(pOut, pOut);
-
- return pOut;
-};
-
-///< Interpolate between 2 quaternions
-cc.kmQuaternionSlerp = function (pOut, q1, q2, t) {
- /*float CosTheta = Q0.DotProd(Q1);
- float Theta = acosf(CosTheta);
- float SinTheta = sqrtf(1.0f-CosTheta*CosTheta);
-
- float Sin_T_Theta = sinf(T*Theta)/SinTheta;
- float Sin_OneMinusT_Theta = sinf((1.0f-T)*Theta)/SinTheta;
-
- Quaternion Result = Q0*Sin_OneMinusT_Theta;
- Result += (Q1*Sin_T_Theta);
-
- return Result;*/
-
- if (q1.x == q2.x &&
- q1.y == q2.y &&
- q1.z == q2.z &&
- q1.w == q2.w) {
-
- pOut.x = q1.x;
- pOut.y = q1.y;
- pOut.z = q1.z;
- pOut.w = q1.w;
-
- return pOut;
- }
-
- var ct = cc.kmQuaternionDot(q1, q2);
- var theta = Math.acos(ct);
- var st = Math.sqrt(1.0 - cc.kmSQR(ct));
-
- var stt = Math.sin(t * theta) / st;
- var somt = Math.sin((1.0 - t) * theta) / st;
-
- var temp = new cc.kmQuaternion(), temp2 = new cc.kmQuaternion();
- cc.kmQuaternionScale(temp, q1, somt);
- cc.kmQuaternionScale(temp2, q2, stt);
- cc.kmQuaternionAdd(pOut, temp, temp2);
-
- return pOut;
-};
-
-///< Get the axis and angle of rotation from a quaternion
-cc.kmQuaternionToAxisAngle = function (pIn, pAxis, pAngle) {
- var tempAngle; // temp angle
- var scale; // temp vars
-
- tempAngle = Math.acos(pIn.w);
- scale = Math.sqrt(cc.kmSQR(pIn.x) + cc.kmSQR(pIn.y) + cc.kmSQR(pIn.z));
-
- if (((scale > -cc.kmEpsilon) && scale < cc.kmEpsilon)
- || (scale < 2 * cc.kmPI + cc.kmEpsilon && scale > 2 * cc.kmPI - cc.kmEpsilon)) { // angle is 0 or 360 so just simply set axis to 0,0,1 with angle 0
- pAngle = 0.0;
-
- pAxis.x = 0.0;
- pAxis.y = 0.0;
- pAxis.z = 1.0;
- } else {
- pAngle = tempAngle * 2.0; // angle in radians
-
- pAxis.x = pIn.x / scale;
- pAxis.y = pIn.y / scale;
- pAxis.z = pIn.z / scale;
- cc.kmVec3Normalize(pAxis, pAxis);
- }
-};
-
-///< Scale a quaternion
-cc.kmQuaternionScale = function (pOut, pIn, s) {
- pOut.x = pIn.x * s;
- pOut.y = pIn.y * s;
- pOut.z = pIn.z * s;
- pOut.w = pIn.w * s;
-
- return pOut;
-};
-
-cc.kmQuaternionAssign = function (pOut, pIn) {
- pOut.x = pIn.x;
- pOut.y = pIn.y;
- pOut.z = pIn.z;
- pOut.w = pIn.w;
-
- return pOut;
-};
+ /**
+ * Sets the conjugate of quaternion to self
+ * @param {cc.math.Quaternion} quaternion
+ */
+ proto.conjugate = function (quaternion) { //= cc.kmQuaternionConjugate
+ this.x = -quaternion.x;
+ this.y = -quaternion.y;
+ this.z = -quaternion.z;
+ this.w = quaternion.w;
+ return this;
+ };
+
+ /**
+ * Returns the dot product of the current quaternion and parameter quaternion
+ * @param quaternion
+ * @returns {number}
+ */
+ proto.dot = function(quaternion) { // = cc.kmQuaternionDot
+ // A dot B = B dot A = AtBt + AxBx + AyBy + AzBz
+ return (this.w * quaternion.w + this.x * quaternion.x + this.y * quaternion.y + this.z * quaternion.z);
+ };
+
+ /**
+ * Returns the exponential of the quaternion, this function doesn't implemented.
+ * @returns {cc.math.Quaternion}
+ */
+ proto.exponential = function(){ //=cc.kmQuaternionExp
+ return this;
+ };
-cc.kmQuaternionAdd = function (pOut, pQ1, pQ2) {
- pOut.x = pQ1.x + pQ2.x;
- pOut.y = pQ1.y + pQ2.y;
- pOut.z = pQ1.z + pQ2.z;
- pOut.w = pQ1.w + pQ2.w;
-
- return pOut;
-};
-
-/** Adapted from the OGRE engine!
-
- Gets the shortest arc quaternion to rotate this vector to the destination
- vector.
- @remarks
- If you call this with a dest vector that is close to the inverse
- of this vector, we will rotate 180 degrees around the 'fallbackAxis'
- (if specified, or a generated axis if not) since in this case
- ANY axis of rotation is valid.
- */
-cc.kmQuaternionRotationBetweenVec3 = function (pOut, vec1, vec2, fallback) {
- var v1 = new cc.kmVec3(), v2 = new cc.kmVec3();
- var a;
+ /**
+ * Makes the current quaternion an identity quaternion
+ */
+ proto.identity = function(){ //=cc.kmQuaternionIdentity
+ this.x = 0.0;
+ this.y = 0.0;
+ this.z = 0.0;
+ this.w = 1.0;
+ return this;
+ };
+
+ /**
+ * Inverses the value of current Quaternion
+ */
+ proto.inverse = function(){ //=cc.kmQuaternionInverse
+ var len = this.length();
+ if (Math.abs(len) > cc.math.EPSILON) {
+ this.x = 0.0;
+ this.y = 0.0;
+ this.z = 0.0;
+ this.w = 0.0;
+ return this;
+ }
- cc.kmVec3Assign(v1, vec1);
- cc.kmVec3Assign(v2, vec2);
+ ///Get the conjugute and divide by the length
+ this.conjugate(this).scale(1.0 / len);
+ return this;
+ };
- cc.kmVec3Normalize(v1, v1);
- cc.kmVec3Normalize(v2, v2);
+ /**
+ * Returns true if the quaternion is an identity quaternion
+ * @returns {boolean}
+ */
+ proto.isIdentity = function(){ //=cc.kmQuaternionIsIdentity
+ return (this.x === 0.0 && this.y === 0.0 && this.z === 0.0 && this.w === 1.0);
+ };
- a = cc.kmVec3Dot(v1, v2);
+ /**
+ * Returns the length of the quaternion
+ * @returns {number}
+ */
+ proto.length = function() { //=cc.kmQuaternionLength
+ return Math.sqrt(this.lengthSq());
+ };
- if (a >= 1.0) {
- cc.kmQuaternionIdentity(pOut);
- return pOut;
- }
+ /**
+ * Returns the length of the quaternion squared (prevents a sqrt)
+ * @returns {number}
+ */
+ proto.lengthSq = function() { //=cc.kmQuaternionLengthSq
+ return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
+ };
+
+ /**
+ * Uses current quaternion multiplies other quaternion.
+ * @param {cc.math.Quaternion} quaternion
+ * @returns {cc.math.Quaternion}
+ */
+ proto.multiply = function(quaternion) { //cc.kmQuaternionMultiply
+ var x = this.x, y = this.y, z = this.z, w = this.w;
+ this.w = w * quaternion.w - x * quaternion.x - y * quaternion.y - z * quaternion.z;
+ this.x = w * quaternion.x + x * quaternion.w + y * quaternion.z - z * quaternion.y;
+ this.y = w * quaternion.y + y * quaternion.w + z * quaternion.x - x * quaternion.z;
+ this.z = w * quaternion.z + z * quaternion.w + x * quaternion.y - y * quaternion.x;
+ return this;
+ };
+
+ /**
+ * Normalizes a quaternion
+ * @returns {cc.math.Quaternion}
+ */
+ proto.normalize = function(){ //=cc.kmQuaternionNormalize
+ var length = this.length();
+ if (Math.abs(length) <= cc.math.EPSILON)
+ throw new Error("current quaternion is an invalid value");
+ this.scale(1.0 / length);
+ return this;
+ };
+
+ /**
+ * Rotates a quaternion around an axis and an angle
+ * @param {cc.math.Vec3} axis
+ * @param {Number} angle
+ */
+ proto.rotationAxis = function(axis, angle){ //cc.kmQuaternionRotationAxis
+ var rad = angle * 0.5, scale = Math.sin(rad);
+ this.w = Math.cos(rad);
+ this.x = axis.x * scale;
+ this.y = axis.y * scale;
+ this.z = axis.z * scale;
+ return this;
+ };
+
+ /**
+ * Creates a quaternion from a rotation matrix
+ * @param mat3
+ * @returns {*}
+ */
+ cc.math.Quaternion.rotationMatrix = function (mat3) { //cc.kmQuaternionRotationMatrix
+ if (!mat3)
+ return null;
+
+ var x, y, z, w;
+ var m4x4 = [], mat = mat3.mat, scale = 0.0;
+
+ /* 0 3 6
+ 1 4 7
+ 2 5 8
+
+ 0 1 2 3
+ 4 5 6 7
+ 8 9 10 11
+ 12 13 14 15*/
+ m4x4[0] = mat[0];
+ m4x4[1] = mat[3];
+ m4x4[2] = mat[6];
+ m4x4[4] = mat[1];
+ m4x4[5] = mat[4];
+ m4x4[6] = mat[7];
+ m4x4[8] = mat[2];
+ m4x4[9] = mat[5];
+ m4x4[10] = mat[8];
+ m4x4[15] = 1;
+ var pMatrix = m4x4[0];
+
+ var diagonal = pMatrix[0] + pMatrix[5] + pMatrix[10] + 1;
+ if (diagonal > cc.math.EPSILON) {
+ // Calculate the scale of the diagonal
+ scale = Math.sqrt(diagonal) * 2;
- if (a < (1e-6 - 1.0)) {
- if (Math.abs(cc.kmVec3LengthSq(fallback)) < cc.kmEpsilon) {
- cc.kmQuaternionRotationAxis(pOut, fallback, cc.kmPI);
+ // Calculate the x, y, x and w of the quaternion through the respective equation
+ x = ( pMatrix[9] - pMatrix[6] ) / scale;
+ y = ( pMatrix[2] - pMatrix[8] ) / scale;
+ z = ( pMatrix[4] - pMatrix[1] ) / scale;
+ w = 0.25 * scale;
} else {
- var axis = new cc.kmVec3();
- var X = new cc.kmVec3();
- X.x = 1.0;
- X.y = 0.0;
- X.z = 0.0;
-
- cc.kmVec3Cross(axis, X, vec1);
-
- //If axis is zero
- if (Math.abs(cc.kmVec3LengthSq(axis)) < cc.kmEpsilon) {
- var Y = new cc.kmVec3();
- Y.x = 0.0;
- Y.y = 1.0;
- Y.z = 0.0;
-
- cc.kmVec3Cross(axis, Y, vec1);
+ // If the first element of the diagonal is the greatest value
+ if (pMatrix[0] > pMatrix[5] && pMatrix[0] > pMatrix[10]) {
+ // Find the scale according to the first element, and double that value
+ scale = Math.sqrt(1.0 + pMatrix[0] - pMatrix[5] - pMatrix[10]) * 2.0;
+
+ // Calculate the x, y, x and w of the quaternion through the respective equation
+ x = 0.25 * scale;
+ y = (pMatrix[4] + pMatrix[1] ) / scale;
+ z = (pMatrix[2] + pMatrix[8] ) / scale;
+ w = (pMatrix[9] - pMatrix[6] ) / scale;
+ }
+ // Else if the second element of the diagonal is the greatest value
+ else if (pMatrix[5] > pMatrix[10]) {
+ // Find the scale according to the second element, and double that value
+ scale = Math.sqrt(1.0 + pMatrix[5] - pMatrix[0] - pMatrix[10]) * 2.0;
+
+ // Calculate the x, y, x and w of the quaternion through the respective equation
+ x = (pMatrix[4] + pMatrix[1] ) / scale;
+ y = 0.25 * scale;
+ z = (pMatrix[9] + pMatrix[6] ) / scale;
+ w = (pMatrix[2] - pMatrix[8] ) / scale;
+ } else {
+ // Else the third element of the diagonal is the greatest value
+
+ // Find the scale according to the third element, and double that value
+ scale = Math.sqrt(1.0 + pMatrix[10] - pMatrix[0] - pMatrix[5]) * 2.0;
+
+ // Calculate the x, y, x and w of the quaternion through the respective equation
+ x = (pMatrix[2] + pMatrix[8] ) / scale;
+ y = (pMatrix[9] + pMatrix[6] ) / scale;
+ z = 0.25 * scale;
+ w = (pMatrix[4] - pMatrix[1] ) / scale;
}
-
- cc.kmVec3Normalize(axis, axis);
- cc.kmQuaternionRotationAxis(pOut, axis, cc.kmPI);
}
- } else {
- var s = Math.sqrt((1 + a) * 2);
- var invs = 1 / s;
-
- var c = new cc.kmVec3();
- cc.kmVec3Cross(c, v1, v2);
-
- pOut.x = c.x * invs;
- pOut.y = c.y * invs;
- pOut.z = c.z * invs;
- pOut.w = s * 0.5;
-
- cc.kmQuaternionNormalize(pOut, pOut);
- }
- return pOut;
-};
-
-cc.kmQuaternionMultiplyVec3 = function (pOut, q, v) {
- var uv = new cc.kmVec3(), uuv = new cc.kmVec3(), qvec = new cc.kmVec3();
-
- qvec.x = q.x;
- qvec.y = q.y;
- qvec.z = q.z;
+ return new cc.math.Quaternion(x, y, z, w);
+ };
+
+ /**
+ * Create a quaternion from yaw, pitch and roll
+ * @param yaw
+ * @param pitch
+ * @param roll
+ * @returns {cc.math.Quaternion}
+ */
+ cc.math.Quaternion.rotationYawPitchRoll = function (yaw, pitch, roll) { //cc.kmQuaternionRotationYawPitchRoll
+ var ex, ey, ez; // temp half euler angles
+ var cr, cp, cy, sr, sp, sy, cpcy, spsy; // temp vars in roll,pitch yaw
+
+ ex = cc.degreesToRadians(pitch) / 2.0; // convert to rads and half them
+ ey = cc.degreesToRadians(yaw) / 2.0;
+ ez = cc.degreesToRadians(roll) / 2.0;
+
+ cr = Math.cos(ex);
+ cp = Math.cos(ey);
+ cy = Math.cos(ez);
+
+ sr = Math.sin(ex);
+ sp = Math.sin(ey);
+ sy = Math.sin(ez);
+
+ cpcy = cp * cy;
+ spsy = sp * sy;
+
+ var ret = new cc.math.Quaternion();
+ ret.w = cr * cpcy + sr * spsy;
+ ret.x = sr * cpcy - cr * spsy;
+ ret.y = cr * sp * cy + sr * cp * sy;
+ ret.z = cr * cp * sy - sr * sp * cy;
+ ret.normalize();
+ return ret;
+ };
+
+ /**
+ * Interpolate with other quaternions
+ * @param {cc.math.Quaternion} quaternion
+ * @param {Number} t
+ * @returns {cc.math.Quaternion}
+ */
+ proto.slerp = function(quaternion, t) { //=cc.kmQuaternionSlerp
+ if (this.x === quaternion.x && this.y === quaternion.y && this.z === quaternion.z && this.w === quaternion.w) {
+ return this;
+ }
+ var ct = this.dot(quaternion), theta = Math.acos(ct), st = Math.sqrt(1.0 - cc.math.square(ct));
+ var stt = Math.sin(t * theta) / st, somt = Math.sin((1.0 - t) * theta) / st;
+ var temp2 = new cc.math.Quaternion(quaternion);
+ this.scale(somt);
+ temp2.scale(stt);
+ this.add(temp2);
+ return this;
+ };
+
+ /**
+ * Get the axis and angle of rotation from a quaternion
+ * @returns {{axis: cc.math.Vec3, angle: number}}
+ */
+ proto.toAxisAndAngle = function(){ //=cc.kmQuaternionToAxisAngle
+ var tempAngle; // temp angle
+ var scale; // temp vars
+ var retAngle, retAxis = new cc.math.Vec3();
+
+ tempAngle = Math.acos(this.w);
+ scale = Math.sqrt(cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z));
+
+ if (((scale > -cc.math.EPSILON) && scale < cc.math.EPSILON)
+ || (scale < 2 * Math.PI + cc.math.EPSILON && scale > 2 * Math.PI - cc.math.EPSILON)) { // angle is 0 or 360 so just simply set axis to 0,0,1 with angle 0
+ retAngle = 0.0;
+ retAxis.x = 0.0;
+ retAxis.y = 0.0;
+ retAxis.z = 1.0;
+ } else {
+ retAngle = tempAngle * 2.0; // angle in radians
+ retAxis.x = this.x / scale;
+ retAxis.y = this.y / scale;
+ retAxis.z = this.z / scale;
+ retAxis.normalize();
+ }
+ return {axis: retAxis, angle: retAngle};
+ };
- cc.kmVec3Cross(uv, qvec, v);
- cc.kmVec3Cross(uuv, qvec, uv);
+ /**
+ * Scale a quaternion
+ * @param {Number} scale
+ */
+ proto.scale = function(scale) { //cc.kmQuaternionScale
+ this.x *= scale;
+ this.y *= scale;
+ this.z *= scale;
+ this.w *= scale;
+ return this;
+ };
+
+ /**
+ * Assign current quaternion value from a quaternion.
+ * @param {cc.math.Quaternion} quaternion
+ * @returns {cc.math.Quaternion} current quaternion
+ */
+ proto.assignFrom = function(quaternion){ //=cc.kmQuaternionAssign
+ this.x = quaternion.x;
+ this.y = quaternion.y;
+ this.z = quaternion.z;
+ this.w = quaternion.w;
+ return this;
+ };
+
+ /**
+ * Adds other quaternion
+ * @param {cc.math.Quaternion} quaternion
+ * @returns {cc.math.Quaternion}
+ */
+ proto.add = function(quaternion) { //cc.kmQuaternionAdd
+ this.x += quaternion.x;
+ this.y += quaternion.y;
+ this.z += quaternion.z;
+ this.w += quaternion.w;
+ return this;
+ };
+
+ /**
+ *
+ * Adapted from the OGRE engine!
+ * Gets the shortest arc quaternion to rotate this vector to the destination vector.
+ * @remarks
+ * If you call this with a destination vector that is close to the inverse
+ * of this vector, we will rotate 180 degrees around the 'fallbackAxis'
+ * (if specified, or a generated axis if not) since in this case ANY axis of rotation is valid.
+ *
+ * @param {cc.math.Vec3} vec1
+ * @param {cc.math.Vec3} vec2
+ * @param {cc.math.Vec3} fallback
+ * @returns {cc.math.Quaternion}
+ */
+ cc.math.Quaternion.rotationBetweenVec3 = function(vec1, vec2, fallback) { //cc.kmQuaternionRotationBetweenVec3
+ var v1 = new cc.math.Vec3(vec1), v2 = new cc.math.Vec3(vec2);
+ v1.normalize();
+ v2.normalize();
+ var a = v1.dot(v2), quaternion = new cc.math.Quaternion();
+
+ if (a >= 1.0) {
+ quaternion.identity();
+ return quaternion;
+ }
- cc.kmVec3Scale(uv, uv, (2.0 * q.w));
- cc.kmVec3Scale(uuv, uuv, 2.0);
+ if (a < (1e-6 - 1.0)) {
+ if (Math.abs(fallback.lengthSq()) < cc.math.EPSILON) {
+ quaternion.rotationAxis(fallback, Math.PI);
+ } else {
+ var axis = new cc.math.Vec3(1.0, 0.0, 0.0);
+ axis.cross(vec1);
+
+ //If axis is zero
+ if (Math.abs(axis.lengthSq()) < cc.math.EPSILON) {
+ axis.fill(0.0, 1.0, 0.0);
+ axis.cross(vec1);
+ }
+ axis.normalize();
+ quaternion.rotationAxis(axis, Math.PI);
+ }
+ } else {
+ var s = Math.sqrt((1 + a) * 2), invs = 1 / s;
+ v1.cross(v2);
+ quaternion.x = v1.x * invs;
+ quaternion.y = v1.y * invs;
+ quaternion.z = v1.z * invs;
+ quaternion.w = s * 0.5;
+ quaternion.normalize();
+ }
+ return quaternion;
+ };
- cc.kmVec3Add(pOut, v, uv);
- cc.kmVec3Add(pOut, pOut, uuv);
+ /**
+ * Current quaternion multiplies a vec3
+ * @param {cc.math.Vec3} vec
+ * @returns {cc.math.Vec3}
+ */
+ proto.multiplyVec3 = function(vec){ //=cc.kmQuaternionMultiplyVec3
+ var x = this.x, y = this.y, z = this.z, retVec = new cc.math.Vec3(vec);
+ var uv = new cc.math.Vec3(x, y, z), uuv = new cc.math.Vec3(x, y, z);
+ uv.cross(vec);
+ uuv.cross(uv);
+ uv.scale((2.0 * q.w));
+ uuv.scale(2.0);
+
+ retVec.add(uv);
+ retVec.add(uuv);
+ return retVec;
+ };
+})(cc);
- return pOut;
-};
diff --git a/cocos2d/kazmath/ray2.js b/cocos2d/kazmath/ray2.js
index 3a84f70b53..5a29794e88 100644
--- a/cocos2d/kazmath/ray2.js
+++ b/cocos2d/kazmath/ray2.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,139 +26,115 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.kmRay2 = function(start, dir){
- this.start = start || new cc.kmVec2();
- this.start = start || new cc.kmVec2();
-};
-
-cc.kmRay2Fill = function(ray, px, py,vx,vy){
- ray.start.x = px;
- ray.start.y = py;
- ray.dir.x = vx;
- ray.dir.y = vy;
-};
-
-cc.kmRay2IntersectLineSegment = function(ray, p1, p2, intersection){
- var x1 = ray.start.x;
- var y1 = ray.start.y;
- var x2 = ray.start.x + ray.dir.x;
- var y2 = ray.start.y + ray.dir.y;
- var x3 = p1.x;
- var y3 = p1.y;
- var x4 = p2.x;
- var y4 = p2.y;
-
- var denom = (y4 -y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
- var ua, x, y;
- //If denom is zero, the lines are parallel
- if(denom > -cc.kmEpsilon && denom < cc.kmEpsilon) {
- return cc.KM_FALSE;
- }
+(function(cc){
+ cc.math.Ray2 = function (start, dir) { // = cc.kmRay2
+ this.start = start || new cc.math.Vec2();
+ this.dir = dir || new cc.math.Vec2();
+ };
+
+ cc.math.Ray2.prototype.fill = function (px, py, vx, vy) { // = cc.kmRay2Fill
+ this.start.x = px;
+ this.start.y = py;
+ this.dir.x = vx;
+ this.dir.y = vy;
+ };
+
+ cc.math.Ray2.prototype.intersectLineSegment = function (p1, p2, intersection) { // = cc.kmRay2IntersectLineSegment
+ var x1 = this.start.x, y1 = this.start.y;
+ var x2 = this.start.x + this.dir.x, y2 = this.start.y + this.dir.y;
+ var x3 = p1.x, y3 = p1.y;
+ var x4 = p2.x, y4 = p2.y;
+
+ var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
+ var ua, x, y;
+ //If denom is zero, the lines are parallel
+ if (denom > -cc.math.EPSILON && denom < cc.math.EPSILON)
+ return false;
+
+ ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
+ //var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
+
+ x = x1 + ua * (x2 - x1);
+ y = y1 + ua * (y2 - y1);
+
+ if (x < Math.min(p1.x, p2.x) - cc.math.EPSILON ||
+ x > Math.max(p1.x, p2.x) + cc.math.EPSILON ||
+ y < Math.min(p1.y, p2.y) - cc.math.EPSILON ||
+ y > Math.max(p1.y, p2.y) + cc.math.EPSILON) {
+ //Outside of line
+ //printf("Outside of line, %f %f (%f %f)(%f, %f)\n", x, y, p1.x, p1.y, p2.x, p2.y);
+ return false;
+ }
- ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
-// var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
+ if (x < Math.min(x1, x2) - cc.math.EPSILON ||
+ x > Math.max(x1, x2) + cc.math.EPSILON ||
+ y < Math.min(y1, y2) - cc.math.EPSILON ||
+ y > Math.max(y1, y2) + cc.math.EPSILON) {
+ //printf("Outside of ray, %f %f (%f %f)(%f, %f)\n", x, y, x1, y1, x2, y2);
+ return false;
+ }
- x = x1 + ua * (x2 - x1);
- y = y1 + ua * (y2 - y1);
+ intersection.x = x;
+ intersection.y = y;
+ return true;
+ };
- if(x < cc.kmMin(p1.x, p2.x) - cc.kmEpsilon ||
- x > cc.kmMax(p1.x, p2.x) + cc.kmEpsilon ||
- y < cc.kmMin(p1.y, p2.y) - cc.kmEpsilon ||
- y > cc.kmMax(p1.y, p2.y) + cc.kmEpsilon) {
- //Outside of line
- //printf("Outside of line, %f %f (%f %f)(%f, %f)\n", x, y, p1.x, p1.y, p2.x, p2.y);
- return cc.KM_FALSE;
- }
+ function calculate_line_normal(p1, p2, normalOut){
+ var tmp = new cc.math.Vec2(p2);
+ tmp.subtract(p1);
- if(x < cc.kmMin(x1, x2) - cc.kmEpsilon ||
- x > cc.kmMax(x1, x2) + cc.kmEpsilon ||
- y < cc.kmMin(y1, y2) - cc.kmEpsilon ||
- y > cc.kmMax(y1, y2) + cc.kmEpsilon) {
- //printf("Outside of ray, %f %f (%f %f)(%f, %f)\n", x, y, x1, y1, x2, y2);
- return cc.KM_FALSE;
+ normalOut.x = -tmp.y;
+ normalOut.y = tmp.x;
+ normalOut.normalize();
+ //TODO: should check that the normal is pointing out of the triangle
}
- intersection.x = x;
- intersection.y = y;
-
- return cc.KM_TRUE;
-};
-
-cc.calculate_line_normal = function(p1, p2, normal_out){
- var tmp = new cc.kmVec2();
- cc.kmVec2Subtract(tmp, p2, p1); //Get direction vector
-
- normal_out.x = -tmp.y;
- normal_out.y = tmp.x;
- cc.kmVec2Normalize(normal_out, normal_out);
-
- //TODO: should check that the normal is pointing out of the triangle
-};
-
-cc.kmRay2IntersectTriangle = function(ray, p1, p2, p3, intersection, normal_out){
- var intersect = new cc.kmVec2();
- var final_intersect = new cc.kmVec2();
- var normal = new cc.kmVec2();
- var distance = 10000.0;
- var intersected = cc.KM_FALSE;
-
- var tmp,this_distance;
-
- if(cc.kmRay2IntersectLineSegment(ray, p1, p2, intersect)) {
- tmp = new cc.kmVec2();
-
- intersected = cc.KM_TRUE;
- this_distance = cc.kmVec2Length(cc.kmVec2Subtract(tmp, intersect, ray.start));
- if(this_distance < distance) {
- final_intersect.x = intersect.x;
- final_intersect.y = intersect.y;
- distance = this_distance;
-
- cc.calculate_line_normal(p1, p2, normal);
+ cc.math.Ray2.prototype.intersectTriangle = function(p1, p2, p3, intersection, normal_out){
+ var intersect = new cc.math.Vec2(), final_intersect = new cc.math.Vec2();
+ var normal = new cc.math.Vec2(), distance = 10000.0, intersected = false;
+ var this_distance;
+
+ if(this.intersectLineSegment(p1, p2, intersect)) {
+ intersected = true;
+ this_distance = intersect.subtract(this.start).length();
+ if(this_distance < distance) {
+ final_intersect.x = intersect.x;
+ final_intersect.y = intersect.y;
+ distance = this_distance;
+ calculate_line_normal(p1, p2, normal);
+ }
}
- }
-
- if(cc.kmRay2IntersectLineSegment(ray, p2, p3, intersect)) {
- tmp = new cc.kmVec2();
- intersected = cc.KM_TRUE;
- this_distance = cc.kmVec2Length(cc.kmVec2Subtract(tmp, intersect, ray.start));
- if(this_distance < distance) {
- final_intersect.x = intersect.x;
- final_intersect.y = intersect.y;
- distance = this_distance;
-
- cc.calculate_line_normal(p2, p3, normal);
+ if(this.intersectLineSegment(p2, p3, intersect)) {
+ intersected = true;
+ this_distance = intersect.subtract(this.start).length();
+ if(this_distance < distance) {
+ final_intersect.x = intersect.x;
+ final_intersect.y = intersect.y;
+ distance = this_distance;
+ calculate_line_normal(p2, p3, normal);
+ }
}
- }
-
- if(cc.kmRay2IntersectLineSegment(ray, p3, p1, intersect)) {
- tmp = new cc.kmVec2();
- intersected = cc.KM_TRUE;
- this_distance = cc.kmVec2Length(cc.kmVec2Subtract(tmp, intersect, ray.start));
- if(this_distance < distance) {
- final_intersect.x = intersect.x;
- final_intersect.y = intersect.y;
- distance = this_distance;
-
- cc.calculate_line_normal(p3, p1, normal);
+ if(this.intersectLineSegment(p3, p1, intersect)) {
+ intersected = true;
+ this_distance = intersect.subtract(this.start).length();
+ if(this_distance < distance) {
+ final_intersect.x = intersect.x;
+ final_intersect.y = intersect.y;
+ distance = this_distance;
+ calculate_line_normal(p3, p1, normal);
+ }
}
- }
- if(intersected) {
- intersection.x = final_intersect.x;
- intersection.y = final_intersect.y;
- if(normal_out) {
- normal_out.x = normal.x;
- normal_out.y = normal.y;
+ if(intersected) {
+ intersection.x = final_intersect.x;
+ intersection.y = final_intersect.y;
+ if(normal_out) {
+ normal_out.x = normal.x;
+ normal_out.y = normal.y;
+ }
}
- }
-
- return intersected;
-};
-
-cc.kmRay2IntersectCircle = function(ray, centre, radius, intersection) {
- cc.Assert(0 , "Not implemented");
- return 0;
-};
\ No newline at end of file
+ return intersected;
+ };
+})(cc);
diff --git a/cocos2d/kazmath/simd_benchmark/base.js b/cocos2d/kazmath/simd_benchmark/base.js
new file mode 100644
index 0000000000..d01857c77e
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/base.js
@@ -0,0 +1,139 @@
+// SIMD Kernel Benchmark Harness
+// Author: Peter Jensen
+
+function Benchmark (config) {
+ this.config = config;
+ this.initOk = true; // Initialize all properties used on a Benchmark object
+ this.cleanupOk = true;
+ this.useAutoIterations = true;
+ this.autoIterations = 0;
+ this.actualIterations = 0;
+ this.simdTime = 0;
+ this.nonSimdTime = 0;
+}
+
+function Benchmarks () {
+ this.benchmarks = [];
+}
+
+Benchmarks.prototype.add = function (benchmark) {
+ this.benchmarks.push (benchmark);
+ return this.benchmarks.length - 1;
+}
+
+Benchmarks.prototype.runOne = function (benchmark) {
+
+ function timeKernel(kernel, iterations) {
+ var start, stop;
+ start = Date.now();
+ kernel(iterations);
+ stop = Date.now();
+ return stop - start;
+ }
+
+ function computeIterations() {
+ var desiredRuntime = 1000; // milliseconds for longest running kernel
+ var testIterations = 10; // iterations used to determine time for desiredRuntime
+
+ // Make the slowest kernel run for at least 500ms
+ var simdTime = timeKernel(benchmark.config.kernelSimd, testIterations);
+ var nonSimdTime = timeKernel(benchmark.config.kernelNonSimd, testIterations);
+ var maxTime = simdTime > nonSimdTime ? simdTime : nonSimdTime;
+ while (maxTime < 500) {
+ testIterations *= 2;
+ simdTime = timeKernel(benchmark.config.kernelSimd, testIterations);
+ nonSimdTime = timeKernel(benchmark.config.kernelNonSimd, testIterations);
+ maxTime = simdTime > nonSimdTime ? simdTime : nonSimdTime;
+ }
+ maxTime = simdTime > nonSimdTime ? simdTime : nonSimdTime;
+
+ // Compute iteration count for 1 second run of slowest kernel
+ var iterations = Math.ceil(desiredRuntime * testIterations / maxTime);
+ return iterations;
+ }
+
+ // Initialize the kernels and check the correctness status
+ if (!benchmark.config.kernelInit()) {
+ benchmark.initOk = false;
+ return false;
+ }
+
+ // Determine how many iterations to use.
+ if (benchmark.useAutoIterations) {
+ benchmark.autoIterations = computeIterations();
+ benchmark.actualIterations = benchmark.autoIterations;
+ }
+ else {
+ benchmark.actualIterations = benchmark.config.kernelIterations;
+ }
+
+ // Run the SIMD kernel
+ benchmark.simdTime = timeKernel(benchmark.config.kernelSimd, benchmark.actualIterations);
+
+ // Run the non-SIMD kernel
+ benchmark.nonSimdTime = timeKernel(benchmark.config.kernelNonSimd, benchmark.actualIterations);
+
+ // Do the final sanity check
+ if (!benchmark.config.kernelCleanup()) {
+ benchmark.cleanupOk = false;
+ return false;
+ }
+
+ return true;
+}
+
+Benchmarks.prototype.report = function (benchmark, outputFunctions) {
+
+ function fillRight(str, width) {
+ str += ""; // make sure it's a string
+ while (str.length < width) {
+ str += " ";
+ }
+ return str;
+ }
+
+ function fillLeft(str, width) {
+ str += ""; // make sure it's a string
+ while (str.length < width) {
+ str = " " + str;
+ }
+ return str;
+ }
+
+ if (!benchmark.initOk) {
+ outputFunctions.notifyError(fillRight(benchmark.config.kernelName + ": ", 23) + "FAILED INIT");
+ return;
+ }
+ if (!benchmark.cleanupOk) {
+ outputFunctions.notifyError(fillRight(benchmark.config.kernelName + ": ", 23) + "FAILED CLEANUP");
+ return;
+ }
+
+ var ratio = benchmark.nonSimdTime / benchmark.simdTime;
+ ratio = ratio.toFixed(2);
+ outputFunctions.notifyResult(
+ fillRight(benchmark.config.kernelName + ": ", 23) +
+ "Iterations(" + fillLeft(benchmark.actualIterations, 10) + ")" +
+ ", SIMD(" + fillLeft(benchmark.simdTime + "ms)", 8) +
+ ", Non-SIMD(" + fillLeft(benchmark.nonSimdTime + "ms)", 8) +
+ ", Speedup(" + ratio + ")");
+ outputFunctions.timeData.labels.push(benchmark.config.kernelName);
+ outputFunctions.timeData.datasets[0].data.push(benchmark.simdTime);
+ outputFunctions.timeData.datasets[1].data.push(benchmark.nonSimdTime);
+ outputFunctions.speedupData.labels.push(benchmark.config.kernelName);
+ outputFunctions.speedupData.datasets[0].data.push(ratio);
+}
+
+Benchmarks.prototype.runAll = function (outputFunctions, useAutoIterations) {
+ if (typeof useAutoIterations === "undefined") {
+ useAutoIterations = false;
+ }
+ for (var i = 0, n = this.benchmarks.length; i < n; ++i) {
+ var benchmark = this.benchmarks[i];
+ benchmark.useAutoIterations = useAutoIterations;
+ this.runOne(benchmark);
+ this.report(benchmark, outputFunctions);
+ }
+}
+
+var benchmarks = new Benchmarks ();
diff --git a/cocos2d/kazmath/simd_benchmark/index.html b/cocos2d/kazmath/simd_benchmark/index.html
new file mode 100644
index 0000000000..8c9cb4f410
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/index.html
@@ -0,0 +1,44 @@
+
+
+
+
+ Kazmath SIMD benchmarks
+
+
+
+ Running benchmarks...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/cocos2d/kazmath/simd_benchmark/kernel-template.js b/cocos2d/kazmath/simd_benchmark/kernel-template.js
new file mode 100644
index 0000000000..d7c377585d
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kernel-template.js
@@ -0,0 +1,64 @@
+// Kernel template
+// Author: Peter Jensen
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "Test",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 100000000
+ };
+
+ // Hook up to the harness
+ benchmarks.add (new Benchmark (kernelConfig));
+
+ // Kernel Initializer
+ function init () {
+ // Do initial sanity check and initialize data for the kernels.
+ // The sanity check should verify that the simd and nonSimd results
+ // are the same.
+ // It is recommended to do minimal object creation in the kernels
+ // themselves. If global data needs to be initialized, here would
+ // be the place to do it.
+ // If the sanity checks fails the kernels will not be executed
+ // Returns:
+ // true: First run (unoptimized) of the kernels passed
+ // false: First run (unoptimized) of the kernels failed
+ return simd (1) === nonSimd (1);
+ }
+
+ // Kernel Cleanup
+ function cleanup () {
+ // Do final sanity check and perform cleanup.
+ // This function is called when all the kernel iterations have been
+ // executed, so they should be in their final optimized version. The
+ // sanity check done during initialization will probably be of the
+ // initial unoptimized version.
+ // Returns:
+ // true: Last run (optimized) of the kernels passed
+ // false: last run (optimized) of the kernels failed
+ return simd (1) === nonSimd (1);
+ }
+
+ // SIMD version of the kernel
+ function simd (n) {
+ var s = 0;
+ for (var i = 0; i < n; ++i) {
+ s += i;
+ }
+ return s;
+ }
+
+ // Non SIMD version of the kernel
+ function nonSimd (n) {
+ var s = 0;
+ for (var i = 0; i < n; ++i) {
+ s += i;
+ }
+ return s;
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmMat4AreEqual.js b/cocos2d/kazmath/simd_benchmark/kmMat4AreEqual.js
new file mode 100644
index 0000000000..a3dee727ac
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmMat4AreEqual.js
@@ -0,0 +1,77 @@
+// kmMat4AreEqual
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmMat4AreEqual",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var T1 = new cc.kmMat4();
+ var T2 = new cc.kmMat4();
+ var T1x4 = new cc.kmMat4();
+ var T2x4 = new cc.kmMat4();
+ var areEqual, areEqualSIMD;
+
+ function equals(A, B) {
+ for (var i = 0; i < 16; ++i) {
+ if (A[i] != B[i])
+ return false;
+ }
+ return true;
+ }
+
+ function init() {
+ T1.mat[0] = 1.0;
+ T1.mat[5] = 1.0;
+ T1.mat[10] = 1.0;
+ T1.mat[15] = 1.0;
+
+ T2.mat[0] = 1.0;
+ T2.mat[5] = 1.0;
+ T2.mat[10] = 1.0;
+ T2.mat[15] = 1.0;
+
+ T1x4.mat[0] = 1.0;
+ T1x4.mat[5] = 1.0;
+ T1x4.mat[10] = 1.0;
+ T1x4.mat[15] = 1.0;
+
+ T2x4.mat[0] = 1.0;
+ T2x4.mat[5] = 1.0;
+ T2x4.mat[10] = 1.0;
+ T2x4.mat[15] = 1.0;
+
+ nonSimd(1);
+ simd(1);
+
+ return equals(T1.mat, T1x4.mat) && equals(T2.mat, T2x4.mat) && (areEqual === areEqualSIMD);
+
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ areEqual = T1.equals(T2);
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ areEqualSIMD = T1x4.equalsSIMD(T2x4);
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmMat4Assign.js b/cocos2d/kazmath/simd_benchmark/kmMat4Assign.js
new file mode 100644
index 0000000000..e8e386f781
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmMat4Assign.js
@@ -0,0 +1,68 @@
+// kmMat4Assign
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmMat4Assign",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var T1 = new cc.kmMat4();
+ var T2 = new cc.kmMat4();
+ var T1x4 = new cc.kmMat4();
+ var T2x4 = new cc.kmMat4();
+
+ function equals(A, B) {
+ for (var i = 0; i < 16; ++i) {
+ if (A[i] != B[i])
+ return false;
+ }
+ return true;
+ }
+
+ function init() {
+ T1.mat[0] = 1.0;
+ T1.mat[5] = 1.0;
+ T1.mat[10] = 1.0;
+ T1.mat[15] = 1.0;
+
+ T1x4.mat[0] = 1.0;
+ T1x4.mat[5] = 1.0;
+ T1x4.mat[10] = 1.0;
+ T1x4.mat[15] = 1.0;
+
+ nonSimd(1);
+ simd(1);
+
+ return equals(T1.mat, T1x4.mat) && equals(T2.mat, T2x4.mat);
+
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ //cc.kmMat4Assign(T2, T1);
+ T2.assignFrom(T1);
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ //cc.kmMat4AssignSIMD(T2x4, T1x4);
+ T2x4.assignFromSIMD(T1x4);
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmMat4Inverse.js b/cocos2d/kazmath/simd_benchmark/kmMat4Inverse.js
new file mode 100644
index 0000000000..212dff1af1
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmMat4Inverse.js
@@ -0,0 +1,116 @@
+// kmMat4Inverse
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmMat4Inverse",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var src = new cc.kmMat4();
+ var dst = new cc.kmMat4();
+ var srcx4 = new cc.kmMat4();
+ var dstx4 = new cc.kmMat4();
+ var ident = new Float32Array(
+ [1,0,0,0,
+ 0,1,0,0,
+ 0,0,1,0,
+ 0,0,0,1]);
+
+ function equals(A, B) {
+ for (var i = 0; i < 16; ++i) {
+ if (Math.abs (A[i] - B[i]) > 5)
+ return false;
+ }
+ return true;
+ }
+
+ function initMatrix(matrix) {
+ // These values were chosen somewhat randomly, but they will at least yield a solution.
+ matrix [0] = 0; matrix[1] = 1; matrix[2] = 2; matrix[3] = 3;
+ matrix [4] = -1; matrix[5] = -2; matrix[6] = -3; matrix[7] = -4;
+ matrix [8] = 0; matrix[9] = 0; matrix[10] = 2; matrix[11] = 3;
+ matrix [12] = -1; matrix[13] = -2; matrix[14] = 0; matrix[15] = -4;
+ }
+
+ function mulMatrix(dst, op1, op2) {
+ for (var r = 0; r < 4; ++r) {
+ for (var c = 0; c < 4; ++c) {
+ var ri = 4*r;
+ dst[ri + c] = op1[ri]*op2[c] + op1[ri+1]*op2[c+4] + op1[ri+2]*op2[c+8] + op1[ri+3]*op2[c+12];
+ }
+ }
+ }
+
+ function printMatrix(matrix, str) {
+ print('--------matrix ' + str + '----------');
+ for (var r = 0; r < 4; ++r) {
+ var str = "";
+ var ri = r*4;
+ for (var c = 0; c < 4; ++c) {
+ var value = matrix[ri + c];
+ str += " " + value.toFixed(2);
+ }
+ print(str);
+ }
+ }
+
+ function checkMatrix(src, dst) {
+ // when multiplied with the src matrix it should yield the identity matrix
+ var tmp = new Float32Array(16);
+ mulMatrix(tmp, src, dst);
+ for (var i = 0; i < 16; ++i) {
+ if (Math.abs (tmp[i] - ident[i]) > 0.00001) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function init() {
+ initMatrix(src.mat);
+ // printMatrix(src);
+ nonSimd(1);
+ // printMatrix(dst);
+ if (!checkMatrix(src.mat, dst.mat)) {
+ return false;
+ }
+
+ initMatrix(srcx4.mat);
+ simd(1);
+ // printMatrix(dst);
+ if (!checkMatrix(srcx4.mat, dstx4.mat)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ //cc.kmMat4Inverse(dst, src);
+ dst = src.inverse();
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ //cc.kmMat4InverseSIMD(dstx4, srcx4);
+ dstx4 = srcx4.inverseSIMD();
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmMat4IsIdentity.js b/cocos2d/kazmath/simd_benchmark/kmMat4IsIdentity.js
new file mode 100644
index 0000000000..9ab17ac744
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmMat4IsIdentity.js
@@ -0,0 +1,65 @@
+// kmMat4IsIdentity
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmMat4IsIdentity",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var T1 = new cc.kmMat4();
+ var T1x4 = new cc.kmMat4();
+ var isIdentity, isIdentitySIMD;
+
+ function equals(A, B) {
+ for (var i = 0; i < 16; ++i) {
+ if (A[i] != B[i])
+ return false;
+ }
+ return true;
+ }
+
+ function init() {
+ T1.mat[0] = 1.0;
+ T1.mat[5] = 1.0;
+ T1.mat[10] = 1.0;
+ T1.mat[15] = 1.0;
+
+ T1x4.mat[0] = 1.0;
+ T1x4.mat[5] = 1.0;
+ T1x4.mat[10] = 1.0;
+ T1x4.mat[15] = 1.0;
+
+ nonSimd(1);
+ simd(1);
+
+ return equals(T1.mat, T1x4.mat) && (isIdentity === isIdentitySIMD);
+
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ isIdentity = T1.isIdentity();
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ isIdentitySIMD = T1x4.isIdentitySIMD();
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmMat4LookAt.js b/cocos2d/kazmath/simd_benchmark/kmMat4LookAt.js
new file mode 100644
index 0000000000..1015ad14eb
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmMat4LookAt.js
@@ -0,0 +1,94 @@
+// kmMat4LookAt
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmMat4LookAt",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var eye = new cc.kmVec3(), center = new cc.kmVec3(), up = new cc.kmVec3();
+ var T1 = new cc.kmMat4();
+ var eye1 = new cc.kmVec3(), center1 = new cc.kmVec3(), up1 = new cc.kmVec3();
+ var T1x4 = new cc.kmMat4();
+
+ function printMatrix(matrix) {
+ print('--------matrix----------');
+ for (var r = 0; r < 4; ++r) {
+ var str = "";
+ var ri = r*4;
+ for (var c = 0; c < 4; ++c) {
+ var value = matrix[ri + c];
+ str += " " + value.toFixed(2);
+ }
+ print(str);
+ }
+ }
+
+ function equals(A, B) {
+ for (var i = 0; i < 16; ++i) {
+ if (Math.abs (A[i] - B[i]) > 0.001) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function init() {
+
+ eye.fill(0, 1, 2);
+ center.fill(2, 1, 0);
+ up.fill(1, 1, 1);
+
+ eye1.fill(0, 1, 2);
+ center1.fill(2, 1, 0);
+ up1.fill(1, 1, 1);
+ /*
+ eye1.data[0] = 0;
+ eye1.data[1] = 1;
+ eye1.data[2] = 2;
+
+ center1.data[0] = 2;
+ center1.data[1] = 1;
+ center1.data[2] = 0;
+
+ up1.data[0] = 1;
+ up1.data[1] = 1;
+ up1.data[2] = 1;
+ */
+ nonSimd(1);
+ //printMatrix(T1.mat);
+ simd(1);
+ //printMatrix(T1x4.mat);
+
+ return equals(T1.mat, T1x4.mat);
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ //cc.kmMat4LookAt(T1, eye, center, up);
+ T1.lookAt(eye, center, up);
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ //cc.kmMat4LookAtSIMD(T1x4, eye1, center1, up1);
+ T1x4.lookAtSIMD(eye1, center1, up1);
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmMat4Multiply.js b/cocos2d/kazmath/simd_benchmark/kmMat4Multiply.js
new file mode 100644
index 0000000000..325b6f95bf
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmMat4Multiply.js
@@ -0,0 +1,74 @@
+// kmMat4Multiply
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmMat4Multiply",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var T1 = new cc.kmMat4();
+ var T2 = new cc.kmMat4();
+ var T1x4 = new cc.kmMat4();
+ var T2x4 = new cc.kmMat4();
+
+ function equals(A, B) {
+ for (var i = 0; i < 16; ++i) {
+ if (A[i] != B[i])
+ return false;
+ }
+ return true;
+ }
+
+ function init() {
+ T1.mat[0] = 1.0;
+ T1.mat[5] = 1.0;
+ T1.mat[10] = 1.0;
+ T1.mat[15] = 1.0;
+
+ T2.mat[0] = 1.0;
+ T2.mat[5] = 1.0;
+ T2.mat[10] = 1.0;
+ T2.mat[15] = 1.0;
+
+ T1x4.mat[0] = 1.0;
+ T1x4.mat[5] = 1.0;
+ T1x4.mat[10] = 1.0;
+ T1x4.mat[15] = 1.0;
+
+ T2x4.mat[0] = 1.0;
+ T2x4.mat[5] = 1.0;
+ T2x4.mat[10] = 1.0;
+ T2x4.mat[15] = 1.0;
+
+ nonSimd(1);
+ simd(1);
+ return equals(T1.mat, T1x4.mat) && equals(T2.mat, T2x4.mat);
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ T1.multiply(T2);
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ T1x4.multiplySIMD(T2x4);
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmMat4Transpose.js b/cocos2d/kazmath/simd_benchmark/kmMat4Transpose.js
new file mode 100644
index 0000000000..cd1b776bf0
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmMat4Transpose.js
@@ -0,0 +1,82 @@
+// kmMat4Transpose
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmMat4Transpose",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var T1 = new cc.kmMat4();
+ var T2 = new cc.kmMat4();
+ var T1x4 = new cc.kmMat4();
+ var T2x4 = new cc.kmMat4();
+
+ function equals(A, B) {
+ for (var i = 0; i < 16; ++i) {
+ if (A[i] != B[i])
+ return false;
+ }
+ return true;
+ }
+
+ function printMatrix(matrix) {
+ print('--------matrix----------');
+ for (var r = 0; r < 4; ++r) {
+ var str = "";
+ var ri = r*4;
+ for (var c = 0; c < 4; ++c) {
+ var value = matrix[ri + c];
+ str += " " + value.toFixed(2);
+ }
+ print(str);
+ }
+ }
+
+ function init() {
+ T1.mat [0] = 0; T1.mat[1] = 1; T1.mat[2] = 2; T1.mat[3] = 3;
+ T1.mat [4] = -1; T1.mat[5] = -2; T1.mat[6] = -3; T1.mat[7] = -4;
+ T1.mat [8] = 0; T1.mat[9] = 0; T1.mat[10] = 2; T1.mat[11] = 3;
+ T1.mat [12] = -1; T1.mat[13] = -2; T1.mat[14] = 0; T1.mat[15] = -4;
+
+ T1x4.mat [0] = 0; T1x4.mat[1] = 1; T1x4.mat[2] = 2; T1x4.mat[3] = 3;
+ T1x4.mat [4] = -1; T1x4.mat[5] = -2; T1x4.mat[6] = -3; T1x4.mat[7] = -4;
+ T1x4.mat [8] = 0; T1x4.mat[9] = 0; T1x4.mat[10] = 2; T1x4.mat[11] = 3;
+ T1x4.mat [12] = -1; T1x4.mat[13] = -2; T1x4.mat[14] = 0; T1x4.mat[15] = -4;
+
+ nonSimd(1);
+ //printMatrix(T2.mat);
+ simd(1);
+ //printMatrix(T2x4.mat);
+ return equals(T1.mat, T1x4.mat) && equals(T2.mat, T2x4.mat);
+
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ T2 = T1.transpose();
+ //T1.transpose();
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ T2x4 = T1x4.transposeSIMD();
+ //T1x4.transposeSIMD();
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/kmVec3TransformCoord.js b/cocos2d/kazmath/simd_benchmark/kmVec3TransformCoord.js
new file mode 100644
index 0000000000..541a926c9d
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/kmVec3TransformCoord.js
@@ -0,0 +1,65 @@
+// kmVec3TransformCoord
+
+(function () {
+
+ // Kernel configuration
+ var kernelConfig = {
+ kernelName: "kmVec3TransformCoord",
+ kernelInit: init,
+ kernelCleanup: cleanup,
+ kernelSimd: simd,
+ kernelNonSimd: nonSimd,
+ kernelIterations: 10000
+ };
+
+ // Hook up to the harness
+ benchmarks.add(new Benchmark(kernelConfig));
+
+ // Benchmark data, initialization and kernel functions
+ var V = new cc.kmVec3();
+ var T = new cc.kmMat4();
+ var Out = new cc.kmVec3();
+ var Vx4 = new cc.kmVec3();
+ var Tx4 = new cc.kmMat4();
+ var Outx4 = new cc.kmVec3();
+
+ function init() {
+ T.mat[0] = 1.0;
+ T.mat[5] = 1.0;
+ T.mat[10] = 1.0;
+ T.mat[15] = 1.0;
+
+ V.fill(0.0, 1.0, 0.0);
+
+ Tx4.mat[0] = 1.0;
+ Tx4.mat[5] = 1.0;
+ Tx4.mat[10] = 1.0;
+ Tx4.mat[15] = 1.0;
+
+ Vx4.fill(0.0, 1.0, 0.0);
+
+ nonSimd(1);
+ simd(1);
+ //console.log(V);
+ //console.log(Vx4);
+ return V.equals(Vx4);
+
+ }
+
+ function cleanup() {
+ return init(); // Sanity checking before and after are the same
+ }
+
+ function nonSimd(n) {
+ for (var i = 0; i < n; i++) {
+ V.transformCoord(T);
+ }
+ }
+
+ function simd(n) {
+ for (var i = 0; i < n; i++) {
+ Vx4.transformCoordSIMD(Tx4);
+ }
+ }
+
+} ());
diff --git a/cocos2d/kazmath/simd_benchmark/run.js b/cocos2d/kazmath/simd_benchmark/run.js
new file mode 100644
index 0000000000..8441ae1eda
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/run.js
@@ -0,0 +1,40 @@
+"use strict"
+
+var cc = {};
+
+load ('base.js');
+
+load ('../utility.js');
+load ('../vec3.js');
+load ('../vec4.js');
+load ('../mat4.js');
+load ('../vec3SIMD.js');
+load ('../mat4SIMD.js');
+
+// load individual benchmarks
+load ('kernel-template.js');
+load ('kmMat4Multiply.js');
+load ('kmMat4Assign.js');
+load ('kmMat4AreEqual.js');
+load ('kmMat4Inverse.js');
+load ('kmMat4IsIdentity.js');
+load ('kmMat4Transpose.js');
+load ('kmMat4LookAt.js');
+load ('kmVec3TransformCoord.js');
+
+function printResult (str) {
+ print (str);
+}
+
+function printError (str) {
+ print (str);
+}
+
+function printScore (str) {
+ print (str);
+}
+
+benchmarks.runAll ({notifyResult: printResult,
+ notifyError: printError,
+ notifyScore: printScore},
+ true);
diff --git a/cocos2d/kazmath/simd_benchmark/run_browser.js b/cocos2d/kazmath/simd_benchmark/run_browser.js
new file mode 100644
index 0000000000..5d2d0cdd74
--- /dev/null
+++ b/cocos2d/kazmath/simd_benchmark/run_browser.js
@@ -0,0 +1,80 @@
+var echo = document.getElementById('echo');
+
+function printResult(str) {
+ console.log(str);
+ echo.innerHTML += str + ' ';
+}
+
+function printError(str) {
+ console.log(str);
+ echo.innerHTML += str + ' ';
+}
+
+function printScore(str) {
+ console.log(str);
+ echo.innerHTML += str + ' ';
+}
+
+var timeData = {
+ labels: [],
+ datasets: [
+ {
+ labels: 'Non-SIMD',
+ fillColor: "rgba(220,220,220,0.5)",
+ strokeColor: "rgba(220,220,220,0.8)",
+ highlightFill: "rgba(220,220,220,0.75)",
+ highlightStroke: "rgba(220,220,220,1)",
+ data: []
+ },
+ {
+ labels: 'SIMD',
+ fillColor: "rgba(151,187,205,0.5)",
+ strokeColor: "rgba(151,187,205,0.8)",
+ highlightFill: "rgba(151,187,205,0.75)",
+ highlightStroke: "rgba(151,187,205,1)",
+ data: []
+ }
+ ]
+};
+
+var speedupData ={
+ labels: [],
+ datasets: [
+ {
+ labels: 'SIMD',
+ fillColor: "rgba(151,187,205,0.5)",
+ strokeColor: "rgba(151,187,205,0.8)",
+ highlightFill: "rgba(151,187,205,0.75)",
+ highlightStroke: "rgba(151,187,205,1)",
+ data: []
+ }
+ ]
+};
+
+window.onload = function() {
+ if (typeof(SIMD) === 'undefined') {
+ var head = document.getElementById('head');
+ head.innerHTML = 'SIMD is not implemented in your browser, stops.';
+ return;
+ }
+ console.log('Running benchmarks.');
+ benchmarks.runAll({notifyResult: printResult,
+ notifyError: printError,
+ notifyScore: printScore,
+ timeData: timeData,
+ speedupData: speedupData}, true);
+ document.getElementById('head').innerHTML = 'Results';
+ document.getElementById('time').innerHTML = 'Time';
+ document.getElementById('speedup').innerHTML = 'Speedup';
+ var ctx1 = document.getElementById("canvasTime").getContext("2d");
+ window.Bar1 = new Chart(ctx1).Bar(timeData, {
+ scaleLabel: "<%=value%>ms",
+ responsive: true
+ });
+ var ctx2 = document.getElementById("canvasSpeedup").getContext("2d");
+ window.Bar2 = new Chart(ctx2).Bar(speedupData, {
+ scaleLabel: " <%=value%>",
+ responsive: true
+ });
+ console.log('Benchmarks completed.');
+};
diff --git a/cocos2d/kazmath/utility.js b/cocos2d/kazmath/utility.js
index a5e2be4798..9cd3fb4c71 100644
--- a/cocos2d/kazmath/utility.js
+++ b/cocos2d/kazmath/utility.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,48 +26,29 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.kmScalar = Number;
-cc.kmBool = Number;
-
-cc.kmEnum = Number;
-
-cc.KM_FALSE = 0;
-
-cc.KM_TRUE = 1;
-
-cc.kmPI = 3.141592;
+/**
+ * The main namespace of Cocos2d-html5's math library,
+ * all math core classes, functions, properties and constants are defined in this namespace
+ * @namespace
+ * @name cc.math
+ */
+cc.math = cc.math || {};
-cc.kmPIOver180 = 0.017453;
+//cc.kmPIOver180 = 0.017453; please use cc.RAD
-cc.kmPIUnder180 = 57.295779;
+//cc.kmPIUnder180 = 57.295779; please use cc.DEG
-cc.kmEpsilon = 1.0 / 64.0;
+cc.math.EPSILON = 1.0 / 64.0; //cc.kmEpsilon
/**
* Returns the square of s (e.g. s*s)
* @param {Number} s
*/
-cc.kmSQR = function(s){
+cc.math.square = function(s){
return s*s;
};
-cc.kmDegreesToRadians = function(degrees){
- return degrees * cc.kmPIOver180;
-};
-
-cc.kmRadiansToDegrees = function(radians){
- return radians * cc.kmPIUnder180;
-};
-
-cc.kmMin = function(lhs,rhs){
- return (lhs < rhs)? lhs : rhs;
-};
-
-cc.kmMax = function(lhs,rhs){
- return (lhs > rhs)? lhs : rhs;
-};
-
-cc.kmAlmostEqual = function(lhs,rhs){
- return (lhs + cc.kmEpsilon > rhs && lhs - cc.kmEpsilon < rhs);
+cc.math.almostEqual = function(lhs,rhs){
+ return (lhs + cc.math.EPSILON > rhs && lhs - cc.math.EPSILON < rhs);
};
diff --git a/cocos2d/kazmath/vec2.js b/cocos2d/kazmath/vec2.js
index 613ad45559..a682bc4853 100644
--- a/cocos2d/kazmath/vec2.js
+++ b/cocos2d/kazmath/vec2.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,82 +26,88 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.kmVec2 = function (x, y) {
- this.x = x || 0;
- this.y = y || 0;
-};
+(function(cc){
+ cc.math.Vec2 = function (x, y) {
+ if(y === undefined){
+ this.x = x.x;
+ this.y = x.y;
+ }else{
+ this.x = x || 0;
+ this.y = y || 0;
+ }
+ };
+
+ var proto = cc.math.Vec2.prototype;
+ proto.fill = function(x, y){ // = cc.kmVec2Fill
+ this.x = x;
+ this.y = y;
+ };
+
+ proto.length = function(){ // = cc.kmVec2Length
+ return Math.sqrt(cc.math.square(this.x) + cc.math.square(this.y));
+ };
+
+ proto.lengthSq = function(){ // = cc.kmVec2LengthSq
+ return cc.math.square(this.x) + cc.math.square(this.y);
+ };
+
+ proto.normalize = function(){ // = cc.kmVec2Normalize
+ var l = 1.0 / this.length();
+ this.x *= l;
+ this.y *= l;
+ return this;
+ };
+
+ cc.math.Vec2.add = function (pOut, pV1, pV2) { // = cc.kmVec2Add
+ pOut.x = pV1.x + pV2.x;
+ pOut.y = pV1.y + pV2.y;
+ return pOut
+ };
+
+ proto.add = function(vec){ // = cc.kmVec2Add
+ this.x += vec.x;
+ this.y += vec.y;
+ return this;
+ };
+
+ proto.dot = function (vec) { //cc.kmVec2Dot
+ return this.x * vec.x + this.y * vec.y;
+ };
+
+ cc.math.Vec2.subtract = function (pOut, pV1, pV2) { // = cc.kmVec2Subtract
+ pOut.x = pV1.x - pV2.x;
+ pOut.y = pV1.y - pV2.y;
+ return pOut;
+ };
+
+ proto.subtract = function(vec){ // = cc.kmVec2Subtract
+ this.x -= vec.x;
+ this.y -= vec.y;
+ return this;
+ };
+
+ proto.transform = function (mat3) { // = cc.kmVec2Transform
+ var x = this.x, y = this.y;
+ this.x = x * mat3.mat[0] + y * mat3.mat[3] + mat3.mat[6];
+ this.y = x * mat3.mat[1] + y * mat3.mat[4] + mat3.mat[7];
+ return this;
+ };
+
+ cc.math.Vec2.scale = function (pOut, pIn, s) { // = cc.kmVec2Scale
+ pOut.x = pIn.x * s;
+ pOut.y = pIn.y * s;
+ return pOut;
+ };
+
+ proto.scale = function(s) { // = cc.kmVec2Scale
+ this.x *= s;
+ this.y *= s;
+ return this;
+ };
+
+ proto.equals = function (vec) { // = cc.kmVec2AreEqual
+ return (this.x < vec.x + cc.math.EPSILON && this.x > vec.x - cc.math.EPSILON) &&
+ (this.y < vec.y + cc.math.EPSILON && this.y > vec.y - cc.math.EPSILON);
+ };
+})(cc);
-cc.kmVec2Fill = function (pOut, x, y) {
- pOut.x = x;
- pOut.y = y;
- return pOut;
-};
-
-cc.kmVec2Length = function (pIn) {
- return Math.sqrt(cc.kmSQR(pIn.x) + cc.kmSQR(pIn.y));
-};
-
-cc.kmVec2LengthSq = function (pIn) {
- return cc.kmSQR(pIn.x) + cc.kmSQR(pIn.y);
-};
-
-cc.kmVec2Normalize = function (pOut, pIn) {
- var l = 1.0 / cc.kmVec2Length(pIn);
-
- var v = new cc.kmVec2();
- v.x = pIn.x * l;
- v.y = pIn.y * l;
-
- pOut.x = v.x;
- pOut.y = v.y;
-
- return pOut;
-};
-
-cc.kmVec2Add = function (pOut, pV1, pV2) {
- pOut.x = pV1.x + pV2.x;
- pOut.y = pV1.y + pV2.y;
-
- return pOut
-};
-
-cc.kmVec2Dot = function (pV1, pV2) {
- return pV1.x * pV2.x + pV1.y * pV2.y;
-};
-
-cc.kmVec2Subtract = function (pOut, pV1, pV2) {
- pOut.x = pV1.x - pV2.x;
- pOut.y = pV1.y - pV2.y;
-
- return pOut;
-};
-
-cc.kmVec2Transform = function (pOut, pV, pM) {
- var v= new cc.kmVec2();
-
- v.x = pV.x * pM.mat[0] + pV.y * pM.mat[3] + pM.mat[6];
- v.y = pV.x * pM.mat[1] + pV.y * pM.mat[4] + pM.mat[7];
-
- pOut.x = v.x;
- pOut.y = v.y;
-
- return pOut;
-};
-
-cc.kmVec2TransformCoord = function (pOut, pV, pM) {
- return null;
-};
-
-cc.kmVec2Scale = function (pOut, pIn, s) {
- pOut.x = pIn.x * s;
- pOut.y = pIn.y * s;
-
- return pOut;
-};
-
-cc.kmVec2AreEqual = function (p1, p2) {
- return (
- (p1.x < p2.x + cc.kmEpsilon && p1.x > p2.x - cc.kmEpsilon) &&
- (p1.y < p2.y + cc.kmEpsilon && p1.y > p2.y - cc.kmEpsilon)
- );
-};
diff --git a/cocos2d/kazmath/vec3.js b/cocos2d/kazmath/vec3.js
index c31de7c191..d9eafbee2f 100644
--- a/cocos2d/kazmath/vec3.js
+++ b/cocos2d/kazmath/vec3.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,180 +26,174 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.kmVec3 = function (x, y, z) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
-};
-
-cc.kmVec3Fill = function(pOut, x, y , z){
- if(!pOut)
- return new cc.kmVec3(x, y , z);
- pOut.x = x;
- pOut.y = y;
- pOut.z = z;
- return pOut;
-};
-
-cc.kmVec3Length = function(pIn){
- return Math.sqrt(cc.kmSQR(pIn.x) + cc.kmSQR(pIn.y) + cc.kmSQR(pIn.z));
-};
-
-cc.kmVec3LengthSq = function(pIn){
- return cc.kmSQR(pIn.x) + cc.kmSQR(pIn.y) + cc.kmSQR(pIn.z)
-} ;
-
-cc.kmVec3Normalize = function(pOut,pIn){
- var l = 1.0 / cc.kmVec3Length(pIn);
-
- pOut.x = pIn.x * l;
- pOut.y = pIn.y * l;
- pOut.z = pIn.z * l;
- return pOut;
-};
-
-cc.kmVec3Cross = function(pOut, pV1,pV2){
- pOut.x = (pV1.y * pV2.z) - (pV1.z * pV2.y);
- pOut.y = (pV1.z * pV2.x) - (pV1.x * pV2.z);
- pOut.z = (pV1.x * pV2.y) - (pV1.y * pV2.x);
- return pOut;
-};
-
-cc.kmVec3Dot = function(pV1, pV2){
- return ( pV1.x * pV2.x
- + pV1.y * pV2.y
- + pV1.z * pV2.z );
-} ;
-
-cc.kmVec3Add = function(pOut, pV1, pV2){
- pOut.x = pV1.x + pV2.x;
- pOut.y = pV1.y + pV2.y;
- pOut.z = pV1.z + pV2.z;
- return pOut;
-};
-
-cc.kmVec3Subtract = function(pOut, pV1, pV2){
- pOut.x = pV1.x - pV2.x;
- pOut.y = pV1.y - pV2.y;
- pOut.z = pV1.z - pV2.z;
- return pOut;
-};
-
-cc.kmVec3Transform = function(pOut, pV, pM){
- /*
- a = (Vx, Vy, Vz, 1)
- b = (a×M)T
- Out = (bx, by, bz)
+(function(cc) {
+ /**
+ * A 3d vector.
+ * @class
+ * @param {number} [x]
+ * @param {number} [y]
+ * @param {number} [z]
*/
- pOut.x = pV.x * pM.mat[0] + pV.y * pM.mat[4] + pV.z * pM.mat[8] + pM.mat[12];
- pOut.y = pV.x * pM.mat[1] + pV.y * pM.mat[5] + pV.z * pM.mat[9] + pM.mat[13];
- pOut.z = pV.x * pM.mat[2] + pV.y * pM.mat[6] + pV.z * pM.mat[10] + pM.mat[14];
- return pOut;
-};
-
-cc.kmVec3TransformNormal = function(pOut, pV, pM){
- /*
- a = (Vx, Vy, Vz, 0)
- b = (a×M)T
- Out = (bx, by, bz)
- */
- //Omits the translation, only scaling + rotating
- pOut.x = pV.x * pM.mat[0] + pV.y * pM.mat[4] + pV.z * pM.mat[8];
- pOut.y = pV.x * pM.mat[1] + pV.y * pM.mat[5] + pV.z * pM.mat[9];
- pOut.z = pV.x * pM.mat[2] + pV.y * pM.mat[6] + pV.z * pM.mat[10];
- return pOut;
-};
-
-cc.kmVec3TransformCoord = function(pOut,pV,pM){
- /*
- a = (Vx, Vy, Vz, 1)
- b = (a×M)T
- Out = 1â„bw(bx, by, bz)
- */
- var v = new cc.kmVec4();
- var inV = new cc.kmVec4();
- cc.kmVec4Fill(inV, pV.x, pV.y, pV.z, 1.0);
-
- cc.kmVec4Transform(v, inV,pM);
-
- pOut.x = v.x / v.w;
- pOut.y = v.y / v.w;
- pOut.z = v.z / v.w;
-
- return pOut;
-};
-
-cc.kmVec3Scale = function(pOut, pIn, s){
- pOut.x = pIn.x * s;
- pOut.y = pIn.y * s;
- pOut.z = pIn.z * s;
-
- return pOut;
-};
-
-cc.kmVec3AreEqual = function(p1, p2){
- if ((p1.x < (p2.x + cc.kmEpsilon) && p1.x > (p2.x - cc.kmEpsilon)) &&
- (p1.y < (p2.y + cc.kmEpsilon) && p1.y > (p2.y - cc.kmEpsilon)) &&
- (p1.z < (p2.z + cc.kmEpsilon) && p1.z > (p2.z - cc.kmEpsilon))) {
- return 1;
- }
-
- return 0;
-};
-
-cc.kmVec3InverseTransform = function(pOut, pVect,pM){
- var v1 = new cc.kmVec3(pVect.x - pM.mat[12], pVect.y - pM.mat[13],pVect.z - pM.mat[14]);
-
- pOut.x = v1.x * pM.mat[0] + v1.y * pM.mat[1] + v1.z * pM.mat[2];
- pOut.y = v1.x * pM.mat[4] + v1.y * pM.mat[5] + v1.z * pM.mat[6];
- pOut.z = v1.x * pM.mat[8] + v1.y * pM.mat[9] + v1.z * pM.mat[10];
-
- return pOut;
-};
-
-cc.kmVec3InverseTransformNormal = function(pOut, pVect, pM){
- pOut.x = pVect.x * pM.mat[0] + pVect.y * pM.mat[1] + pVect.z * pM.mat[2];
- pOut.y = pVect.x * pM.mat[4] + pVect.y * pM.mat[5] + pVect.z * pM.mat[6];
- pOut.z = pVect.x * pM.mat[8] + pVect.y * pM.mat[9] + pVect.z * pM.mat[10];
-
- return pOut;
-};
-
-cc.kmVec3Assign = function(pOut,pIn){
- if (pOut == pIn)
- return pOut;
-
- pOut.x = pIn.x;
- pOut.y = pIn.y;
- pOut.z = pIn.z;
- return pOut;
-};
-
-cc.kmVec3Zero = function(pOut){
- pOut.x = 0.0;
- pOut.y = 0.0;
- pOut.z = 0.0;
-
- return pOut;
-};
-
-cc.kmVec3ToTypeArray = function(vecValue){
- if(!vecValue)
- return null;
-
- var tyArr = new Float32Array(3);
- tyArr[0] = vecValue.x;
- tyArr[1] = vecValue.y;
- tyArr[2] = vecValue.z;
- return tyArr;
-};
-
-
-
-
-
-
-
-
-
+ cc.math.Vec3 = cc.kmVec3 = function (x, y, z) {
+ if(x && y === undefined){
+ this.x = x.x;
+ this.y = x.y;
+ this.z = x.z;
+ } else {
+ this.x = x || 0;
+ this.y = y || 0;
+ this.z = z || 0;
+ }
+ };
+
+ cc.math.vec3 = function(x, y, z){
+ return new cc.math.Vec3(x, y, z);
+ };
+
+ var _p = cc.math.Vec3.prototype;
+
+ _p.fill = function (x, y, z) { // =cc.kmVec3Fill
+ if (x && y === undefined) {
+ this.x = x.x;
+ this.y = x.y;
+ this.z = x.z;
+ } else {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+ return this;
+ };
+
+ _p.length = function () { //=cc.kmVec3Length
+ return Math.sqrt(cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z));
+ };
+
+ _p.lengthSq = function () { //=cc.kmVec3LengthSq
+ return cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z)
+ };
+
+ _p.normalize = function () { //= cc.kmVec3Normalize
+ var l = 1.0 / this.length();
+ this.x *= l;
+ this.y *= l;
+ this.z *= l;
+ return this;
+ };
+
+ _p.cross = function (vec3) { //= cc.kmVec3Cross
+ var x = this.x, y = this.y, z = this.z;
+ this.x = (y * vec3.z) - (z * vec3.y);
+ this.y = (z * vec3.x) - (x * vec3.z);
+ this.z = (x * vec3.y) - (y * vec3.x);
+ return this;
+ };
+
+ _p.dot = function (vec) { //= cc.kmVec3Dot
+ return ( this.x * vec.x + this.y * vec.y + this.z * vec.z );
+ };
+
+ _p.add = function(vec){ //= cc.kmVec3Add
+ this.x += vec.x;
+ this.y += vec.y;
+ this.z += vec.z;
+ return this;
+ };
+
+ _p.subtract = function (vec) { // = cc.kmVec3Subtract
+ this.x -= vec.x;
+ this.y -= vec.y;
+ this.z -= vec.z;
+ return this;
+ };
+
+ _p.transform = function (mat4) { // = cc.kmVec3Transform
+ var x = this.x, y = this.y, z = this.z, mat = mat4.mat;
+ this.x = x * mat[0] + y * mat[4] + z * mat[8] + mat[12];
+ this.y = x * mat[1] + y * mat[5] + z * mat[9] + mat[13];
+ this.z = x * mat[2] + y * mat[6] + z * mat[10] + mat[14];
+ return this;
+ };
+
+ _p.transformNormal = function(mat4){
+ /*
+ a = (Vx, Vy, Vz, 0)
+ b = (a×M)T
+ Out = (bx, by, bz)
+ */
+ //Omits the translation, only scaling + rotating
+ var x = this.x, y = this.y, z = this.z, mat = mat4.mat;
+ this.x = x * mat[0] + y * mat[4] + z * mat[8];
+ this.y = x * mat[1] + y * mat[5] + z * mat[9];
+ this.z = x * mat[2] + y * mat[6] + z * mat[10];
+ return this;
+ };
+
+ _p.transformCoord = function(mat4){ // = cc.kmVec3TransformCoord
+ /*
+ a = (Vx, Vy, Vz, 1)
+ b = (a×M)T
+ Out = 1â„bw(bx, by, bz)
+ */
+ var v = new cc.math.Vec4(this.x, this.y, this.z, 1.0);
+ v.transform(mat4);
+ this.x = v.x / v.w;
+ this.y = v.y / v.w;
+ this.z = v.z / v.w;
+ return this;
+ };
+
+ _p.scale = function(scale){ // = cc.kmVec3Scale
+ this.x *= scale;
+ this.y *= scale;
+ this.z *= scale;
+ return this;
+ };
+
+ _p.equals = function(vec){ // = cc.kmVec3AreEqual
+ var EPSILON = cc.math.EPSILON;
+ return (this.x < (vec.x + EPSILON) && this.x > (vec.x - EPSILON)) &&
+ (this.y < (vec.y + EPSILON) && this.y > (vec.y - EPSILON)) &&
+ (this.z < (vec.z + EPSILON) && this.z > (vec.z - EPSILON));
+ };
+
+ _p.inverseTransform = function(mat4){ //= cc.kmVec3InverseTransform
+ var mat = mat4.mat;
+ var v1 = new cc.math.Vec3(this.x - mat[12], this.y - mat[13], this.z - mat[14]);
+ this.x = v1.x * mat[0] + v1.y * mat[1] + v1.z * mat[2];
+ this.y = v1.x * mat[4] + v1.y * mat[5] + v1.z * mat[6];
+ this.z = v1.x * mat[8] + v1.y * mat[9] + v1.z * mat[10];
+ return this;
+ };
+
+ _p.inverseTransformNormal = function(mat4){ // = cc.kmVec3InverseTransformNormal
+ var x = this.x, y = this.y, z = this.z, mat = mat4.mat;
+ this.x = x * mat[0] + y * mat[1] + z * mat[2];
+ this.y = x * mat[4] + y * mat[5] + z * mat[6];
+ this.z = x * mat[8] + y * mat[9] + z * mat[10];
+ return this;
+ };
+
+ _p.assignFrom = function(vec){
+ if(!vec)
+ return this;
+ this.x = vec.x;
+ this.y = vec.y;
+ this.z = vec.z;
+ return this;
+ };
+
+ cc.math.Vec3.zero = function(vec){ // = cc.kmVec3Zero
+ vec.x = vec.y = vec.z = 0.0;
+ return vec;
+ };
+
+ _p.toTypeArray = function(){ //cc.kmVec3ToTypeArray
+ var tyArr = new Float32Array(3);
+ tyArr[0] = this.x;
+ tyArr[1] = this.y;
+ tyArr[2] = this.z;
+ return tyArr;
+ };
+})(cc);
diff --git a/cocos2d/kazmath/GL/mat4stack.js b/cocos2d/kazmath/vec3SIMD.js
similarity index 55%
rename from cocos2d/kazmath/GL/mat4stack.js
rename to cocos2d/kazmath/vec3SIMD.js
index dc9aa0a76f..0bf4ff4b87 100644
--- a/cocos2d/kazmath/GL/mat4stack.js
+++ b/cocos2d/kazmath/vec3SIMD.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,35 +26,26 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.km_mat4_stack = function(capacity, item_count, top, stack){
- this.top = top ;
- this.stack = stack ;
-};
-
-cc.km_mat4_stack.INITIAL_SIZE = 30;
-
-cc.km_mat4_stack_initialize = function(stack){
- stack.stack = []; //allocate the memory
- stack.top = null; //Set the top to NULL
-};
-
-cc.km_mat4_stack_push = function(stack, item){
- stack.stack.push(stack.top);
- stack.top = new cc.kmMat4();
- cc.kmMat4Assign(stack.top, item);
-};
-
-cc.km_mat4_stack_pop = function(stack, pOut){
- //cc.Assert(stack.item_count , "Cannot pop an empty stack");
- stack.top = stack.stack.pop();
-};
-
-cc.km_mat4_stack_release = function(stack){
- stack.stack = null;
- stack.top = null;
- stack = null;
-};
-
-
-
-
+ (function(cc) {
+ var proto = cc.math.Vec3.prototype;
+
+ proto.transformCoordSIMD = function(mat4){
+ var vec = SIMD.float32x4(this.x, this.y, this.z, 0.0);
+ var mat0 = SIMD.float32x4.load(mat4.mat, 0);
+ var mat1 = SIMD.float32x4.load(mat4.mat, 4);
+ var mat2 = SIMD.float32x4.load(mat4.mat, 8);
+ var mat3 = SIMD.float32x4.load(mat4.mat, 12);
+
+ //cc.kmVec4Transform(v, inV,pM);
+ var out = SIMD.float32x4.add(
+ SIMD.float32x4.add(SIMD.float32x4.mul(mat0, SIMD.float32x4.swizzle(vec, 0, 0, 0, 0)),
+ SIMD.float32x4.mul(mat1, SIMD.float32x4.swizzle(vec, 1, 1, 1, 1))),
+ SIMD.float32x4.add(SIMD.float32x4.mul(mat2, SIMD.float32x4.swizzle(vec, 2, 2, 2, 2)),
+ mat3));
+
+ out = SIMD.float32x4.div(out, SIMD.float32x4.swizzle(out, 3, 3, 3, 3));
+ this.fill(out);
+
+ return this;
+ };
+})(cc);
diff --git a/cocos2d/kazmath/vec4.js b/cocos2d/kazmath/vec4.js
index 56dfea83bb..fb2e376380 100644
--- a/cocos2d/kazmath/vec4.js
+++ b/cocos2d/kazmath/vec4.js
@@ -1,5 +1,7 @@
/**
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008, Luke Benstead.
All rights reserved.
@@ -24,130 +26,133 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-cc.kmVec4 = function (x, y, z, w) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- this.w = w || 0;
-};
-
-
-cc.kmVec4Fill = function(outVec, x, y ,z, w){
- outVec.x = x;
- outVec.y = y;
- outVec.z = z;
- outVec.w = w;
- return outVec;
-};
-
-cc.kmVec4Add = function(outVec, pV1, pV2){
- outVec.x = pV1.x + pV2.x;
- outVec.y = pV1.y + pV2.y;
- outVec.z = pV1.z + pV2.z;
- outVec.w = pV1.w + pV2.w;
-
- return outVec;
-};
-
-cc.kmVec4Dot = function( vec1, vec2){
- return ( vec1.x * vec2.x
- + vec1.y * vec2.y
- + vec1.z * vec2.z
- + vec1.w * vec2.w );
-};
-
-cc.kmVec4Length = function(inVec){
- return Math.sqrt(cc.kmSQR(inVec.x) + cc.kmSQR(inVec.y) + cc.kmSQR(inVec.z) + cc.kmSQR(inVec.w));
-};
-
-cc.kmVec4LengthSq = function(inVec){
- return cc.kmSQR(inVec.x) + cc.kmSQR(inVec.y) + cc.kmSQR(inVec.z) + cc.kmSQR(inVec.w);
-};
-
-cc.kmVec4Lerp = function(outVec, pV1, pV2, t){
- return outVec;
-};
-
-cc.kmVec4Normalize = function(outVec, inVec){
- var l = 1.0 / cc.kmVec4Length(inVec);
-
- outVec.x *= l;
- outVec.y *= l;
- outVec.z *= l;
- outVec.w *= l;
-
- return outVec;
-};
-
-cc.kmVec4Scale = function(outVec, inVec, scale){
- cc.kmVec4Normalize(outVec, inVec);
-
- outVec.x *= scale;
- outVec.y *= scale;
- outVec.z *= scale;
- outVec.w *= scale;
- return outVec;
-};
-
-cc.kmVec4Subtract = function(outVec,vec1, vec2){
- outVec.x = vec1.x - vec2.x;
- outVec.y = vec1.y - vec2.y;
- outVec.z = vec1.z - vec2.z;
- outVec.w = vec1.w - vec2.w;
-
- return outVec;
-};
-
-cc.kmVec4Transform = function(outVec, vec,mat4Obj){
- outVec.x = vec.x * mat4Obj.mat[0] + vec.y * mat4Obj.mat[4] + vec.z * mat4Obj.mat[8] + vec.w * mat4Obj.mat[12];
- outVec.y = vec.x * mat4Obj.mat[1] + vec.y * mat4Obj.mat[5] + vec.z * mat4Obj.mat[9] + vec.w * mat4Obj.mat[13];
- outVec.z = vec.x * mat4Obj.mat[2] + vec.y * mat4Obj.mat[6] + vec.z * mat4Obj.mat[10] + vec.w * mat4Obj.mat[14];
- outVec.w = vec.x * mat4Obj.mat[3] + vec.y * mat4Obj.mat[7] + vec.z * mat4Obj.mat[11] + vec.w * mat4Obj.mat[15];
- return outVec;
-};
-
-cc.kmVec4TransformArray = function(outVec,outStride,vecObj,stride,mat4Obj,count){
- var i = 0;
- //Go through all of the vectors
- while (i < count) {
- var currIn = vecObj + (i * stride); //Get a pointer to the current input
- var out = outVec + (i * outStride); //and the current output
- cc.kmVec4Transform(out, currIn, mat4Obj); //Perform transform on it
- ++i;
- }
-
- return outVec;
-};
-
-cc.kmVec4AreEqual = function(vec1,vec2){
- return (
- (vec1.x < vec2.x + cc.kmEpsilon && vec1.x > vec2.x - cc.kmEpsilon) &&
- (vec1.y < vec2.y + cc.kmEpsilon && vec1.y > vec2.y - cc.kmEpsilon) &&
- (vec1.z < vec2.z + cc.kmEpsilon && vec1.z > vec2.z - cc.kmEpsilon) &&
- (vec1.w < vec2.w + cc.kmEpsilon && vec1.w > vec2.w - cc.kmEpsilon)
- );
-};
-
-cc.kmVec4Assign = function(destVec, srcVec){
- cc.Assert(destVec != srcVec, "same object!");
-
- destVec.x = srcVec.x;
- destVec.y = srcVec.y;
- destVec.z = srcVec.z;
- destVec.w = srcVec.w;
-
- return destVec;
-};
-
-cc.kmVec4ToTypeArray = function(vecValue){
- if(!vecValue)
- return null;
-
- var tyArr = new Float32Array(4);
- tyArr[0] = vecValue.x;
- tyArr[1] = vecValue.y;
- tyArr[2] = vecValue.z;
- tyArr[3] = vecValue.w;
- return tyArr;
-};
+(function(cc) {
+ cc.math.Vec4 = function (x, y, z, w) {
+ if (x && y === undefined) {
+ this.x = x.x;
+ this.y = x.y;
+ this.z = x.z;
+ this.w = x.w;
+ } else {
+ this.x = x || 0;
+ this.y = y || 0;
+ this.z = z || 0;
+ this.w = w || 0;
+ }
+ };
+ cc.kmVec4 = cc.math.Vec4;
+ var proto = cc.math.Vec4.prototype;
+
+ proto.fill = function (x, y, z, w) { //=cc.kmVec4Fill
+ if (x && y === undefined) {
+ this.x = x.x;
+ this.y = x.y;
+ this.z = x.z;
+ this.w = x.w;
+ } else {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+ };
+
+ proto.add = function(vec) { //cc.kmVec4Add
+ if(!vec)
+ return this;
+ this.x += vec.x;
+ this.y += vec.y;
+ this.z += vec.z;
+ this.w += vec.w;
+ return this;
+ };
+
+ proto.dot = function(vec){ //cc.kmVec4Dot
+ return ( this.x * vec.x + this.y * vec.y + this.z * vec.z + this.w * vec.w );
+ };
+
+ proto.length = function(){ //=cc.kmVec4Length
+ return Math.sqrt(cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z) + cc.math.square(this.w));
+ };
+
+ proto.lengthSq = function(){ //=cc.kmVec4LengthSq
+ return cc.math.square(this.x) + cc.math.square(this.y) + cc.math.square(this.z) + cc.math.square(this.w);
+ };
+
+ proto.lerp = function(vec, t){ //= cc.kmVec4Lerp
+ //not implemented
+ return this;
+ };
+
+ proto.normalize = function() { // cc.kmVec4Normalize
+ var l = 1.0 / this.length();
+ this.x *= l;
+ this.y *= l;
+ this.z *= l;
+ this.w *= l;
+ return this;
+ };
+
+ proto.scale = function(scale){ //= cc.kmVec4Scale
+ /// Scales a vector to the required length. This performs a Normalize before multiplying by S.
+ this.normalize();
+ this.x *= scale;
+ this.y *= scale;
+ this.z *= scale;
+ this.w *= scale;
+ return this;
+ };
+
+ proto.subtract = function(vec) {
+ this.x -= vec.x;
+ this.y -= vec.y;
+ this.z -= vec.z;
+ this.w -= vec.w;
+ };
+
+ proto.transform = function(mat4) {
+ var x = this.x, y = this.y, z = this.z, w = this.w, mat = mat4.mat;
+ this.x = x * mat[0] + y * mat[4] + z * mat[8] + w * mat[12];
+ this.y = x * mat[1] + y * mat[5] + z * mat[9] + w * mat[13];
+ this.z = x * mat[2] + y * mat[6] + z * mat[10] + w * mat[14];
+ this.w = x * mat[3] + y * mat[7] + z * mat[11] + w * mat[15];
+ return this;
+ };
+
+ cc.math.Vec4.transformArray = function(vecArray, mat4){
+ var retArray = [];
+ for (var i = 0; i < vecArray.length; i++) {
+ var selVec = new cc.math.Vec4(vecArray[i]);
+ selVec.transform(mat4);
+ retArray.push(selVec);
+ }
+ return retArray;
+ };
+
+ proto.equals = function(vec){ //=cc.kmVec4AreEqual
+ var EPSILON = cc.math.EPSILON;
+ return (this.x < vec.x + EPSILON && this.x > vec.x - EPSILON) &&
+ (this.y < vec.y + EPSILON && this.y > vec.y - EPSILON) &&
+ (this.z < vec.z + EPSILON && this.z > vec.z - EPSILON) &&
+ (this.w < vec.w + EPSILON && this.w > vec.w - EPSILON);
+ };
+
+ proto.assignFrom = function(vec) { //= cc.kmVec4Assign
+ this.x = vec.x;
+ this.y = vec.y;
+ this.z = vec.z;
+ this.w = vec.w;
+ return this;
+ };
+
+ proto.toTypeArray = function(){ //cc.kmVec4ToTypeArray
+ var tyArr = new Float32Array(4);
+ tyArr[0] = this.x;
+ tyArr[1] = this.y;
+ tyArr[2] = this.z;
+ tyArr[3] = this.w;
+ return tyArr;
+ };
+})(cc);
+
diff --git a/cocos2d/keyboard_dispatcher/CCKeyboardDelegate.js b/cocos2d/keyboard_dispatcher/CCKeyboardDelegate.js
deleted file mode 100644
index 3695a9f36d..0000000000
--- a/cocos2d/keyboard_dispatcher/CCKeyboardDelegate.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-/**
- * you must extend the keyboardDelegate and
- * implement your own game logic in
- * keydown and keyup functions
- * @class
- * @extends cc.Class
- */
-cc.KeyboardDelegate = cc.Class.extend(/** @lends cc.KeyboardDelegate# */{
- /**
- * Call back when a key is pressed down
- * @param {Integer} keyCode
- * @example
- * // example
- * if(keyCode == cc.KEY.w){}
- */
- onKeyDown:function (keyCode) {
- },
-
- /**
- * Call back when a key is released
- * @param {Integer} keyCode
- * @example
- * // example
- * if(keyCode == cc.KEY.w){}
- */
- onKeyUp:function (keyCode) {
- }
-});
-
-/**
- * KeyboardHandler is an object that contains KeyboardDelegate
- * @class
- * @extends cc.Class
- */
-cc.KeyboardHandler = cc.Class.extend(/** @lends cc.KeyboardHandler# */{
- /**
- * returns the keyboard delegate
- * @return {cc.KeyboardDelegate}
- */
- getDelegate:function () {
- return this._delegate;
- },
-
- /**
- * set the keyboard delegate
- * @param {cc.KeyboardDelegate} delegate
- */
- setDelegate:function (delegate) {
- this._delegate = delegate;
- },
- /**
- * initializes a cc.KeyboardHandler with a delegate
- * @param {cc.KeyboardDelegate} delegate
- * @return {Boolean}
- */
- initWithDelegate:function (delegate) {
- cc.Assert(delegate != null, "It's a wrong delegate!");
-
- this._delegate = delegate;
-
- return true;
- },
- _delegate:null
-});
-/**
- * Create a KeyboardHandler with KeyboardDelegate
- * @param delegate
- * @return {cc.KeyboardHandler}
- */
-cc.KeyboardHandler.create = function (delegate) {
- var handler = new cc.KeyboardHandler();
- handler.initWithDelegate(delegate);
- return handler;
-};
diff --git a/cocos2d/keyboard_dispatcher/CCKeyboardDispatcher.js b/cocos2d/keyboard_dispatcher/CCKeyboardDispatcher.js
deleted file mode 100644
index 4dc21ee233..0000000000
--- a/cocos2d/keyboard_dispatcher/CCKeyboardDispatcher.js
+++ /dev/null
@@ -1,318 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * android back button
- * @deprecated These were for android devices, but does not work in html5 environment
- * @constant
- * @type Number
- */
-cc.TYPE_BACK_CLICKED = 1;
-/**
- * android menu button
- * @deprecated for android devices, does not work in html5 environment
- * @constant
- * @type Number
- */
-cc.TYPE_MENU_CLICKED = 2;
-/**
- * keymap
- * @example
- * //Example
- * //to mark a keydown
- * cc.keyDown[65] = true;
- * //or
- * cc.keyMap[cc.KEY.a]
- *
- * //to mark a keyup
- * do cc.keyDown[65] = false;
- *
- * //to find out if a key is down, check
- * if(cc.keyDown[65])
- * //or
- * if,(cc.keyDown[cc.KEY.space])
- * //if its undefined or false or null, its not pressed
- * @constant
- * @type object
- */
-cc.KEY = {
- backspace:8,
- tab:9,
- enter:13,
- shift:16, //should use shiftkey instead
- ctrl:17, //should use ctrlkey
- alt:18, //should use altkey
- pause:19,
- capslock:20,
- escape:27,
- pageup:33,
- pagedown:34,
- end:35,
- home:36,
- left:37,
- up:38,
- right:39,
- down:40,
- insert:45,
- Delete:46,
- 0:48,
- 1:49,
- 2:50,
- 3:51,
- 4:52,
- 5:53,
- 6:54,
- 7:55,
- 8:56,
- 9:57,
- a:65,
- b:66,
- c:67,
- d:68,
- e:69,
- f:70,
- g:71,
- h:72,
- i:73,
- j:74,
- k:75,
- l:76,
- m:77,
- n:78,
- o:79,
- p:80,
- q:81,
- r:82,
- s:83,
- t:84,
- u:85,
- v:86,
- w:87,
- x:88,
- y:89,
- z:90,
- num0:96,
- num1:97,
- num2:98,
- num3:99,
- num4:100,
- num5:101,
- num6:102,
- num7:103,
- num8:104,
- num9:105,
- '*':106,
- '+':107,
- '-':109,
- 'numdel':110,
- '/':111,
- f1:112, //f1-f12 dont work on ie
- f2:113,
- f3:114,
- f4:115,
- f5:116,
- f6:117,
- f7:118,
- f8:119,
- f9:120,
- f10:121,
- f11:122,
- f12:123,
- numlock:144,
- scrolllock:145,
- semicolon:186,
- ',':186,
- equal:187,
- '=':187,
- ';':188,
- comma:188,
- dash:189,
- '.':190,
- period:190,
- forwardslash:191,
- grave:192,
- '[':219,
- openbracket:219,
- ']':221,
- closebracket:221,
- backslash:220,
- quote:222,
- space:32
-};
-
-/**
- * Dispatch the keyboard message
- * @class
- * @extends cc.Class
- */
-cc.KeyboardDispatcher = cc.Class.extend(/** @lends cc.KeyboardDispatcher# */{
- /**
- * add delegate to concern keyboard msg
- * @param {cc.KeyboardDelegate} delegate keyboard delegate object
- */
- addDelegate:function (delegate) {
- if (!delegate) {
- return;
- }
- if (!this._locked) {
- this.forceAddDelegate(delegate);
- }
- else {
- this._handlersToAdd.push(delegate);
- this._toAdd = true;
- }
- },
-
- /**
- * remove the delegate from the delegates who concern keyboard msg
- * @param {cc.KeyboardDelegate} delegate
- */
- removeDelegate:function (delegate) {
- if (!delegate) {
- return;
- }
- if (!this._locked) {
- this.forceRemoveDelegate(delegate);
- }
- else {
- this._handlersToRemove.push(delegate);
- this._toRemove = true;
- }
- },
-
- /**
- * force add the delegate
- * @param {cc.KeyboardDelegate} delegate
- */
- forceAddDelegate:function (delegate) {
- var handler = cc.KeyboardHandler.create(delegate);
- if (handler) {
- //if handler already exist
- for (var i = 0; i < this._delegates; i++) {
- if (this._delegates[i].getDelegate() == handler.getDelegate()) {
- }
- }
- this._delegates.push(handler);
- }
- },
-
- /**
- * force remove the delegate
- * @param {cc.KeyboardDelegate} delegate
- */
- forceRemoveDelegate:function (delegate) {
- for (var i = 0; i < this._delegates.length; i++) {
- if (this._delegates[i].getDelegate() == delegate) {
- this._delegates.splice(i, 1);
- return;
- }
- }
- },
-
- /**
- * dispatch the keyboard message to the delegates
- * @param {event} e
- * @param {Boolean} keydown whether this is a keydown or keyup
- * @return {Boolean}
- */
- dispatchKeyboardMSG:function (e, keydown) {
- this._locked = true;
- e.stopPropagation();
- e.preventDefault();
-
- var i = 0;
- //update keymap
- if (keydown && e) { //if keydown and our keymap doesnt have it
- //execute all deletegate that registered a keyboard event
- for (i = 0; i < this._delegates.length; i++) {
- if(this._delegates[i].getDelegate() && this._delegates[i].getDelegate().onKeyDown)
- this._delegates[i].getDelegate().onKeyDown(e.keyCode);
- }
- } else if (!keydown && e) {//if keyup and our keymap have that key in it
- for (i = 0; i < this._delegates.length; i++) {
- if(this._delegates[i].getDelegate() && this._delegates[i].getDelegate().onKeyUp)
- this._delegates[i].getDelegate().onKeyUp(e.keyCode);
- }
- }
- this._locked = false;
- if (this._toRemove) {
- this._toRemove = false;
- for (i = 0; i < this._handlersToRemove.length; ++i) {
- this.forceRemoveDelegate(this._handlersToRemove[i]);
- }
- delete this._handlersToRemove;
- this._handlersToRemove = [];
- }
-
- if (this._toAdd) {
- this._toAdd = false;
- for (i = 0; i < this._handlersToAdd.length; ++i) {
- this.forceAddDelegate(this._handlersToAdd[i]);
- }
- this._handlersToAdd = [];
- }
- return true;
- },
-
- //private
- _delegates:[],
- _locked:false,
- _toAdd:false,
- _toRemove:false,
- _handlersToAdd:[],
- _handlersToRemove:[]
-});
-
-/**
- * Returns the shared cc.KeyboardDispatcher object for the system.
- * @return {cc.keyboardDispatcher}
- */
-cc.KeyboardDispatcher.getInstance = function () {
- if (!cc.keyboardDispatcher) {
- cc.keyboardDispatcher = new cc.KeyboardDispatcher();
- //make canvas focusable
- cc.canvas.setAttribute('tabindex', 1);
- cc.canvas.style.outline = 'none';
- cc.canvas.style.cursor = 'default';
- cc.canvas.addEventListener("keydown", function (e) {
- cc.keyboardDispatcher.dispatchKeyboardMSG(e, true);
- });
- cc.canvas.addEventListener("keyup", function (e) {
- cc.keyboardDispatcher.dispatchKeyboardMSG(e, false);
- });
- }
- return cc.keyboardDispatcher;
-};
-
-/**
- * Release the shared cc.KeyboardDispatcher object from the system.
- */
-cc.KeyboardDispatcher.purgeSharedDispatcher = function () {
- if (cc.keyboardDispatcher) {
- delete cc.keyboardDispatcher;
- cc.keyboardDispatcher = null;
- }
-};
diff --git a/cocos2d/label_nodes/CCLabelAtlas.js b/cocos2d/label_nodes/CCLabelAtlas.js
deleted file mode 100644
index 66479026ca..0000000000
--- a/cocos2d/label_nodes/CCLabelAtlas.js
+++ /dev/null
@@ -1,329 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * using image file to print text label on the screen, might be a bit slower than cc.Label, similar to cc.LabelBMFont
- * @class
- * @extends cc.AtlasNode
- */
-cc.LabelAtlas = cc.AtlasNode.extend(/** @lends cc.LabelAtlas# */{
- // string to render
- _string:null,
- // the first char in the charmap
- _mapStartChar:null,
-
- /**
- *
- * initializes the cc.LabelAtlas with a string, a char map file(the atlas),
- * the width and height of each element and the starting char of the atlas
- * It accepts two groups of parameters:
- * a) string, fntFile
- * b) label, textureFilename, width, height, startChar
- *
- * @param {String} strText
- * @param {String|cc.Texture2D} charMapFile charMapFile or fntFile or texture file
- * @param {Number} [itemWidth=0]
- * @param {Number} [itemHeight=0]
- * @param {Number} [startCharMap=""]
- * @return {Boolean} returns true on success
- */
- initWithString:function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
- var label = strText + "", textureFilename, width, height, startChar;
- cc.Assert(label !== null, "Label must be non-nil");
- if (arguments.length === 2) {
- var fileUtils = cc.FileUtils.getInstance();
- var pathStr = fileUtils.fullPathForFilename(charMapFile);
- var relPathStr = pathStr.substr(0, pathStr.lastIndexOf('/')) + '/';
-
- var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(pathStr);
- cc.Assert(parseInt(dict["version"], 10) == 1, "Unsupported version. Upgrade cocos2d version");
-
- textureFilename = relPathStr + dict["textureFilename"];
- var locScaleFactor = cc.CONTENT_SCALE_FACTOR();
- width = parseInt(dict["itemWidth"], 10) / locScaleFactor;
- height = parseInt(dict["itemHeight"], 10) / locScaleFactor;
- startChar = String.fromCharCode(parseInt(dict["firstChar"], 10));
- } else {
- textureFilename = charMapFile;
- width = itemWidth || 0;
- height = itemHeight || 0;
- startChar = startCharMap || " ";
- }
-
- var texture = null;
- if(textureFilename instanceof cc.Texture2D)
- texture = textureFilename;
- else
- texture = cc.TextureCache.getInstance().addImage(textureFilename);
-
- if (this.initWithTexture(texture, width, height, label.length)) {
- this._mapStartChar = startChar;
- this.setString(label);
- return true;
- }
- return false;
- },
-
- /**
- * @param {cc.Color3B} color3
- */
- setColor:function (color3) {
- cc.AtlasNode.prototype.setColor.call(this, color3);
- this.updateAtlasValues();
- },
- /**
- * return the text of this label
- * @return {String}
- */
- getString:function () {
- return this._string;
- },
-
- /**
- * draw the label
- */
- draw:function (ctx) {
- cc.AtlasNode.prototype.draw.call(this,ctx);
- if (cc.LABELATLAS_DEBUG_DRAW) {
- var s = this.getContentSize();
- var vertices = [cc.p(0, 0), cc.p(s.width, 0),
- cc.p(s.width, s.height), cc.p(0, s.height)];
- cc.drawingUtil.drawPoly(vertices, 4, true);
- }
- },
-
- /**
- * Atlas generation
- */
- updateAtlasValues: null,
-
- _updateAtlasValuesForCanvas: function () {
- var locString = this._string;
- var n = locString.length;
- var texture = this.getTexture();
- var locItemWidth = this._itemWidth, locItemHeight = this._itemHeight;
- var locScaleFactor = cc.CONTENT_SCALE_FACTOR();
- for (var i = 0; i < n; i++) {
- var a = locString.charCodeAt(i) - this._mapStartChar.charCodeAt(0);
- var row = parseInt(a % this._itemsPerRow, 10) * locScaleFactor;
- var col = parseInt(a / this._itemsPerRow, 10) * locScaleFactor;
-
- var rect = cc.rect(row * locItemWidth, col * locItemHeight, locItemWidth, locItemHeight);
- var c = locString.charCodeAt(i);
- var fontChar = this.getChildByTag(i);
- if (!fontChar) {
- fontChar = new cc.Sprite();
- if (c == 32) {
- fontChar.init();
- fontChar.setTextureRect(cc.rect(0, 0, 10, 10), false, cc.SizeZero());
- } else
- fontChar.initWithTexture(texture, rect);
-
- this.addChild(fontChar, 0, i);
- } else {
- if (c == 32) {
- fontChar.init();
- fontChar.setTextureRect(cc.rect(0, 0, 10, 10), false, cc.SizeZero());
- } else {
- // reusing fonts
- fontChar.initWithTexture(texture, rect);
- // restore to default in case they were modified
- fontChar.setVisible(true);
- fontChar.setOpacity(this._displayedOpacity);
- }
- }
- fontChar.setPosition(i * locItemWidth + locItemWidth / 2, locItemHeight / 2);
- }
- },
-
- _updateAtlasValuesForWebGL: function () {
- var locString = this._string;
- var n = locString.length;
- var locTextureAtlas = this._textureAtlas;
-
- var texture = locTextureAtlas.getTexture();
- var textureWide = texture.getPixelsWide();
- var textureHigh = texture.getPixelsHigh();
- var itemWidthInPixels = this._itemWidth;
- var itemHeightInPixels = this._itemHeight;
- if (!this._ignoreContentScaleFactor) {
- itemWidthInPixels = this._itemWidth * cc.CONTENT_SCALE_FACTOR();
- itemHeightInPixels = this._itemHeight * cc.CONTENT_SCALE_FACTOR();
- }
- cc.Assert(n <= locTextureAtlas.getCapacity(), "updateAtlasValues: Invalid String length");
- var quads = locTextureAtlas.getQuads();
- var locDisplayedColor = this._displayedColor;
- var curColor = {r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: this._displayedOpacity};
- var locItemWidth = this._itemWidth;
- for (var i = 0; i < n; i++) {
- var a = locString.charCodeAt(i) - this._mapStartChar.charCodeAt(0);
- var row = a % this._itemsPerRow;
- var col = 0 | (a / this._itemsPerRow);
-
- var left, right, top, bottom;
- if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
- // Issue #938. Don't use texStepX & texStepY
- left = (2 * row * itemWidthInPixels + 1) / (2 * textureWide);
- right = left + (itemWidthInPixels * 2 - 2) / (2 * textureWide);
- top = (2 * col * itemHeightInPixels + 1) / (2 * textureHigh);
- bottom = top + (itemHeightInPixels * 2 - 2) / (2 * textureHigh);
- } else {
- left = row * itemWidthInPixels / textureWide;
- right = left + itemWidthInPixels / textureWide;
- top = col * itemHeightInPixels / textureHigh;
- bottom = top + itemHeightInPixels / textureHigh;
- }
- var quad = quads[i];
- var locQuadTL = quad.tl, locQuadTR = quad.tr, locQuadBL = quad.bl, locQuadBR = quad.br;
- locQuadTL.texCoords.u = left;
- locQuadTL.texCoords.v = top;
- locQuadTR.texCoords.u = right;
- locQuadTR.texCoords.v = top;
- locQuadBL.texCoords.u = left;
- locQuadBL.texCoords.v = bottom;
- locQuadBR.texCoords.u = right;
- locQuadBR.texCoords.v = bottom;
-
- locQuadBL.vertices.x = (i * locItemWidth);
- locQuadBL.vertices.y = 0;
- locQuadBL.vertices.z = 0.0;
- locQuadBR.vertices.x = (i * locItemWidth + locItemWidth);
- locQuadBR.vertices.y = 0;
- locQuadBR.vertices.z = 0.0;
- locQuadTL.vertices.x = i * locItemWidth;
- locQuadTL.vertices.y = this._itemHeight;
- locQuadTL.vertices.z = 0.0;
- locQuadTR.vertices.x = i * locItemWidth + locItemWidth;
- locQuadTR.vertices.y = this._itemHeight;
- locQuadTR.vertices.z = 0.0;
- locQuadTL.colors = curColor;
- locQuadTR.colors = curColor;
- locQuadBL.colors = curColor;
- locQuadBR.colors = curColor;
- }
- if (n > 0) {
- locTextureAtlas.setDirty(true);
- var totalQuads = locTextureAtlas.getTotalQuads();
- if (n > totalQuads)
- locTextureAtlas.increaseTotalQuadsWith(n - totalQuads);
- }
- },
-
- /**
- * set the display string
- * @param {String} label
- */
- setString: null,
-
- _setStringForCanvas: function (label) {
- label = String(label);
- var len = label.length;
- this._string = label;
- this.setContentSize(cc.size(len * this._itemWidth, this._itemHeight));
- if (this._children) {
- var locChildren = this._children;
- len = locChildren.length;
- for (var i = 0; i < len; i++) {
- var node = locChildren[i];
- if (node)
- node.setVisible(false);
- }
- }
-
- this.updateAtlasValues();
- this._quadsToDraw = len;
- },
-
- _setStringForWebGL: function (label) {
- label = String(label);
- var len = label.length;
- if (len > this._textureAtlas.getTotalQuads())
- this._textureAtlas.resizeCapacity(len);
-
- this._string = label;
- this.setContentSize(cc.size(len * this._itemWidth, this._itemHeight));
-
- this.updateAtlasValues();
- this._quadsToDraw = len;
- },
-
- setOpacity: null,
-
- _setOpacityForCanvas: function (opacity) {
- if (this._displayedOpacity !== opacity) {
- cc.AtlasNode.prototype.setOpacity.call(this, opacity);
- var locChildren = this._children;
- for (var i = 0, len = locChildren.length; i < len; i++) {
- if (locChildren[i])
- locChildren[i].setOpacity(opacity);
- }
- }
- },
-
- _setOpacityForWebGL: function (opacity) {
- if (this._opacity !== opacity)
- cc.AtlasNode.prototype.setOpacity.call(this, opacity);
- }
-});
-
-if(cc.Browser.supportWebGL){
- cc.LabelAtlas.prototype.updateAtlasValues = cc.LabelAtlas.prototype._updateAtlasValuesForWebGL;
- cc.LabelAtlas.prototype.setString = cc.LabelAtlas.prototype._setStringForWebGL;
- cc.LabelAtlas.prototype.setOpacity = cc.LabelAtlas.prototype._setOpacityForWebGL;
-} else {
- cc.LabelAtlas.prototype.updateAtlasValues = cc.LabelAtlas.prototype._updateAtlasValuesForCanvas;
- cc.LabelAtlas.prototype.setString = cc.LabelAtlas.prototype._setStringForCanvas;
- cc.LabelAtlas.prototype.setOpacity = cc.LabelAtlas.prototype._setOpacityForCanvas;
-}
-
-/**
- *
- * It accepts two groups of parameters:
- * a) string, fntFile
- * b) label, textureFilename, width, height, startChar
- *
- * @param {String} strText
- * @param {String} charMapFile charMapFile or fntFile
- * @param {Number} [itemWidth=0]
- * @param {Number} [itemHeight=0]
- * @param {Number} [startCharMap=""]
- * @return {cc.LabelAtlas|Null} returns the LabelAtlas object on success
- * @example
- * //Example
- * //creates the cc.LabelAtlas with a string, a char map file(the atlas), the width and height of each element and the starting char of the atlas
- * var myLabel = cc.LabelAtlas.create('Text to display', 'CharMapfile.png', 12, 20, ' ')
- *
- * //creates the cc.LabelAtlas with a string, a fnt file
- * var myLabel = cc.LabelAtlas.create('Text to display', 'CharMapFile.plist‘);
- */
-cc.LabelAtlas.create = function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
- var ret = new cc.LabelAtlas();
- if (ret && cc.LabelAtlas.prototype.initWithString.apply(ret,arguments)) {
- return ret;
- }
- return null;
-};
-
diff --git a/cocos2d/label_nodes/CCLabelBMFont.js b/cocos2d/label_nodes/CCLabelBMFont.js
deleted file mode 100644
index 7b9f3c0319..0000000000
--- a/cocos2d/label_nodes/CCLabelBMFont.js
+++ /dev/null
@@ -1,1334 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
-
- Use any of these editors to generate BMFonts:
- http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
- http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
- http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
- http://www.angelcode.com/products/bmfont/ (Free, Windows only)
- ****************************************************************************/
-/**
- * @constant
- * @type Number
- */
-cc.LABEL_AUTOMATIC_WIDTH = -1;
-
-cc.KerningHashElement = function (key, amount) {
- this.key = key || 0; //key for the hash. 16-bit for 1st element, 16-bit for 2nd element
- this.amount = amount || 0;
-};
-
-cc.FontDefHashElement = function (key, fontDef) {
- this.key = key || 0; // key. Font Unicode value
- this.fontDef = fontDef || new cc.BMFontDef(); // font definition
-};
-
-cc.BMFontDef = function (charID, rect, xOffset, yOffset, xAdvance) {
- //! ID of the character
- this.charID = charID || 0;
- //! origin and size of the font
- this.rect = rect || cc.rect(0, 0, 0.1, 0.1);
- //! The X amount the image should be offset when drawing the image (in pixels)
- this.xOffset = xOffset || 0;
- //! The Y amount the image should be offset when drawing the image (in pixels)
- this.yOffset = yOffset || 0;
- //! The amount to move the current position after drawing the character (in pixels)
- this.xAdvance = xAdvance || 0;
-};
-
-cc.BMFontPadding = function (left, top, right, bottom) {
- /// padding left
- this.left = left || 0;
- /// padding top
- this.top = top || 0;
- /// padding right
- this.right = right || 0;
- /// padding bottom
- this.bottom = bottom || 0;
-};
-
-/**
- * cc.BMFontConfiguration has parsed _configuration of the the .fnt file
- * @class
- * @extends cc.Class
- */
-cc.BMFontConfiguration = cc.Class.extend(/** @lends cc.BMFontConfiguration# */{
- // XXX: Creating a public interface so that the bitmapFontArray[] is acc.esible
- //@public
- /**
- * FNTConfig: Common Height
- * @type Number
- */
- commonHeight:0,
-
- /**
- * Padding
- * @type cc.BMFontPadding
- */
- padding:null,
-
- /**
- * atlas name
- * @type String
- */
- atlasName:null,
-
- /**
- * values for kerning
- * @type cc.KerningHashElement
- */
- kerningDictionary:null,
-
- /**
- * values for FontDef
- * @type cc.FontDefHashElement
- */
- fontDefDictionary:null,
-
- /**
- * Character Set defines the letters that actually exist in the font
- * @type Array
- */
- characterSet:null,
-
- /**
- * Constructor
- */
- ctor:function () {
- this.padding = new cc.BMFontPadding();
- this.atlasName = "";
- this.kerningDictionary = new cc.KerningHashElement();
- this.fontDefDictionary = {};
- this.characterSet = [];
- },
-
- /**
- * Description of BMFontConfiguration
- * @return {String}
- */
- description:function () {
- return "";
- },
-
- /**
- * @return {String}
- */
- getAtlasName:function () {
- return this.atlasName;
- },
-
- /**
- * @param {String} atlasName
- */
- setAtlasName:function (atlasName) {
- this.atlasName = atlasName;
- },
-
- /**
- * @return {Object}
- */
- getCharacterSet:function () {
- return this.characterSet;
- },
-
- /**
- * initializes a BitmapFontConfiguration with a FNT file
- * @param {String} FNTfile file path
- * @return {Boolean}
- */
- initWithFNTfile:function (FNTfile) {
- cc.Assert(FNTfile != null && FNTfile.length != 0, "");
- this.characterSet = this._parseConfigFile(FNTfile);
- return this.characterSet != null;
- },
-
- _parseConfigFile:function (controlFile) {
- var fullpath = cc.FileUtils.getInstance().fullPathForFilename(controlFile);
- var data = cc.SAXParser.getInstance().getList(fullpath);
- cc.Assert(data, "cc.BMFontConfiguration._parseConfigFile | Open file error.");
-
- if (!data) {
- cc.log("cocos2d: Error parsing FNTfile " + controlFile);
- return null;
- }
-
- var validCharsString = [];
-
- // parse spacing / padding
- var line, re, i;
-
- re = /padding+[a-z0-9\-= ",]+/gi;
- line = re.exec(data)[0];
- if (line) {
- this._parseInfoArguments(line);
- }
-
- re = /common lineHeight+[a-z0-9\-= ",]+/gi;
- line = re.exec(data)[0];
- if (line) {
- this._parseCommonArguments(line);
- }
-
- //re = /page id=[a-zA-Z0-9\.\-= ",]+/gi;
- re = /page id=[0-9]+ file="[\w\-\.]+/gi;
- line = re.exec(data)[0];
- if (line) {
- this._parseImageFileName(line, controlFile);
- }
-
- re = /chars c+[a-z0-9\-= ",]+/gi;
- line = re.exec(data)[0];
- if (line) {
- // Ignore this line
- }
-
- re = /char id=\w[a-z0-9\-= ]+/gi;
- line = data.match(re);
- if (line) {
- // Parse the current line and create a new CharDef
- for (i = 0; i < line.length; i++) {
- var element = new cc.FontDefHashElement();
- this._parseCharacterDefinition(line[i], element.fontDef);
- element.key = element.fontDef.charID;
- this.fontDefDictionary[element.key] = element;
- validCharsString.push(element.fontDef.charID);
- }
- }
-
- /*
- re = /kernings count+[a-z0-9\-= ",]+/gi;
- if (re.test(data)) {
- line = RegExp.$1[0];
- if (line)
- this._parseKerningCapacity(line);
- }*/
-
- re = /kerning first=\w[a-z0-9\-= ]+/gi;
- line = data.match(re);
- if (line) {
- for (i = 0; i < line.length; i++)
- this._parseKerningEntry(line[i]);
- }
-
- return validCharsString;
- },
-
- _parseCharacterDefinition:function (line, characterDefinition) {
- //////////////////////////////////////////////////////////////////////////
- // line to parse:
- // char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=44 xadvance=14 page=0 chnl=0
- //////////////////////////////////////////////////////////////////////////
- // Character ID
- var value = /id=(\d+)/gi.exec(line)[1];
- characterDefinition.charID = value.toString();
-
- // Character x
- value = /x=([\-\d]+)/gi.exec(line)[1];
- characterDefinition.rect.x = parseInt(value);
-
- // Character y
- value = /y=([\-\d]+)/gi.exec(line)[1];
- characterDefinition.rect.y = parseInt(value);
-
- // Character width
- value = /width=([\-\d]+)/gi.exec(line)[1];
- characterDefinition.rect.width = parseInt(value);
-
- // Character height
- value = /height=([\-\d]+)/gi.exec(line)[1];
- characterDefinition.rect.height = parseInt(value);
-
- // Character xoffset
- value = /xoffset=([\-\d]+)/gi.exec(line)[1];
- characterDefinition.xOffset = parseInt(value);
-
- // Character yoffset
- value = /yoffset=([\-\d]+)/gi.exec(line)[1];
- characterDefinition.yOffset = parseInt(value);
-
- // Character xadvance
- value = /xadvance=([\-\d]+)/gi.exec(line)[1];
- characterDefinition.xAdvance = parseInt(value);
-
- },
-
- _parseInfoArguments:function (line) {
- //////////////////////////////////////////////////////////////////////////
- // possible lines to parse:
- // info face="Script" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=1,4,3,2 spacing=0,0 outline=0
- // info face="Cracked" size=36 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1
- //////////////////////////////////////////////////////////////////////////
-
- // padding
- var tmpPadding = /padding=(\d+)[,](\d+)[,](\d+)[,](\d+)/gi.exec(line);
- this.padding.left = tmpPadding[1];
- this.padding.top = tmpPadding[2];
- this.padding.right = tmpPadding[3];
- this.padding.bottom = tmpPadding[4];
- cc.log("cocos2d: padding: " + this.padding.left + "," + this.padding.top + "," + this.padding.right + "," + this.padding.bottom);
- },
-
- _parseCommonArguments:function (line) {
- //////////////////////////////////////////////////////////////////////////
- // line to parse:
- // common lineHeight=104 base=26 scaleW=1024 scaleH=512 pages=1 packed=0
- //////////////////////////////////////////////////////////////////////////
-
- var value;
- // Height
- this.commonHeight = parseInt(/lineHeight=(\d+)/gi.exec(line)[1]);
-
- if (cc.renderContextType === cc.WEBGL) {
- var scaleW = parseInt(/scaleW=(\d+)/gi.exec(line)[1]);
- cc.Assert(scaleW <= cc.Configuration.getInstance().getMaxTextureSize(), "cc.LabelBMFont: page can't be larger than supported");
-
- var scaleH = parseInt(/scaleH=(\d+)/gi.exec(line)[1]);
- cc.Assert(scaleH <= cc.Configuration.getInstance().getMaxTextureSize(), "cc.LabelBMFont: page can't be larger than supported");
- }
-
- // pages. sanity check
- value = /pages=(\d+)/gi.exec(line)[1];
- cc.Assert(parseInt(value) == 1, "cc.BitfontAtlas: only supports 1 page");
-
- // packed (ignore) What does this mean ??
- },
-
- _parseImageFileName:function (line, fntFile) {
- //////////////////////////////////////////////////////////////////////////
- // line to parse:
- // page id=0 file="bitmapFontTest.png"
- //////////////////////////////////////////////////////////////////////////
- var value;
- // page ID. Sanity check
- value = /id=(\d+)/gi.exec(line)[1];
- cc.Assert(parseInt(value) == 0, "LabelBMFont file could not be found");
-
- // file
- value = /file="([a-zA-Z0-9\-\._]+)/gi.exec(line)[1];
-
- this.atlasName = cc.FileUtils.getInstance().fullPathFromRelativeFile(value, fntFile);
- },
-
- _parseKerningCapacity:function (line) {
- },
-
- _parseKerningEntry:function (line) {
- //////////////////////////////////////////////////////////////////////////
- // line to parse:
- // kerning first=121 second=44 amount=-7
- //////////////////////////////////////////////////////////////////////////
- // first
- var value = /first=([\-\d]+)/gi.exec(line)[1];
- var first = parseInt(value);
-
- // second
- value = /second=([\-\d]+)/gi.exec(line)[1];
- var second = parseInt(value);
-
- // amount
- value = /amount=([\-\d]+)/gi.exec(line)[1];
- var amount = parseInt(value);
-
- var element = new cc.KerningHashElement();
- element.amount = amount;
- element.key = (first << 16) | (second & 0xffff);
-
- this.kerningDictionary[element.key] = element;
- },
-
- _purgeKerningDictionary:function () {
- this.kerningDictionary = null;
- },
-
- _purgeFontDefDictionary:function () {
- this.fontDefDictionary = null;
- }
-});
-
-/**
- * Create a cc.BMFontConfiguration
- * @param {String} FNTfile
- * @return {cc.BMFontConfiguration|Null} returns the configuration or null if error
- * @example
- * // Example
- * var conf = cc.BMFontConfiguration.create('myfont.fnt');
- */
-cc.BMFontConfiguration.create = function (FNTfile) {
- var ret = new cc.BMFontConfiguration();
- if (ret.initWithFNTfile(FNTfile)) {
- return ret;
- }
- return null;
-};
-
-/**
- * cc.LabelBMFont is a subclass of cc.SpriteBatchNode.
- *
- * Features:
- *
- Treats each character like a cc.Sprite. This means that each individual character can be:
- * - rotated
- * - scaled
- * - translated
- * - tinted
- * - chage the opacity
- * - It can be used as part of a menu item.
- * - anchorPoint can be used to align the "label"
- * - Supports AngelCode text format
- *
- * Limitations:
- * - All inner characters are using an anchorPoint of (0.5, 0.5) and it is not recommend to change it
- * because it might affect the rendering
- *
- * cc.LabelBMFont implements the protocol cc.LabelProtocol, like cc.Label and cc.LabelAtlas.
- * cc.LabelBMFont has the flexibility of cc.Label, the speed of cc.LabelAtlas and all the features of cc.Sprite.
- * If in doubt, use cc.LabelBMFont instead of cc.LabelAtlas / cc.Label.
- *
- * Supported editors:
- * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
- * http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
- * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
- * http://www.angelcode.com/products/bmfont/ (Free, Windows only)
- * @class
- * @extends cc.SpriteBatchNode
- */
-cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{
- RGBAProtocol:true,
-
- _opacityModifyRGB:false,
-
- _string:null,
- _configuration:null,
-
- // name of fntFile
- _fntFile:null,
-
- // initial string without line breaks
- _initialString : "",
-
- // alignment of all lines
- _alignment:null,
-
- // max width until a line break is added
- _width:0,
- _lineBreakWithoutSpaces:false,
- _imageOffset:null,
-
- _reusedChar:null,
-
- //texture RGBA
- _displayedOpacity:255,
- _realOpacity:255,
- _displayedColor:null,
- _realColor:null,
- _cascadeColorEnabled:false,
- _cascadeOpacityEnabled:false,
-
- _textureLoaded: false,
-
- _setString:function(newString, needUpdateLabel){
- if(!needUpdateLabel){
- this._string = newString;
- } else {
- this._initialString = newString;
- }
- var locChildren = this._children;
- if(locChildren){
- for(var i = 0; i< locChildren.length;i++){
- var selNode = locChildren[i];
- if(selNode)
- selNode.setVisible(false);
- }
- }
- if(this._textureLoaded){
- this.createFontChars();
-
- if(needUpdateLabel)
- this.updateLabel();
- }
- },
- /**
- * Constructor
- */
- ctor:function () {
- cc.SpriteBatchNode.prototype.ctor.call(this);
- this._imageOffset = cc.PointZero();
- this._string = "";
- this._initialString = "";
- this._alignment = cc.TEXT_ALIGNMENT_CENTER;
- this._width = -1;
- this._configuration = null;
- this._lineBreakWithoutSpaces = false;
-
- this._displayedOpacity = 255;
- this._realOpacity = 255;
- this._displayedColor = cc.white();
- this._realColor = cc.white();
- this._cascadeColorEnabled = true;
- this._cascadeOpacityEnabled = true;
- this._opacityModifyRGB = false;
-
- this._fntFile = "";
- this._reusedChar = [];
- },
- /**
- * @param {CanvasRenderingContext2D} ctx
- */
- draw:function (ctx) {
- cc.SpriteBatchNode.prototype.draw.call(this, ctx);
-
- //LabelBMFont - Debug draw
- if (cc.LABELBMFONT_DEBUG_DRAW) {
- var size = this.getContentSize();
- var pos = cc.p(0 | ( -this._anchorPointInPoints.x), 0 | ( -this._anchorPointInPoints.y));
- var vertices = [cc.p(pos.x, pos.y), cc.p(pos.x + size.width, pos.y), cc.p(pos.x + size.width, pos.y + size.height), cc.p(pos.x, pos.y + size.height)];
- cc.drawingUtil.setDrawColor4B(0,255,0,255);
- cc.drawingUtil.drawPoly(vertices, 4, true);
- }
- },
-
- //TODO
- /**
- * tint this label
- * @param {cc.Color3B} color3
- */
- setColor:function (color3) {
- if (((this._realColor.r == color3.r) && (this._realColor.g == color3.g) && (this._realColor.b == color3.b)))
- return;
- this._displayedColor = {r:color3.r, g:color3.g, b:color3.b};
- this._realColor = {r:color3.r, g:color3.g, b:color3.b};
-
- if(this._textureLoaded){
- if(this._cascadeColorEnabled){
- var parentColor = cc.white();
- var locParent = this._parent;
- if(locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled())
- parentColor = locParent.getDisplayedColor();
- this.updateDisplayedColor(parentColor);
- }
- }
- },
-
- /**
- * conforms to cc.RGBAProtocol protocol
- * @return {Boolean}
- */
- isOpacityModifyRGB:function () {
- return this._opacityModifyRGB;
- },
-
- /**
- * @param {Boolean} opacityModifyRGB
- */
- setOpacityModifyRGB:function (opacityModifyRGB) {
- this._opacityModifyRGB = opacityModifyRGB;
- var locChildren = this._children;
- if (locChildren) {
- for (var i = 0; i < locChildren.length; i++) {
- var node = locChildren[i];
- if (node && node.RGBAProtocol)
- node.setOpacityModifyRGB(this._opacityModifyRGB);
- }
- }
- },
-
- getOpacity:function(){
- return this._realOpacity;
- },
-
- getDisplayedOpacity:function(){
- return this._displayedOpacity;
- },
-
- /**
- * Override synthesized setOpacity to recurse items
- * @param {Number} opacity
- */
- setOpacity:function(opacity){
- this._displayedOpacity = this._realOpacity = opacity;
- if(this._cascadeOpacityEnabled){
- var parentOpacity = 255;
- var locParent = this._parent;
- if(locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled())
- parentOpacity = locParent.getDisplayedOpacity();
- this.updateDisplayedOpacity(parentOpacity);
- }
- },
-
- updateDisplayedOpacity:function(parentOpacity){
- this._displayedOpacity = this._realOpacity * parentOpacity/255.0;
- var locChildren = this._children;
- for(var i = 0; i< locChildren; i++){
- var locChild = locChildren[i];
- if(cc.Browser.supportWebGL){
- locChild.updateDisplayedOpacity(this._displayedOpacity);
- }else{
- cc.NodeRGBA.prototype.updateDisplayedOpacity.call(locChild, this._displayedOpacity);
- locChild.setNodeDirty();
- }
- }
- this._changeTextureColor();
- },
-
- isCascadeOpacityEnabled:function(){
- return false;
- },
-
- setCascadeOpacityEnabled:function(cascadeOpacityEnabled){
- this._cascadeOpacityEnabled = cascadeOpacityEnabled;
- },
-
- getColor:function(){
- return this._realColor;
- },
-
- getDisplayedColor:function(){
- return this._displayedColor;
- },
-
- updateDisplayedColor:function(parentColor){
- var locDispColor = this._displayedColor;
- var locRealColor = this._realColor;
- locDispColor.r = locRealColor.r * parentColor.r/255.0;
- locDispColor.g = locRealColor.g * parentColor.g/255.0;
- locDispColor.b = locRealColor.b * parentColor.b/255.0;
-
- var locChildren = this._children;
- for(var i = 0;i < locChildren.length;i++){
- var locChild = locChildren[i];
- if(cc.Browser.supportWebGL){
- locChild.updateDisplayedColor(this._displayedColor);
- }else{
- cc.NodeRGBA.prototype.updateDisplayedColor.call(locChild, this._displayedColor);
- locChild.setNodeDirty();
- }
- }
- this._changeTextureColor();
- },
-
- _changeTextureColor:function(){
- if(cc.Browser.supportWebGL){
- return;
- }
- var locElement, locTexture = this.getTexture();
- if (locTexture) {
- locElement = locTexture.getHtmlElementObj();
- if (!locElement)
- return;
- var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture.getHtmlElementObj());
- if (cacheTextureForColor) {
- if (locElement instanceof HTMLCanvasElement && !this._rectRotated)
- cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, null, locElement);
- else{
- locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor);
- locTexture = new cc.Texture2D();
- locTexture.initWithElement(locElement);
- locTexture.handleLoadedTexture();
- this.setTexture(locTexture);
- }
- }
- }
- },
-
- isCascadeColorEnabled:function(){
- return false;
- },
-
- setCascadeColorEnabled:function(cascadeColorEnabled){
- this._cascadeColorEnabled = cascadeColorEnabled;
- },
-
- /**
- * init LabelBMFont
- */
- init:function () {
- return this.initWithString(null, null, null, null, null);
- },
-
- /**
- * init a bitmap font altas with an initial string and the FNT file
- * @param {String} str
- * @param {String} fntFile
- * @param {Number} width
- * @param {Number} alignment
- * @param {cc.Point} imageOffset
- * @return {Boolean}
- */
- initWithString:function (str, fntFile, width, alignment, imageOffset) {
- var theString = str || "";
-
- cc.Assert(!this._configuration, "re-init is no longer supported");
-
- var texture;
- if (fntFile) {
- var newConf = cc.FNTConfigLoadFile(fntFile);
- cc.Assert(newConf, "cc.LabelBMFont: Impossible to create font. Please check file");
- this._configuration = newConf;
- this._fntFile = fntFile;
- texture = cc.TextureCache.getInstance().addImage(this._configuration.getAtlasName());
- var locIsLoaded = texture.isLoaded();
- this._textureLoaded = locIsLoaded;
- if(!locIsLoaded){
- this._textureLoaded = false;
- texture.addLoadedEventListener(function(sender){
- this._textureLoaded = true;
- //reset the LabelBMFont
- this.initWithTexture(sender, theString.length)
- this.setString(theString,true);
- }, this);
- }
- } else{
- texture = new cc.Texture2D();
- var image = new Image();
- texture.initWithElement(image);
- this._textureLoaded = false;
- }
-
- if (this.initWithTexture(texture, theString.length)) {
- this._alignment = alignment || cc.TEXT_ALIGNMENT_LEFT;
- this._imageOffset = imageOffset || cc.PointZero();
- this._width = (width == null) ? -1 : width;
-
- this._displayedOpacity = this._realOpacity = 255;
- this._displayedColor = cc.white();
- this._realColor = cc.white();
- this._cascadeOpacityEnabled = true;
- this._cascadeColorEnabled = true;
-
- this._contentSize = cc.SizeZero();
-
- this.setAnchorPoint(cc.p(0.5, 0.5));
-
- if (cc.renderContextType === cc.WEBGL) {
- var locTexture = this._textureAtlas.getTexture();
- this._opacityModifyRGB = locTexture.hasPremultipliedAlpha();
-
- this._reusedChar = new cc.Sprite();
- this._reusedChar.initWithTexture(locTexture, cc.rect(0, 0, 0, 0), false);
- this._reusedChar.setBatchNode(this);
- }
- this.setString(theString,true);
- return true;
- }
- return false;
- },
-
- /**
- * updates the font chars based on the string to render
- */
- createFontChars:function () {
- var locContextType = cc.renderContextType;
- var locTexture = (locContextType === cc.CANVAS) ? this.getTexture() : this._textureAtlas.getTexture();
-
- var nextFontPositionX = 0;
- var prev = -1;
- var kerningAmount = 0;
-
- var tmpSize = cc.SizeZero();
-
- var longestLine = 0;
-
- var quantityOfLines = 1;
-
- var stringLen = this._string ? this._string.length : 0;
-
- if (stringLen === 0)
- return;
-
- var i, charSet = this._configuration.getCharacterSet();
- for (i = 0; i < stringLen - 1; i++) {
- if (this._string.charCodeAt(i) == 10)
- quantityOfLines++;
- }
-
- var totalHeight = this._configuration.commonHeight * quantityOfLines;
- var nextFontPositionY = -(this._configuration.commonHeight - this._configuration.commonHeight * quantityOfLines);
-
- for (i = 0; i < stringLen; i++) {
- var key = this._string.charCodeAt(i);
-
- if (key === 10) {
- //new line
- nextFontPositionX = 0;
- nextFontPositionY -= this._configuration.commonHeight;
- continue;
- }
-
- if (charSet[key] === null) {
- cc.log("cc.LabelBMFont: Attempted to use character not defined in this bitmap: " + this._string[i]);
- continue;
- }
-
- kerningAmount = this._kerningAmountForFirst(prev,key);
- var element = this._configuration.fontDefDictionary[key];
- if (!element) {
- if(key !== 0 && key !== 10)
- cc.log("cocos2d: LabelBMFont: character not found " + this._string[i]);
- continue;
- }
-
- var fontDef = element.fontDef;
-
- var rect = cc.rect(fontDef.rect.x, fontDef.rect.y, fontDef.rect.width, fontDef.rect.height);
- rect = cc.RECT_PIXELS_TO_POINTS(rect);
- rect.x += this._imageOffset.x;
- rect.y += this._imageOffset.y;
-
- var fontChar = this.getChildByTag(i);
- //var hasSprite = true;
- if (!fontChar) {
- fontChar = new cc.Sprite();
- if ((key === 32) && (locContextType === cc.CANVAS)) {
- fontChar.initWithTexture(locTexture, cc.RectZero(), false);
- } else
- fontChar.initWithTexture(locTexture, rect, false);
- fontChar._newTextureWhenChangeColor = true;
- this.addChild(fontChar, 0, i);
- } else {
- if ((key === 32) && (locContextType === cc.CANVAS)) {
- fontChar.setTextureRect(rect, false, cc.SizeZero());
- } else {
- // updating previous sprite
- fontChar.setTextureRect(rect, false, rect.size);
- // restore to default in case they were modified
- fontChar.setVisible(true);
- }
- }
- // Apply label properties
- fontChar.setOpacityModifyRGB(this._opacityModifyRGB);
- // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on
- if (cc.Browser.supportWebGL) {
- fontChar.updateDisplayedColor(this._displayedColor);
- fontChar.updateDisplayedOpacity(this._displayedOpacity);
- } else {
- cc.NodeRGBA.prototype.updateDisplayedColor.call(fontChar, this._displayedColor);
- cc.NodeRGBA.prototype.updateDisplayedOpacity.call(fontChar, this._displayedOpacity);
- fontChar.setNodeDirty();
- }
-
- var yOffset = this._configuration.commonHeight - fontDef.yOffset;
- var fontPos = cc.p(nextFontPositionX + fontDef.xOffset + fontDef.rect.width * 0.5 + kerningAmount,
- nextFontPositionY + yOffset - rect.height * 0.5 * cc.CONTENT_SCALE_FACTOR());
- fontChar.setPosition(cc.POINT_PIXELS_TO_POINTS(fontPos));
-
- // update kerning
- nextFontPositionX += fontDef.xAdvance + kerningAmount;
- prev = key;
-
- if (longestLine < nextFontPositionX)
- longestLine = nextFontPositionX;
- }
-
- tmpSize.width = longestLine;
- tmpSize.height = totalHeight;
- this.setContentSize(cc.SIZE_PIXELS_TO_POINTS(tmpSize));
- },
-
- /**
- * update String
- * @param {Boolean} fromUpdate
- */
- updateString:function (fromUpdate) {
- var locChildren = this._children;
- if (locChildren) {
- for (var i = 0; i < locChildren.length; i++) {
- var node = locChildren[i];
- if (node)
- node.setVisible(false);
- }
- }
- if (this._configuration)
- this.createFontChars();
-
- if (!fromUpdate)
- this.updateLabel();
- },
-
- /**
- * get the text of this label
- * @return {String}
- */
- getString:function () {
- return this._initialString;
- },
-
- /**
- * set the text
- * @param {String} newString
- * @param {Boolean|null} needUpdateLabel
- */
- setString: function (newString, needUpdateLabel) {
- newString = String(newString);
- if(needUpdateLabel == null)
- needUpdateLabel = true;
- if (newString == null || typeof(newString) != "string")
- newString = newString + "";
-
- this._initialString = newString;
- this._setString(newString, needUpdateLabel);
- },
-
- /**
- * @deprecated
- * @param label
- */
- setCString:function (label) {
- this.setString(label,true);
- },
-
- /**
- * update Label
- */
- updateLabel:function () {
- this.setString(this._initialString, false);
-
- if (this._width > 0) {
- // Step 1: Make multiline
- var stringLength = this._string.length;
- var multiline_string = [];
- var last_word = [];
-
- var line = 1, i = 0, start_line = false, start_word = false, startOfLine = -1, startOfWord = -1, skip = 0, j;
-
- var characterSprite;
- for (j = 0; j < this._children.length; j++) {
- var justSkipped = 0;
- while (!(characterSprite = this.getChildByTag(j + skip + justSkipped)))
- justSkipped++;
- skip += justSkipped;
-
- if (!characterSprite.isVisible())
- continue;
- if (i >= stringLength)
- break;
-
- var character = this._string[i];
- if (!start_word) {
- startOfWord = this._getLetterPosXLeft(characterSprite);
- start_word = true;
- }
- if (!start_line) {
- startOfLine = startOfWord;
- start_line = true;
- }
-
- // Newline.
- if (character.charCodeAt(0) == 10) {
- last_word.push('\n');
- multiline_string = multiline_string.concat(last_word);
- last_word.length = 0;
- start_word = false;
- start_line = false;
- startOfWord = -1;
- startOfLine = -1;
- i+= justSkipped;
- line++;
-
- if (i >= stringLength)
- break;
-
- character = this._string[i];
-
- if (!startOfWord) {
- startOfWord = this._getLetterPosXLeft(characterSprite);
- start_word = true;
- }
- if (!startOfLine) {
- startOfLine = startOfWord;
- start_line = true;
- }
- }
-
- // Whitespace.
- if (character.charCodeAt(0) == 32) {
- last_word.push(character);
- multiline_string = multiline_string.concat(last_word);
- last_word.length = 0;
- start_word = false;
- startOfWord = -1;
- i++;
- continue;
- }
-
- // Out of bounds.
- if (this._getLetterPosXRight(characterSprite) - startOfLine > this._width) {
- if (!this._lineBreakWithoutSpaces) {
- last_word.push(character);
-
- var found = multiline_string.lastIndexOf(" ");
- if (found != -1)
- cc.utf8_trim_ws(multiline_string);
- else
- multiline_string = [];
-
- if (multiline_string.length > 0)
- multiline_string.push('\n');
-
- line++;
- start_line = false;
- startOfLine = -1;
- i++;
- } else {
- cc.utf8_trim_ws(last_word);
-
- last_word.push('\n');
- multiline_string = multiline_string.concat(last_word);
- last_word.length = 0;
- start_word = false;
- start_line = false;
- startOfWord = -1;
- startOfLine = -1;
- line++;
-
- if (i >= stringLength)
- break;
-
- if (!startOfWord) {
- startOfWord = this._getLetterPosXLeft(characterSprite);
- start_word = true;
- }
- if (!startOfLine) {
- startOfLine = startOfWord;
- start_line = true;
- }
- j--;
- }
- } else {
- // Character is normal.
- last_word.push(character);
- i++;
- }
- }
-
- multiline_string = multiline_string.concat(last_word);
- var len = multiline_string.length;
- var str_new = "";
-
- for (i = 0; i < len; ++i)
- str_new += multiline_string[i];
-
- str_new = str_new + String.fromCharCode(0);
- //this.updateString(true);
- this._setString(str_new, false)
- }
-
- // Step 2: Make alignment
- if (this._alignment != cc.TEXT_ALIGNMENT_LEFT) {
- i = 0;
-
- var lineNumber = 0;
- var strlen = this._string.length;
- var last_line = [];
-
- for (var ctr = 0; ctr < strlen; ctr++) {
- if (this._string[ctr].charCodeAt(0) == 10 || this._string[ctr].charCodeAt(0) == 0) {
- var lineWidth = 0;
- var line_length = last_line.length;
- var index = i + line_length - 1 + lineNumber;
- if (index < 0) continue;
-
- var lastChar = this.getChildByTag(index);
- if (lastChar == null)
- continue;
- lineWidth = lastChar.getPosition().x + lastChar.getContentSize().width / 2;
-
- var shift = 0;
- switch (this._alignment) {
- case cc.TEXT_ALIGNMENT_CENTER:
- shift = this.getContentSize().width / 2 - lineWidth / 2;
- break;
- case cc.TEXT_ALIGNMENT_RIGHT:
- shift = this.getContentSize().width - lineWidth;
- break;
- default:
- break;
- }
-
- if (shift != 0) {
- for (j = 0; j < line_length; j++) {
- index = i + j + lineNumber;
- if (index < 0) continue;
- characterSprite = this.getChildByTag(index);
- if (characterSprite)
- characterSprite.setPosition(cc.pAdd(characterSprite.getPosition(), cc.p(shift, 0)));
- }
- }
-
- i += line_length;
- lineNumber++;
-
- last_line.length = 0;
- continue;
- }
- last_line.push(this._string[i]);
- }
- }
- },
-
- /**
- * Set text vertical alignment
- * @param {Number} alignment
- */
- setAlignment:function (alignment) {
- this._alignment = alignment;
- this.updateLabel();
- },
-
- /**
- * @param {Number} width
- */
- setWidth:function (width) {
- this._width = width;
- this.updateLabel();
- },
-
- /**
- * @param {Boolean} breakWithoutSpace
- */
- setLineBreakWithoutSpace:function (breakWithoutSpace) {
- this._lineBreakWithoutSpaces = breakWithoutSpace;
- this.updateLabel();
- },
-
- /**
- * @param {Number} scale
- * @param {Number} [scaleY=null]
- */
- setScale:function (scale, scaleY) {
- cc.Node.prototype.setScale.call(this, scale, scaleY);
- this.updateLabel();
- },
-
- /**
- * @param {Number} scaleX
- */
- setScaleX:function (scaleX) {
- cc.Node.prototype.setScaleX.call(this,scaleX);
- this.updateLabel();
- },
-
- /**
- * @param {Number} scaleY
- */
- setScaleY:function (scaleY) {
- cc.Node.prototype.setScaleY.call(this,scaleY);
- this.updateLabel();
- },
-
- //TODO
- /**
- * set fnt file path
- * @param {String} fntFile
- */
- setFntFile:function (fntFile) {
- if (fntFile != null && fntFile != this._fntFile) {
- var newConf = cc.FNTConfigLoadFile(fntFile);
-
- cc.Assert(newConf, "cc.LabelBMFont: Impossible to create font. Please check file");
-
- this._fntFile = fntFile;
- this._configuration = newConf;
-
- var texture = cc.TextureCache.getInstance().addImage(this._configuration.getAtlasName());
- var locIsLoaded = texture.isLoaded();
- this._textureLoaded = locIsLoaded;
- this.setTexture(texture);
- if (cc.renderContextType === cc.CANVAS)
- this._originalTexture = this.getTexture();
- if(!locIsLoaded){
- texture.addLoadedEventListener(function(sender){
- this._textureLoaded = true;
- this.setTexture(sender);
- this.createFontChars();
- this._changeTextureColor();
- this.updateLabel();
- }, this);
- } else {
- this.createFontChars();
- }
- }
- },
-
- /**
- * @return {String}
- */
- getFntFile:function () {
- return this._fntFile;
- },
-
- /**
- * set the AnchorPoint of the label
- * @param {cc.Point} point
- */
- setAnchorPoint:function (point) {
- if (!cc.pointEqualToPoint(point, this._anchorPoint)) {
- cc.Node.prototype.setAnchorPoint.call(this, point);
- this.updateLabel();
- }
- },
-
- _atlasNameFromFntFile:function (fntFile) {
- },
-
- _kerningAmountForFirst:function (first, second) {
- var ret = 0;
- var key = (first << 16) | (second & 0xffff);
- if (this._configuration.kerningDictionary) {
- var element = this._configuration.kerningDictionary[key.toString()];
- if (element)
- ret = element.amount;
- }
- return ret;
- },
-
- _getLetterPosXLeft:function (sp) {
- return sp.getPosition().x * this._scaleX + (sp.getContentSize().width * this._scaleX * sp.getAnchorPoint().x);
- },
-
- _getLetterPosXRight:function (sp) {
- return sp.getPosition().x * this._scaleX - (sp.getContentSize().width * this._scaleX * sp.getAnchorPoint().x);
- }
-});
-
-/**
- * creates a bitmap font altas with an initial string and the FNT file
- * @param {String} str
- * @param {String} fntFile
- * @param {String} width
- * @param {Number} alignment
- * @param {cc.Point} imageOffset
- * @return {cc.LabelBMFont|Null}
- * @example
- * // Example 01
- * var label1 = cc.LabelBMFont.create("Test case", "test.fnt");
- *
- * // Example 02
- * var label2 = cc.LabelBMFont.create("test case", "test.fnt", 200, cc.TEXT_ALIGNMENT_LEFT);
- *
- * // Example 03
- * var label3 = cc.LabelBMFont.create("This is a \n test case", "test.fnt", 200, cc.TEXT_ALIGNMENT_LEFT, cc.PointZero());
- */
-cc.LabelBMFont.create = function (str, fntFile, width, alignment, imageOffset) {
- var ret = new cc.LabelBMFont();
- if (arguments.length == 0) {
- if (ret && ret.init()) {
- return ret;
- }
- return null;
- }
-
- if (ret && ret.initWithString(str, fntFile, width, alignment, imageOffset)) {
- return ret;
- }
- return null;
-};
-
-/**
- * shared instance of configuration
- * @type cc.BMFontConfiguration
- */
-cc.LabelBMFont._configurations = null;
-
-/**
- * Load the .fnt file
- * @param {String} fntFile
- * @return {cc.BMFontConfiguration}
- * Constructor
- */
-cc.FNTConfigLoadFile = function (fntFile) {
- if (!cc.LabelBMFont._configurations) {
- cc.LabelBMFont._configurations = {};
- }
- var ret = cc.LabelBMFont._configurations[fntFile];
- if (!ret) {
- ret = cc.BMFontConfiguration.create(fntFile);
- cc.LabelBMFont._configurations[fntFile] = ret;
- }
- return ret;
-};
-
-/**
- * Purges the cached .fnt data
- */
-cc.LabelBMFont.purgeCachedData = function () {
- cc.FNTConfigRemoveCache();
-};
-
-/**
- * Purges the FNT config cache
- */
-cc.FNTConfigRemoveCache = function () {
- if (cc.LabelBMFont._configurations) {
- cc.LabelBMFont._configurations = null;
- }
-};
-
-/**
- * @param {String} ch
- * @return {Boolean} weather the character is a whitespace character.
- */
-cc.isspace_unicode = function (ch) {
- ch = ch.charCodeAt(0);
- return ((ch >= 9 && ch <= 13) || ch == 32 || ch == 133 || ch == 160 || ch == 5760
- || (ch >= 8192 && ch <= 8202) || ch == 8232 || ch == 8233 || ch == 8239
- || ch == 8287 || ch == 12288)
-};
-
-/**
- * @param {Array} str
- */
-cc.utf8_trim_ws = function (str) {
- var len = str.length;
-
- if (len <= 0)
- return;
-
- var last_index = len - 1;
-
- // Only start trimming if the last character is whitespace..
- if (cc.isspace_unicode(str[last_index])) {
- for (var i = last_index - 1; i >= 0; --i) {
- if (cc.isspace_unicode(str[i])) {
- last_index = i;
- }
- else {
- break;
- }
- }
- cc.utf8_trim_from(str, last_index);
- }
-};
-
-/**
- * Trims str st str=[0, index) after the operation.
- * Return value: the trimmed string.
- * @param {Array} str he string to trim
- * @param {Number} index the index to start trimming from.
- */
-cc.utf8_trim_from = function (str, index) {
- var len = str.length;
- if (index >= len || index < 0)
- return;
- str.splice(index, len);
-};
diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js
deleted file mode 100644
index 4f7ea32a5c..0000000000
--- a/cocos2d/label_nodes/CCLabelTTF.js
+++ /dev/null
@@ -1,1049 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels
- * All features from cc.TextureNode are valid in cc.LabelTTF
- * cc.LabelTTF objects are slow for js-binding on mobile devices.Consider using cc.LabelAtlas or cc.LabelBMFont instead.
- * Consider using cc.LabelAtlas or cc.LabelBMFont instead.
- * @class
- * @extends cc.Sprite
- */
-cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{
- _dimensions:null,
- _hAlignment:cc.TEXT_ALIGNMENT_CENTER,
- _vAlignment:cc.VERTICAL_TEXT_ALIGNMENT_TOP,
- _fontName: null,
- _fontSize:0.0,
- _string:"",
- _isMultiLine:false,
- _fontStyleStr:null,
- _colorStyleStr:null,
-
- // font shadow
- _shadowEnabled:false,
- _shadowOffset:null,
- _shadowOpacity:0,
- _shadowBlur:0,
-
- // font stroke
- _strokeEnabled:false,
- _strokeColor:null,
- _strokeSize:0,
- _strokeColorStr:null,
-
- // font tint
- _textFillColor:null,
- _fillColorStr:null,
-
- _strokeShadowOffsetX:0,
- _strokeShadowOffsetY:0,
- _originalPosition:null,
- _needUpdateTexture:false,
-
- _labelCanvas:null,
- _labelContext:null,
-
- /**
- * Constructor
- */
- ctor:function () {
- cc.Sprite.prototype.ctor.call(this);
- this._dimensions = cc.SizeZero();
- this._hAlignment = cc.TEXT_ALIGNMENT_LEFT;
- this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
- this._opacityModifyRGB = false;
- this._fontStyleStr = "";
- this._colorStyleStr = "";
- this._fontName = "Arial";
- this._isMultiLine = false;
-
- this._shadowEnabled = false;
- this._shadowOffset = cc.SizeZero();
- this._shadowOpacity = 0;
- this._shadowBlur = 0;
-
- this._strokeEnabled = false;
- this._strokeColor = cc.white();
- this._strokeSize = 0;
- this._strokeColorStr = "";
-
- this._textFillColor = cc.white();
- this._fillColorStr = "rgba(255,255,255,1)";
- this._strokeShadowOffsetX = 0;
- this._strokeShadowOffsetY = 0;
- this._originalPosition = cc.PointZero();
- this._needUpdateTexture = false;
-
- this._setColorStyleStr();
- },
-
- init:function () {
- return this.initWithString(" ", this._fontName, this._fontSize);
- },
- /**
- * Prints out a description of this class
- * @return {String}
- */
- description:function () {
- return "";
- },
-
- setColor: null,
-
- _setColorForCanvas: function (color3) {
- this.setFontFillColor(color3, true);
- },
-
- getColor: null,
-
- _getColorForCanvas: function () {
- return this._textFillColor;
- },
-
- setOpacity: null,
-
- _setOpacityForCanvas: function (opacity) {
- if (this._opacity === opacity)
- return;
- cc.Sprite.prototype.setOpacity.call(this, opacity);
- this._setColorStyleStr();
- this._needUpdateTexture = true;
- },
-
- _setColorStyleStr:function () {
- var locFillColor = this._textFillColor;
- this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._displayedOpacity / 255 + ")";
- if(this._strokeEnabled){
- var locStrokeColor = this._strokeColor;
- this._strokeColorStr = "rgba(" + locStrokeColor.r + "," + locStrokeColor.g + "," + locStrokeColor.b + ", " + this._displayedOpacity / 255 + ")";
- }
- },
-
- /**
- * returns the text of the label
- * @return {String}
- */
- getString:function () {
- return this._string;
- },
-
- /**
- * return Horizontal Alignment of cc.LabelTTF
- * @return {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT}
- */
- getHorizontalAlignment:function () {
- return this._hAlignment;
- },
-
- /**
- * return Vertical Alignment of cc.LabelTTF
- * @return {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM}
- */
- getVerticalAlignment:function () {
- return this._vAlignment;
- },
-
- /**
- * return Dimensions of cc.LabelTTF
- * @return {cc.Size}
- */
- getDimensions:function () {
- return cc.size(this._dimensions.width, this._dimensions.height);
- },
-
- /**
- * return font size of cc.LabelTTF
- * @return {Number}
- */
- getFontSize:function () {
- return this._fontSize;
- },
-
- /**
- * return font name of cc.LabelTTF
- * @return {String}
- */
- getFontName:function () {
- return this._fontName;
- },
-
- /**
- * initializes the cc.LabelTTF with a font name, alignment, dimension and font size
- * @param {String} label string
- * @param {String} fontName
- * @param {Number} fontSize
- * @param {cc.Size} [dimensions=]
- * @param {Number} [hAlignment=]
- * @param {Number} [vAlignment=]
- * @return {Boolean} return false on error
- */
- initWithString:function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) {
- var strInfo = label + "";
- cc.Assert(strInfo != null, "cc.LabelTTF.initWithString() label is null");
-
- fontSize = fontSize || 16;
- dimensions = dimensions || cc.size(0, fontSize);
- hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT;
- vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP;
-
- if (cc.Sprite.prototype.init.call(this)) {
- this._opacityModifyRGB = false;
- this._dimensions = cc.size(dimensions.width, dimensions.height);
- this._fontName = fontName || "Arial";
- this._hAlignment = hAlignment;
- this._vAlignment = vAlignment;
-
- //this._fontSize = (cc.renderContextType === cc.CANVAS) ? fontSize : fontSize * cc.CONTENT_SCALE_FACTOR();
- this._fontSize = fontSize;
- this._fontStyleStr = this._fontSize + "px '" + fontName + "'";
- this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize);
- this.setString(strInfo);
- this._setColorStyleStr();
- this._updateTexture();
- this._needUpdateTexture = false;
- return true;
- }
- return false;
- },
-
- /**
- * initializes the CCLabelTTF with a font name, alignment, dimension and font size
- * @param {String} text
- * @param {cc.FontDefinition} textDefinition
- * @return {Boolean}
- */
- initWithStringAndTextDefinition:null,
-
- _initWithStringAndTextDefinitionForCanvas:function(text, textDefinition){
- if(!cc.Sprite.prototype.init.call(this))
- return false;
-
- // prepare everything needed to render the label
- this._updateWithTextDefinition(textDefinition, false);
-
- // set the string
- this.setString(text);
-
- return true;
- },
-
- _initWithStringAndTextDefinitionForWebGL:function(text, textDefinition){
- if(!cc.Sprite.prototype.init.call(this))
- return false;
-
- // shader program
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.LabelTTF._SHADER_PROGRAM));
-
- // prepare everything needed to render the label
- this._updateWithTextDefinition(textDefinition, false);
-
- // set the string
- this.setString(text);
-
- return true;
- },
-
- /**
- * set the text definition used by this label
- * @param {cc.FontDefinition} theDefinition
- */
- setTextDefinition:function(theDefinition){
- if (theDefinition)
- this._updateWithTextDefinition(theDefinition, true);
- },
-
- /**
- * get the text definition used by this label
- * @return {cc.FontDefinition}
- */
- getTextDefinition:function(){
- return this._prepareTextDefinition(false);
- },
-
- /**
- * enable or disable shadow for the label
- * @param {cc.Size} shadowOffset
- * @param {Number} shadowOpacity
- * @param {Number} shadowBlur
- * @param {Boolean} [mustUpdateTexture=false] This parameter is not used. It's kept for cocos2d-x JSB compatibility
- */
- enableShadow:function(shadowOffset, shadowOpacity, shadowBlur, mustUpdateTexture){
- if (false === this._shadowEnabled)
- this._shadowEnabled = true;
-
- var locShadowOffset = this._shadowOffset;
- if (locShadowOffset && (locShadowOffset.width != shadowOffset.width) || (locShadowOffset.height != shadowOffset.height)) {
- locShadowOffset.width = shadowOffset.width;
- locShadowOffset.height = shadowOffset.height;
- }
-
- if (this._shadowOpacity != shadowOpacity )
- this._shadowOpacity = shadowOpacity;
-
- if (this._shadowBlur != shadowBlur)
- this._shadowBlur = shadowBlur;
-
- this._needUpdateTexture = true;
- },
-
- /**
- * disable shadow rendering
- * @param {Boolean} [mustUpdateTexture=false] This parameter is not used. It's kept for cocos2d-x JSB compatibility
- */
- disableShadow:function(mustUpdateTexture){
- if (this._shadowEnabled) {
- this._shadowEnabled = false;
- this._needUpdateTexture = true;
- }
- },
-
- /**
- * enable or disable stroke
- * @param {cc.Color3B} strokeColor
- * @param {Number} strokeSize
- * @param {Boolean} [mustUpdateTexture=false] This parameter is not used. It's kept for cocos2d-x JSB compatibility
- */
- enableStroke:function(strokeColor, strokeSize, mustUpdateTexture){
- if(this._strokeEnabled === false)
- this._strokeEnabled = true;
-
- var locStrokeColor = this._strokeColor;
- if ( (locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b) ) {
- this._strokeColor = strokeColor;
- this._strokeColorStr = "rgba("+ (0 | strokeColor.r) + "," + (0 | strokeColor.g) + "," + (0 | strokeColor.b) + ", 1)";
- }
-
- if (this._strokeSize!== strokeSize)
- this._strokeSize = strokeSize || 0;
-
- this._needUpdateTexture = true;
- },
-
- /**
- * disable stroke
- * @param {Boolean} [mustUpdateTexture=false] This parameter is not used. It's kept for cocos2d-x JSB compatibility
- */
- disableStroke:function(mustUpdateTexture){
- if (this._strokeEnabled){
- this._strokeEnabled = false;
- this._needUpdateTexture = true;
- }
- },
-
- /**
- * set text tinting
- * @param {cc.Color3B} tintColor
- * @param {Boolean} [mustUpdateTexture=false] This parameter is not used. It's kept for cocos2d-x JSB compatibility
- */
- setFontFillColor:null,
-
- _setFontFillColorForCanvas: function (tintColor, mustUpdateTexture) {
- var locTextFillColor = this._textFillColor;
- if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b) {
- this._textFillColor = tintColor;
- this._setColorStyleStr();
- this._needUpdateTexture = true;
- }
- },
-
- _setFontFillColorForWebGL: function (tintColor, mustUpdateTexture) {
- var locTextFillColor = this._textFillColor;
- if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b) {
- this._textFillColor = tintColor;
- this._fillColorStr = "rgba(" + (0 | tintColor.r) + "," + (0 | tintColor.g) + "," + (0 | tintColor.b) + ", 1)";
- this._needUpdateTexture = true;
- }
- },
-
- //set the text definition for this label
- _updateWithTextDefinition:function(textDefinition, mustUpdateTexture){
- if(textDefinition.fontDimensions){
- this._dimensions.width = textDefinition.fontDimensions.width;
- this._dimensions.height = textDefinition.fontDimensions.height;
- } else {
- this._dimensions.width = 0;
- this._dimensions.height = 0;
- }
-
- this._hAlignment = textDefinition.fontAlignmentH;
- this._vAlignment = textDefinition.fontAlignmentV;
-
- this._fontName = textDefinition.fontName;
- this._fontSize = textDefinition.fontSize||12;
- this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'";
- this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize);
-
- // shadow
- if ( textDefinition.shadowEnabled)
- this.enableShadow(textDefinition.shadowOffset, textDefinition.shadowOpacity, textDefinition.shadowBlur, false);
-
- // stroke
- if ( textDefinition.strokeEnabled )
- this.enableStroke(textDefinition.strokeColor, textDefinition.strokeSize, false);
-
- // fill color
- this.setFontFillColor(textDefinition.fontFillColor, false);
-
- if (mustUpdateTexture)
- this._updateTexture();
- },
-
- _prepareTextDefinition:function(adjustForResolution){
- var texDef = new cc.FontDefinition();
-
- if (adjustForResolution){
- //texDef.fontSize = (cc.renderContextType === cc.CANVAS) ? this._fontSize : this._fontSize * cc.CONTENT_SCALE_FACTOR();
- texDef.fontSize = this._fontSize;
- texDef.fontDimensions = cc.SIZE_POINTS_TO_PIXELS(this._dimensions);
- } else {
- texDef.fontSize = this._fontSize;
- texDef.fontDimensions = cc.size(this._dimensions.width, this._dimensions.height);
- }
-
- texDef.fontName = this._fontName;
- texDef.fontAlignmentH = this._hAlignment;
- texDef.fontAlignmentV = this._vAlignment;
-
- // stroke
- if ( this._strokeEnabled ){
- texDef.strokeEnabled = true;
- var locStrokeColor = this._strokeColor;
- texDef.strokeColor = new cc.Color3B(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b);
- texDef.strokeSize = this._strokeSize;
- }else
- texDef.strokeEnabled = false;
-
- // shadow
- if ( this._shadowEnabled ){
- texDef.shadowEnabled = true;
- texDef.shadowBlur = this._shadowBlur;
- texDef.shadowOpacity = this._shadowOpacity;
-
- texDef.shadowOffset = adjustForResolution ? cc.SIZE_POINTS_TO_PIXELS(this._shadowOffset)
- : cc.size(this._shadowOffset.width,this._shadowOffset.height);
- }else
- texDef._shadowEnabled = false;
-
- // text tint
- var locTextFillColor = this._textFillColor;
- texDef.fontFillColor = new cc.Color3B(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b);
- return texDef;
- },
-
- _fontClientHeight:18,
- /**
- * changes the string to render
- * @warning Changing the string is as expensive as creating a new cc.LabelTTF. To obtain better performance use cc.LabelAtlas
- * @param {String} text text for the label
- */
- setString:function (text) {
- text = String(text);
- if (this._string != text) {
- this._string = text + "";
-
- // Force update
- this._needUpdateTexture = true;
- }
- },
-
- /**
- * set Horizontal Alignment of cc.LabelTTF
- * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
- */
- setHorizontalAlignment:function (alignment) {
- if (alignment !== this._hAlignment) {
- this._hAlignment = alignment;
-
- // Force update
- this._needUpdateTexture = true;
- }
- },
-
- /**
- * set Vertical Alignment of cc.LabelTTF
- * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment
- */
- setVerticalAlignment:function (verticalAlignment) {
- if (verticalAlignment != this._vAlignment) {
- this._vAlignment = verticalAlignment;
-
- // Force update
- this._needUpdateTexture = true;
- }
- },
-
- /**
- * set Dimensions of cc.LabelTTF
- * @param {cc.Size} dim
- */
- setDimensions:function (dim) {
- if (dim.width != this._dimensions.width || dim.height != this._dimensions.height) {
- this._dimensions = dim;
-
- // Force udpate
- this._needUpdateTexture = true;
- }
- },
-
- /**
- * set font size of cc.LabelTTF
- * @param {Number} fontSize
- */
- setFontSize:function (fontSize) {
- if (this._fontSize !== fontSize) {
- this._fontSize = fontSize;
- this._fontStyleStr = fontSize + "px '" + this._fontName + "'";
- this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,fontSize);
- // Force update
- this._needUpdateTexture = true;
- }
- },
-
- /**
- * set font name of cc.LabelTTF
- * @param {String} fontName
- */
- setFontName:function (fontName) {
- if (this._fontName && this._fontName != fontName ) {
- this._fontName = fontName;
- this._fontStyleStr = this._fontSize + "px '" + fontName + "'";
- this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize);
- // Force update
- this._needUpdateTexture = true;
- }
- },
-
- _drawTTFInCanvas: function (context) {
- if (!context)
- return;
-
- var locContentSizeHeight = this._contentSize.height, locVAlignment = this._vAlignment, locHAlignment = this._hAlignment,
- locFontHeight = this._fontClientHeight;
-
- context.setTransform(1, 0, 0, 1, 0, locContentSizeHeight);
- //this is fillText for canvas
- if (context.font != this._fontStyleStr)
- context.font = this._fontStyleStr;
- if(cc.renderContextType === cc.CANVAS)
- context.fillStyle = this._colorStyleStr;
- else
- context.fillStyle = "rgba(255,255,255,1)";
-
- //stroke style setup
- var locStrokeEnabled = this._strokeEnabled;
- if (locStrokeEnabled) {
- context.lineWidth = this._strokeSize;
- context.strokeStyle = this._strokeColorStr;
- }
-
- var isNegForOffsetX = false, isNegForOffsetY = false;
- //shadow style setup
- if (this._shadowEnabled) {
- var locShadowOffset = this._shadowOffset;
- context.shadowColor = "rgba(128,128,128,1)";
- isNegForOffsetX = locShadowOffset.width < 0;
- isNegForOffsetY = locShadowOffset.height < 0;
- context.shadowOffsetX = locShadowOffset.width;
- context.shadowOffsetY = -locShadowOffset.height;
- context.shadowBlur = this._shadowBlur;
- }
-
- context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment];
- context.textAlign = cc.LabelTTF._textAlign[locHAlignment];
-
- var xOffset = 0, locStrokeShadowOffsetX = this._strokeShadowOffsetX, locStrokeShadowOffsetY = this._strokeShadowOffsetY;
- var yOffset = 0;
- var locContentWidth = this._contentSize.width - locStrokeShadowOffsetX;
- if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT)
- xOffset = isNegForOffsetX ? locContentWidth + locStrokeShadowOffsetX : locContentWidth;
- else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER)
- xOffset = isNegForOffsetX ? locContentWidth / 2 + locStrokeShadowOffsetX : locContentWidth / 2;
- else
- xOffset = isNegForOffsetX ? locStrokeShadowOffsetX : 0;
- if (this._isMultiLine) {
- var locStrLen = this._strings.length;
- if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM){
- yOffset = locFontHeight + locContentSizeHeight - locFontHeight * locStrLen;
- if(isNegForOffsetY)
- yOffset -= locStrokeShadowOffsetY;
- } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER){
- yOffset = locFontHeight / 2 + (locContentSizeHeight - locFontHeight * locStrLen) / 2;
- if(isNegForOffsetY)
- yOffset -= locStrokeShadowOffsetY;
- } else{
- if(isNegForOffsetY)
- yOffset -= locStrokeShadowOffsetY/2;
- else
- yOffset += locStrokeShadowOffsetY/2;
- }
-
- for (var i = 0; i < locStrLen; i++) {
- var line = this._strings[i];
- var tmpOffsetY = -locContentSizeHeight + (locFontHeight * i) + yOffset;
- if (locStrokeEnabled)
- context.strokeText(line, xOffset, tmpOffsetY);
- context.fillText(line, xOffset, tmpOffsetY);
- }
- } else {
- if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) {
- yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY : 0;
- if (locStrokeEnabled)
- context.strokeText(this._string, xOffset, yOffset);
- context.fillText(this._string, xOffset, yOffset);
- } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) {
- yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY/2 -locContentSizeHeight : - locContentSizeHeight + locStrokeShadowOffsetY/2;
- if (locStrokeEnabled)
- context.strokeText(this._string, xOffset, yOffset);
- context.fillText(this._string, xOffset, yOffset);
- } else {
- yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY -locContentSizeHeight / 2 : - locContentSizeHeight / 2;
- if (locStrokeEnabled)
- context.strokeText(this._string, xOffset, yOffset);
- context.fillText(this._string, xOffset, yOffset);
- }
- }
- },
-
- _getLabelContext:function () {
- if (this._labelContext)
- return this._labelContext;
-
- if (!this._labelCanvas) {
- var locCanvas = document.createElement("canvas");
- var labelTexture = new cc.Texture2D();
- labelTexture.initWithElement(locCanvas);
- this.setTexture(labelTexture);
- this._labelCanvas = locCanvas;
- }
- this._labelContext = this._labelCanvas.getContext("2d");
- return this._labelContext;
- },
-
- _updateTTF:function () {
- var locDimensionsWidth = this._dimensions.width, locLabelContext = this._labelContext;
-
- var stringWidth = locLabelContext.measureText(this._string).width;
- if(this._string.indexOf('\n') !== -1 || (locDimensionsWidth !== 0 && stringWidth > locDimensionsWidth && this._string.indexOf(" ") !== -1)) {
- var strings = this._strings = this._string.split('\n');
- var lineWidths = this._lineWidths = [];
- for (var i = 0; i < strings.length; i++) {
- if (strings[i].indexOf(" ") !== -1 && locDimensionsWidth > 0) {
- var percent = locDimensionsWidth / locLabelContext.measureText(this._strings[i]).width;
- var startSearch = 0 | (percent * strings[i].length + 1);
- var cutoff = startSearch;
- var tempLineWidth = 0;
- if (percent < 1) {
- do {
- cutoff = strings[i].lastIndexOf(" ", cutoff - 1);
- var str = strings[i].substring(0, cutoff);
- tempLineWidth = locLabelContext.measureText(str).width;
- if (cutoff === -1) {
- cutoff = strings[i].indexOf(" ", startSearch);
- break;
- }
- } while (tempLineWidth > locDimensionsWidth);
- var newline = strings[i].substr(cutoff + 1);
- strings.splice(i + 1, 0, newline);
- strings[i] = str;
- }
- }
- lineWidths[i] = tempLineWidth || locLabelContext.measureText(strings[i]).width;
- }
- this._isMultiLine = true;
- } else
- this._isMultiLine = false;
-
- var locSize, locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0;
- if(this._strokeEnabled)
- locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize;
- if(this._shadowEnabled){
- var locOffsetSize = this._shadowOffset;
- locStrokeShadowOffsetX += Math.abs(locOffsetSize.width);
- locStrokeShadowOffsetY += Math.abs(locOffsetSize.height);
- }
-
- //get offset for stroke and shadow
- if (locDimensionsWidth === 0) {
- if (this._isMultiLine)
- locSize = cc.size(0 | (Math.max.apply(Math, this._lineWidths) + locStrokeShadowOffsetX),
- 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY));
- else
- locSize = cc.size(0 | (stringWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY));
- } else {
- if(this._dimensions.height === 0){
- if (this._isMultiLine)
- locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY));
- else
- locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY));
- } else {
- //dimension is already set, contentSize must be same as dimension
- locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._dimensions.height + locStrokeShadowOffsetY));
- }
- }
- this.setContentSize(locSize);
- this._strokeShadowOffsetX = locStrokeShadowOffsetX;
- this._strokeShadowOffsetY = locStrokeShadowOffsetY;
-
- this._anchorPointInPoints.x = this._contentSize.width * this._anchorPoint.x;
- this._anchorPointInPoints.y = this._contentSize.height * this._anchorPoint.y;
-
- this.setPosition(this._originalPosition);
- },
-
- setPosition:function(posX, posY){
- var locOriginalPosition = this._originalPosition;
- if (arguments.length == 2){
- locOriginalPosition.x = posX;
- locOriginalPosition.y = posY;
- }else {
- locOriginalPosition.x = posX.x;
- locOriginalPosition.y = posX.y;
- }
-
- //get real position
- var locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0;
- if(this._strokeEnabled)
- locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2;
- if (this._shadowEnabled) {
- var locOffsetSize = this._shadowOffset;
- locStrokeShadowOffsetX += locOffsetSize.width > 0 ? 0 : locOffsetSize.width;
- locStrokeShadowOffsetY += locOffsetSize.height > 0 ? 0 : locOffsetSize.height;
- }
- var realPosition = cc.p(locOriginalPosition.x + locStrokeShadowOffsetX, locOriginalPosition.y + locStrokeShadowOffsetY);
- cc.Sprite.prototype.setPosition.call(this, realPosition);
- },
-
- setPositionX:function(x){
- this._originalPosition.x = x;
- cc.Sprite.prototype.setPositionX.call(this, x);
- },
-
- setPositionY:function(y){
- this._originalPosition.y = y;
- cc.Sprite.prototype.setPositionY.call(this, y);
- },
-
- getPosition:function(){
- if(this._needUpdateTexture)
- this._updateTTF();
- return cc.p(this._originalPosition.x, this._originalPosition.y);
- },
-
- getContentSize:function(){
- if(this._needUpdateTexture)
- this._updateTTF();
- return cc.Sprite.prototype.getContentSize.call(this);
- },
-
- _updateTexture:function () {
- var locContext = this._getLabelContext(), locLabelCanvas = this._labelCanvas;
- var locContentSize = this._contentSize;
-
- if(this._string.length === 0){
- locLabelCanvas.width = 1;
- locLabelCanvas.height = locContentSize.height;
- this.setTextureRect(cc.rect(0, 0, 1, locContentSize.height));
- return true;
- }
-
- //set size for labelCanvas
- locContext.font = this._fontStyleStr;
- this._updateTTF();
- var width = locContentSize.width, height = locContentSize.height;
- var flag = locLabelCanvas.width == width && locLabelCanvas.height == height;
- locLabelCanvas.width = width;
- locLabelCanvas.height = height;
- if(flag) locContext.clearRect(0, 0, width, height);
-
- //draw text to labelCanvas
- this._drawTTFInCanvas(locContext);
- this._texture.handleLoadedTexture();
-
- this.setTextureRect(cc.rect(0, 0, width, height));
- return true;
- },
-
- visit:function(ctx){
- if(!this._string || this._string == "")
- return;
- if(this._needUpdateTexture ){
- this._needUpdateTexture = false;
- this._updateTexture();
- }
- var context = ctx || cc.renderContext;
- cc.Sprite.prototype.visit.call(this,context);
- },
-
- draw: null,
-
- /**
- * draw sprite to canvas
- * @param {WebGLRenderingContext} ctx 3d context of canvas
- */
- _drawForWebGL: function (ctx) {
- if (!this._string || this._string == "")
- return;
-
- var gl = ctx || cc.renderContext, locTexture = this._texture;
- //cc.Assert(!this._batchNode, "If cc.Sprite is being rendered by cc.SpriteBatchNode, cc.Sprite#draw SHOULD NOT be called");
-
- if (locTexture && locTexture._isLoaded) {
- this._shaderProgram.use();
- this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
-
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
- //cc.glBindTexture2D(locTexture);
- cc._currentBoundTexture[0] = locTexture;
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, locTexture._webTextureObj);
-
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX);
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer);
- if (this._quadDirty) {
- gl.bufferData(gl.ARRAY_BUFFER, this._quad.arrayBuffer, gl.STATIC_DRAW);
- this._quadDirty = false;
- }
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0);
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16);
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- }
-
- if (cc.SPRITE_DEBUG_DRAW === 1) {
- // draw bounding box
- var locQuad = this._quad;
- var verticesG1 = [
- cc.p(locQuad.tl.vertices.x, locQuad.tl.vertices.y),
- cc.p(locQuad.bl.vertices.x, locQuad.bl.vertices.y),
- cc.p(locQuad.br.vertices.x, locQuad.br.vertices.y),
- cc.p(locQuad.tr.vertices.x, locQuad.tr.vertices.y)
- ];
- cc.drawingUtil.drawPoly(verticesG1, 4, true);
- } else if (cc.SPRITE_DEBUG_DRAW === 2) {
- // draw texture box
- var drawSizeG2 = this.getTextureRect().size;
- var offsetPixG2 = this.getOffsetPosition();
- var verticesG2 = [cc.p(offsetPixG2.x, offsetPixG2.y), cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y),
- cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y + drawSizeG2.height), cc.p(offsetPixG2.x, offsetPixG2.y + drawSizeG2.height)];
- cc.drawingUtil.drawPoly(verticesG2, 4, true);
- } // CC_SPRITE_DEBUG_DRAW
- cc.g_NumberOfDraws++;
- },
-
- _setTextureRectForCanvas: function (rect, rotated, untrimmedSize) {
- this._rectRotated = rotated || false;
- untrimmedSize = untrimmedSize || rect.size;
-
- this.setContentSize(untrimmedSize);
- this.setVertexRect(rect);
-
- var locTextureCoordRect = this._textureRect_Canvas;
- locTextureCoordRect.x = rect.x;
- locTextureCoordRect.y = rect.y;
- locTextureCoordRect.width = rect.width;
- locTextureCoordRect.height = rect.height;
-
- var relativeOffset = this._unflippedOffsetPositionFromCenter;
- if (this._flippedX)
- relativeOffset.x = -relativeOffset.x;
- if (this._flippedY)
- relativeOffset.y = -relativeOffset.y;
- this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - this._rect.width) / 2;
- this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - this._rect.height) / 2;
-
- // rendering using batch node
- if (this._batchNode) {
- this._dirty = true;
- }
- },
-
- _setTextureCoords:function (rect) {
- var tex = this._batchNode ? this._textureAtlas.getTexture() : this._texture;
- if (!tex)
- return;
-
- var atlasWidth = tex.getPixelsWide();
- var atlasHeight = tex.getPixelsHigh();
-
- var left, right, top, bottom, tempSwap, locQuad = this._quad;
- if (this._rectRotated) {
- if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
- left = (2 * rect.x + 1) / (2 * atlasWidth);
- right = left + (rect.height * 2 - 2) / (2 * atlasWidth);
- top = (2 * rect.y + 1) / (2 * atlasHeight);
- bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight);
- } else {
- left = rect.x / atlasWidth;
- right = (rect.x + rect.height) / atlasWidth;
- top = rect.y / atlasHeight;
- bottom = (rect.y + rect.width) / atlasHeight;
- }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
-
- if (this._flippedX) {
- tempSwap = top;
- top = bottom;
- bottom = tempSwap;
- }
-
- if (this._flippedY) {
- tempSwap = left;
- left = right;
- right = tempSwap;
- }
-
- locQuad.bl.texCoords.u = left;
- locQuad.bl.texCoords.v = top;
- locQuad.br.texCoords.u = left;
- locQuad.br.texCoords.v = bottom;
- locQuad.tl.texCoords.u = right;
- locQuad.tl.texCoords.v = top;
- locQuad.tr.texCoords.u = right;
- locQuad.tr.texCoords.v = bottom;
- } else {
- if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
- left = (2 * rect.x + 1) / (2 * atlasWidth);
- right = left + (rect.width * 2 - 2) / (2 * atlasWidth);
- top = (2 * rect.y + 1) / (2 * atlasHeight);
- bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight);
- } else {
- left = rect.x / atlasWidth;
- right = (rect.x + rect.width) / atlasWidth;
- top = rect.y / atlasHeight;
- bottom = (rect.y + rect.height) / atlasHeight;
- } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
-
- if (this._flippedX) {
- tempSwap = left;
- left = right;
- right = tempSwap;
- }
-
- if (this._flippedY) {
- tempSwap = top;
- top = bottom;
- bottom = tempSwap;
- }
-
- locQuad.bl.texCoords.u = left;
- locQuad.bl.texCoords.v = bottom;
- locQuad.br.texCoords.u = right;
- locQuad.br.texCoords.v = bottom;
- locQuad.tl.texCoords.u = left;
- locQuad.tl.texCoords.v = top;
- locQuad.tr.texCoords.u = right;
- locQuad.tr.texCoords.v = top;
- }
- this._quadDirty = true;
- }
-});
-
-if(cc.Browser.supportWebGL){
- cc.LabelTTF.prototype.setColor = cc.Sprite.prototype.setColor;
- cc.LabelTTF.prototype.getColor = cc.Sprite.prototype.getColor;
- cc.LabelTTF.prototype.setOpacity = cc.Sprite.prototype.setOpacity;
- cc.LabelTTF.prototype.initWithStringAndTextDefinition = cc.LabelTTF.prototype._initWithStringAndTextDefinitionForWebGL;
- cc.LabelTTF.prototype.setFontFillColor = cc.LabelTTF.prototype._setFontFillColorForWebGL;
- cc.LabelTTF.prototype.draw = cc.LabelTTF.prototype._drawForWebGL;
- cc.LabelTTF.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForWebGL;
-} else {
- cc.LabelTTF.prototype.setColor = cc.LabelTTF.prototype._setColorForCanvas;
- cc.LabelTTF.prototype.getColor = cc.LabelTTF.prototype._getColorForCanvas;
- cc.LabelTTF.prototype.setOpacity = cc.LabelTTF.prototype._setOpacityForCanvas;
- cc.LabelTTF.prototype.initWithStringAndTextDefinition = cc.LabelTTF.prototype._initWithStringAndTextDefinitionForCanvas;
- cc.LabelTTF.prototype.setFontFillColor = cc.LabelTTF.prototype._setFontFillColorForCanvas;
- cc.LabelTTF.prototype.draw = cc.Sprite.prototype.draw;
- cc.LabelTTF.prototype.setTextureRect = cc.LabelTTF.prototype._setTextureRectForCanvas;
-}
-
-cc.LabelTTF._textAlign = ["left", "center", "right"];
-
-cc.LabelTTF._textBaseline = ["top", "middle", "bottom"];
-
-/**
- * creates a cc.LabelTTF from a fontname, alignment, dimension and font size
- * @param {String} label
- * @param {String} fontName
- * @param {Number} fontSize
- * @param {cc.Size} [dimensions=cc.SIZE_ZERO]
- * @param {Number} [hAlignment]
- * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP]
- * @return {cc.LabelTTF|Null}
- * @example
- * // Example
- * var myLabel = cc.LabelTTF.create('label text', 'Times New Roman', 32, cc.size(32,16), cc.TEXT_ALIGNMENT_LEFT);
- */
-cc.LabelTTF.create = function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) {
- var ret = new cc.LabelTTF();
- if (ret.initWithString(label, fontName, fontSize, dimensions, hAlignment, vAlignment))
- return ret;
- return null;
-};
-
-/**
- * Create a label with string and a font definition
- * @param {String} text
- * @param {cc.FontDefinition} textDefinition
- * @return {cc.LabelTTF|Null}
- */
-cc.LabelTTF.createWithFontDefinition = function(text, textDefinition){
- var ret = new cc.LabelTTF();
- if(ret && ret.initWithStringAndTextDefinition(text, textDefinition))
- return ret;
- return null;
-};
-
-if(cc.USE_LA88_LABELS)
- cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTURECOLOR;
-else
- cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTUREA8COLOR;
-
-cc.LabelTTF.__labelHeightDiv = document.createElement("div");
-cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial";
-cc.LabelTTF.__labelHeightDiv.style.position = "absolute";
-cc.LabelTTF.__labelHeightDiv.style.left = "-100px";
-cc.LabelTTF.__labelHeightDiv.style.top = "-100px";
-cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal";
-document.body.appendChild(cc.LabelTTF.__labelHeightDiv);
-
-cc.LabelTTF.__getFontHeightByDiv = function(fontName, fontSize){
- var clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize];
- if (clientHeight > 0) return clientHeight;
- var labelDiv = cc.LabelTTF.__labelHeightDiv;
- labelDiv.innerHTML = "ajghl~!";
- labelDiv.style.fontFamily = fontName;
- labelDiv.style.fontSize = fontSize + "px";
- clientHeight = labelDiv.clientHeight ;
- cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight;
- labelDiv.innerHTML = "";
- return clientHeight;
-};
-
-cc.LabelTTF.__fontHeightCache = {};
-
-
-
diff --git a/cocos2d/labels/CCLabelAtlas.js b/cocos2d/labels/CCLabelAtlas.js
new file mode 100644
index 0000000000..c5cd81669b
--- /dev/null
+++ b/cocos2d/labels/CCLabelAtlas.js
@@ -0,0 +1,224 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * using image file to print text label on the screen, might be a bit slower than cc.Label, similar to cc.LabelBMFont
+ * @class
+ * @extends cc.LabelBMFont
+ *
+ * @property {String} string - Content string of label
+ *
+ * @param {String} strText
+ * @param {String} charMapFile charMapFile or fntFile
+ * @param {Number} [itemWidth=0]
+ * @param {Number} [itemHeight=0]
+ * @param {Number} [startCharMap=""]
+ * @example
+ * //creates the cc.LabelAtlas with a string, a char map file(the atlas), the width and height of each element and the starting char of the atlas
+ * var myLabel = new cc.LabelAtlas('Text to display', 'CharMapfile.png', 12, 20, ' ')
+ *
+ * //creates the cc.LabelAtlas with a string, a fnt file
+ * var myLabel = new cc.LabelAtlas('Text to display', 'CharMapFile.plist‘);
+ */
+cc.LabelAtlas = cc.LabelBMFont.extend(/** @lends cc.LabelBMFont# */{
+ _className: "LabelAtlas",
+
+ /**
+ *
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * Create a label atlas.
+ * It accepts two groups of parameters:
+ * a) string, fntFile
+ * b) label, textureFilename, width, height, startChar
+ *
+ * @param {String} strText
+ * @param {String} charMapFile charMapFile or fntFile
+ * @param {Number} [itemWidth=0]
+ * @param {Number} [itemHeight=0]
+ * @param {Number} [startCharMap=""]
+ */
+ ctor: function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
+ cc.SpriteBatchNode.prototype.ctor.call(this);
+ this._imageOffset = cc.p(0, 0);
+ this._cascadeColorEnabled = true;
+ this._cascadeOpacityEnabled = true;
+
+ charMapFile && cc.LabelAtlas.prototype.initWithString.call(this, strText, charMapFile, itemWidth, itemHeight, startCharMap);
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new cc.LabelBMFont.WebGLRenderCmd(this);
+ else
+ return new cc.LabelBMFont.CanvasRenderCmd(this);
+ },
+
+ _createFntConfig: function (texture, itemWidth, itemHeight, startCharMap) {
+ var fnt = {};
+ fnt.commonHeight = itemHeight;
+
+ var fontDefDictionary = fnt.fontDefDictionary = {};
+
+ var textureWidth = texture.pixelsWidth;
+ var textureHeight = texture.pixelsHeight;
+
+ var startCharCode = startCharMap.charCodeAt(0);
+ var i = 0;
+ for (var col = itemHeight; col <= textureHeight; col += itemHeight) {
+ for (var row = 0; row < textureWidth; row += itemWidth) {
+ fontDefDictionary[startCharCode+i] = {
+ rect: {x: row, y: col - itemHeight, width:itemWidth, height: itemHeight },
+ xOffset: 0,
+ yOffset: 0,
+ xAdvance: itemWidth
+ };
+ ++i;
+ }
+ }
+
+ fnt.kerningDict = {};
+
+ return fnt;
+ },
+
+ /**
+ *
+ * initializes the cc.LabelAtlas with a string, a char map file(the atlas),
+ * the width and height of each element and the starting char of the atlas
+ * It accepts two groups of parameters:
+ * a) string, fntFile
+ * b) label, textureFilename, width, height, startChar
+ *
+ * @param {String} strText
+ * @param {String|cc.Texture2D} charMapFile charMapFile or fntFile or texture file
+ * @param {Number} [itemWidth=0]
+ * @param {Number} [itemHeight=0]
+ * @param {Number} [startCharMap=""]
+ * @return {Boolean} returns true on success
+ */
+ initWithString: function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
+ var label = strText + "", textureFilename, width, height, startChar;
+ var self = this, theString = label || "";
+ this._initialString = theString;
+ self._string = theString;
+
+ if (itemWidth === undefined) {
+ var dict = cc.loader.getRes(charMapFile);
+ if (parseInt(dict["version"], 10) !== 1) {
+ cc.log("cc.LabelAtlas.initWithString(): Unsupported version. Upgrade cocos2d version");
+ return false;
+ }
+
+ textureFilename = cc.path.changeBasename(charMapFile, dict["textureFilename"]);
+ var locScaleFactor = cc.contentScaleFactor();
+ width = parseInt(dict["itemWidth"], 10) / locScaleFactor;
+ height = parseInt(dict["itemHeight"], 10) / locScaleFactor;
+ startChar = String.fromCharCode(parseInt(dict["firstChar"], 10));
+ } else {
+ textureFilename = charMapFile;
+ width = itemWidth || 0;
+ height = itemHeight || 0;
+ startChar = startCharMap || " ";
+ }
+
+ var texture;
+ if (charMapFile) {
+ self._fntFile = "dummy_fnt_file:" + textureFilename;
+ var spriteFrameBaseName = textureFilename;
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(spriteFrameBaseName) || cc.spriteFrameCache.getSpriteFrame(cc.path.basename(spriteFrameBaseName));
+ if(spriteFrame) {
+ texture = spriteFrame.getTexture();
+ this._spriteFrame = spriteFrame;
+ } else {
+ texture = cc.textureCache.addImage(textureFilename);
+ }
+
+ var newConf = this._createFntConfig(texture, width, height, startChar);
+ newConf.atlasName = textureFilename;
+ self._config = newConf;
+
+ var locIsLoaded = texture.isLoaded();
+ self._textureLoaded = locIsLoaded;
+ if (!locIsLoaded) {
+ texture.addEventListener("load", function (sender) {
+ var self1 = this;
+ self1._textureLoaded = true;
+ //reset the LabelBMFont
+ self1.initWithTexture(sender, self1._initialString.length);
+ self1.setString(self1._initialString, true);
+ self1.dispatchEvent("load");
+ }, self);
+ }
+ } else {
+ texture = new cc.Texture2D();
+ var image = new Image();
+ texture.initWithElement(image);
+ self._textureLoaded = false;
+ }
+
+ if (self.initWithTexture(texture, theString.length)) {
+ self._alignment = cc.TEXT_ALIGNMENT_LEFT;
+ self._imageOffset = cc.p(0, 0);
+ self._width = -1;
+
+ self._realOpacity = 255;
+ self._realColor = cc.color(255, 255, 255, 255);
+
+ self._contentSize.width = 0;
+ self._contentSize.height = 0;
+
+ self.setString(theString, true);
+ return true;
+ }
+ return false;
+ },
+
+ setFntFile: function () {
+ cc.warn("setFntFile doesn't support with LabelAtlas.");
+ }
+
+});
+
+/**
+ *
+ * Please use new cc.LabelAtlas instead.
+ * Create a label atlas.
+ * It accepts two groups of parameters:
+ * a) string, fntFile
+ * b) label, textureFilename, width, height, startChar
+ *
+ * @deprecated since v3.0 please use new cc.LabelAtlas
+ * @param {String} strText
+ * @param {String} charMapFile charMapFile or fntFile
+ * @param {Number} [itemWidth=0]
+ * @param {Number} [itemHeight=0]
+ * @param {Number} [startCharMap=""]
+ * @return {cc.LabelAtlas} returns the LabelAtlas object on success
+ */
+cc.LabelAtlas.create = function (strText, charMapFile, itemWidth, itemHeight, startCharMap) {
+ return new cc.LabelAtlas(strText, charMapFile, itemWidth, itemHeight, startCharMap);
+};
+
diff --git a/cocos2d/labels/CCLabelAtlasCanvasRenderCmd.js b/cocos2d/labels/CCLabelAtlasCanvasRenderCmd.js
new file mode 100644
index 0000000000..890c98be25
--- /dev/null
+++ b/cocos2d/labels/CCLabelAtlasCanvasRenderCmd.js
@@ -0,0 +1,110 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function(){
+ cc.LabelAtlas.CanvasRenderCmd = function(renderableObject){
+ cc.AtlasNode.CanvasRenderCmd.call(this, renderableObject);
+ this._needDraw = false;
+ };
+
+ var proto = cc.LabelAtlas.CanvasRenderCmd.prototype = Object.create(cc.AtlasNode.CanvasRenderCmd.prototype);
+ proto.constructor = cc.LabelAtlas.CanvasRenderCmd;
+
+ proto.setCascade = function(){
+ var node = this._node;
+ node._cascadeOpacityEnabled = true;
+ node._cascadeColorEnabled = false;
+ };
+
+ proto.updateAtlasValues = function(){
+ var node = this._node;
+ var locString = node._string || "";
+ var n = locString.length;
+ var texture = this._textureToRender;
+ var locItemWidth = node._itemWidth , locItemHeight = node._itemHeight; //needn't multiply cc.contentScaleFactor(), because sprite's draw will do this
+
+ for (var i = 0, cr = -1; i < n; i++) {
+ var a = locString.charCodeAt(i) - node._mapStartChar.charCodeAt(0);
+ var row = parseInt(a % node._itemsPerRow, 10);
+ var col = parseInt(a / node._itemsPerRow, 10);
+ if(row < 0 || col < 0)
+ continue;
+ var rect = cc.rect(row * locItemWidth, col * locItemHeight, locItemWidth, locItemHeight);
+ var textureContent = texture._contentSize;
+ if(rect.x < 0 || rect.y < 0 || rect.x + rect.width > textureContent.width || rect.y + rect.height > textureContent.height)
+ continue;
+
+ cr++;
+ var c = locString.charCodeAt(i);
+ var fontChar = node.getChildByTag(i);
+ if (!fontChar) {
+ fontChar = new cc.Sprite();
+ if (c === 32) {
+ fontChar.init();
+ fontChar.setTextureRect(cc.rect(0, 0, 10, 10), false, cc.size(0, 0));
+ } else
+ fontChar.initWithTexture(texture, rect);
+
+ cc.Node.prototype.addChild.call(node, fontChar, 0, i);
+ } else {
+ if (c === 32) {
+ fontChar.init();
+ fontChar.setTextureRect(cc.rect(0, 0, 10, 10), false, cc.size(0, 0));
+ } else {
+ // reusing fonts
+ fontChar.initWithTexture(texture, rect);
+ // restore to default in case they were modified
+ fontChar.visible = true;
+ }
+ }
+ fontChar.setPosition(cr * locItemWidth + locItemWidth / 2, locItemHeight / 2);
+ }
+ this.updateContentSize(i, cr+1);
+ };
+
+ proto.updateContentSize = function(i, cr){
+ var node = this._node,
+ contentSize = node._contentSize;
+ if(i !== cr && i*node._itemWidth === contentSize.width && node._itemHeight === contentSize.height){
+ node.setContentSize(cr * node._itemWidth, node._itemHeight);
+ }
+ };
+
+ proto.setString = function(label){
+ var node = this._node;
+ if (node._children) {
+ var locChildren = node._children;
+ var len = locChildren.length;
+ for (var i = 0; i < len; i++) {
+ var child = locChildren[i];
+ if (child && !child._lateChild)
+ child.visible = false;
+ }
+ }
+ };
+
+ proto._addChild = function(){
+ child._lateChild = true;
+ };
+})();
\ No newline at end of file
diff --git a/cocos2d/labels/CCLabelAtlasWebGLRenderCmd.js b/cocos2d/labels/CCLabelAtlasWebGLRenderCmd.js
new file mode 100644
index 0000000000..5edf6c501b
--- /dev/null
+++ b/cocos2d/labels/CCLabelAtlasWebGLRenderCmd.js
@@ -0,0 +1,170 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.LabelAtlas.WebGLRenderCmd = function (renderable) {
+ cc.AtlasNode.WebGLRenderCmd.call(this, renderable);
+ this._needDraw = true;
+ };
+
+ var proto = cc.LabelAtlas.WebGLRenderCmd.prototype = Object.create(cc.AtlasNode.WebGLRenderCmd.prototype);
+ proto.constructor = cc.LabelAtlas.WebGLRenderCmd;
+
+ proto._updateColor = function () {
+ if (this._colorF32Array) {
+ var locDisplayedColor = this._displayedColor;
+ var a = this._displayedOpacity / 255;
+ if (this._node._opacityModifyRGB) {
+ this._colorF32Array[0] = locDisplayedColor.r * a / 255;
+ this._colorF32Array[1] = locDisplayedColor.g * a / 255;
+ this._colorF32Array[2] = locDisplayedColor.b * a / 255;
+ this._colorF32Array[3] = a;
+ }
+ else {
+ this._colorF32Array[0] = locDisplayedColor.r / 255;
+ this._colorF32Array[1] = locDisplayedColor.g / 255;
+ this._colorF32Array[2] = locDisplayedColor.b / 255;
+ this._colorF32Array[3] = a;
+ }
+ }
+ };
+
+ proto.setCascade = function () {
+ var node = this._node;
+ node._cascadeOpacityEnabled = true;
+ node._cascadeColorEnabled = true;
+ };
+
+ proto.rendering = function (ctx) {
+ cc.AtlasNode.WebGLRenderCmd.prototype.rendering.call(this, ctx);
+ if (cc.LABELATLAS_DEBUG_DRAW) {
+ var node = this._node;
+ var s = node.getContentSize();
+ var locRect = node.getBoundingBoxToWorld();
+ var posX = locRect.x,
+ posY = locRect.y;
+ s.width = locRect.width;
+ s.height = locRect.height;
+ var vertices = [cc.p(posX, posY), cc.p(posX + s.width, posY),
+ cc.p(s.width + posX, s.height + posY), cc.p(posX, posY + s.height)];
+ cc._drawingUtil.drawPoly(vertices, 4, true);
+ }
+ };
+
+ proto.updateAtlasValues = function () {
+ var node = this._node;
+ var locString = node._string;
+ var n = locString.length;
+ var locTextureAtlas = this._textureAtlas;
+
+ var texture = locTextureAtlas.texture;
+ var textureWide = texture.pixelsWidth;
+ var textureHigh = texture.pixelsHeight;
+ var itemWidthInPixels = node._itemWidth;
+ var itemHeightInPixels = node._itemHeight;
+ if (!node._ignoreContentScaleFactor) {
+ itemWidthInPixels = node._itemWidth * cc.contentScaleFactor();
+ itemHeightInPixels = node._itemHeight * cc.contentScaleFactor();
+ }
+ if (n > locTextureAtlas.getCapacity())
+ cc.log("cc.LabelAtlas._updateAtlasValues(): Invalid String length");
+ var quads = locTextureAtlas.quads;
+ var locItemWidth = node._itemWidth;
+ var locItemHeight = node._itemHeight;
+ for (var i = 0, cr = -1; i < n; i++) {
+ var a = locString.charCodeAt(i) - node._mapStartChar.charCodeAt(0);
+ var row = a % node._itemsPerRow;
+ var col = 0 | (a / node._itemsPerRow);
+ if (row < 0 || col < 0)
+ continue;
+ if (row * locItemWidth + locItemWidth > textureWide || col * locItemHeight + locItemHeight > textureHigh)
+ continue;
+
+ cr++;
+ var left, right, top, bottom;
+ if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
+ // Issue #938. Don't use texStepX & texStepY
+ left = (2 * row * itemWidthInPixels + 1) / (2 * textureWide);
+ right = left + (itemWidthInPixels * 2 - 2) / (2 * textureWide);
+ top = (2 * col * itemHeightInPixels + 1) / (2 * textureHigh);
+ bottom = top + (itemHeightInPixels * 2 - 2) / (2 * textureHigh);
+ } else {
+ left = row * itemWidthInPixels / textureWide;
+ right = left + itemWidthInPixels / textureWide;
+ top = col * itemHeightInPixels / textureHigh;
+ bottom = top + itemHeightInPixels / textureHigh;
+ }
+ var quad = quads[i];
+ var locQuadTL = quad.tl, locQuadTR = quad.tr, locQuadBL = quad.bl, locQuadBR = quad.br;
+ locQuadTL.texCoords.u = left;
+ locQuadTL.texCoords.v = top;
+ locQuadTR.texCoords.u = right;
+ locQuadTR.texCoords.v = top;
+ locQuadBL.texCoords.u = left;
+ locQuadBL.texCoords.v = bottom;
+ locQuadBR.texCoords.u = right;
+ locQuadBR.texCoords.v = bottom;
+
+ locQuadBL.vertices.x = (cr * locItemWidth);
+ locQuadBL.vertices.y = 0;
+ locQuadBL.vertices.z = 0.0;
+ locQuadBR.vertices.x = (cr * locItemWidth + locItemWidth);
+ locQuadBR.vertices.y = 0;
+ locQuadBR.vertices.z = 0.0;
+ locQuadTL.vertices.x = cr * locItemWidth;
+ locQuadTL.vertices.y = node._itemHeight;
+ locQuadTL.vertices.z = 0.0;
+ locQuadTR.vertices.x = cr * locItemWidth + locItemWidth;
+ locQuadTR.vertices.y = node._itemHeight;
+ locQuadTR.vertices.z = 0.0;
+ }
+
+ this._updateColor();
+
+ this.updateContentSize(i, cr + 1);
+ if (n > 0) {
+ locTextureAtlas.dirty = true;
+ var totalQuads = locTextureAtlas.totalQuads;
+ if (n > totalQuads)
+ locTextureAtlas.increaseTotalQuadsWith(n - totalQuads);
+ }
+ };
+
+ proto.updateContentSize = function (i, cr) {
+ var node = this._node,
+ contentSize = node._contentSize;
+ if (i !== cr && i * node._itemWidth === contentSize.width && node._itemHeight === contentSize.height) {
+ node.setContentSize(cr * node._itemWidth, node._itemHeight);
+ }
+ };
+
+ proto.setString = function (label) {
+ var len = label.length;
+ if (len > this._textureAtlas.totalQuads)
+ this._textureAtlas.resizeCapacity(len);
+ };
+
+ proto._addChild = function () {
+ };
+})();
diff --git a/cocos2d/labels/CCLabelBMFont.js b/cocos2d/labels/CCLabelBMFont.js
new file mode 100644
index 0000000000..388f0e858c
--- /dev/null
+++ b/cocos2d/labels/CCLabelBMFont.js
@@ -0,0 +1,1022 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+
+ Use any of these editors to generate BMFonts:
+ http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
+ http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
+ http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
+ http://www.angelcode.com/products/bmfont/ (Free, Windows only)
+ ****************************************************************************/
+
+/**
+ * cc.LabelBMFont is a subclass of cc.SpriteBatchNode.
+ *
+ * Features:
+ *
- Treats each character like a cc.Sprite. This means that each individual character can be:
+ * - rotated
+ * - scaled
+ * - translated
+ * - tinted
+ * - change the opacity
+ * - It can be used as part of a menu item.
+ * - anchorPoint can be used to align the "label"
+ * - Supports AngelCode text format
+ *
+ * Limitations:
+ * - All inner characters are using an anchorPoint of (0.5, 0.5) and it is not recommend to change it
+ * because it might affect the rendering
+ *
+ * cc.LabelBMFont implements the protocol cc.LabelProtocol, like cc.Label and cc.LabelAtlas.
+ * cc.LabelBMFont has the flexibility of cc.Label, the speed of cc.LabelAtlas and all the features of cc.Sprite.
+ * If in doubt, use cc.LabelBMFont instead of cc.LabelAtlas / cc.Label.
+ *
+ * Supported editors:
+ * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
+ * http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
+ * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
+ * http://www.angelcode.com/products/bmfont/ (Free, Windows only)
+ * @class
+ * @extends cc.SpriteBatchNode
+ *
+ * @property {String} string - Content string of label
+ * @property {Number} textAlign - Horizontal Alignment of label, cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT
+ * @property {Number} boundingWidth - Width of the bounding box of label, the real content width is limited by boundingWidth
+ *
+ * @param {String} str
+ * @param {String} fntFile
+ * @param {Number} [width=-1]
+ * @param {Number} [alignment=cc.TEXT_ALIGNMENT_LEFT]
+ * @param {cc.Point} [imageOffset=cc.p(0,0)]
+ *
+ * @example
+ * // Example 01
+ * var label1 = new cc.LabelBMFont("Test case", "test.fnt");
+ *
+ * // Example 02
+ * var label2 = new cc.LabelBMFont("test case", "test.fnt", 200, cc.TEXT_ALIGNMENT_LEFT);
+ *
+ * // Example 03
+ * var label3 = new cc.LabelBMFont("This is a \n test case", "test.fnt", 200, cc.TEXT_ALIGNMENT_LEFT, cc.p(0,0));
+ */
+cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{
+ //property string is Getter and Setter.
+ //property textAlign is Getter and Setter.
+ //property boundingWidth is Getter and Setter.
+ _opacityModifyRGB: false,
+
+ _string: "",
+ _config: null,
+
+ // name of fntFile
+ _fntFile: "",
+
+ // initial string without line breaks
+ _initialString: "",
+
+ // alignment of all lines
+ _alignment: cc.TEXT_ALIGNMENT_CENTER,
+
+ // max width until a line break is added
+ _width: -1,
+ _lineBreakWithoutSpaces: false,
+ _imageOffset: null,
+
+ _textureLoaded: false,
+ _className: "LabelBMFont",
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new cc.LabelBMFont.WebGLRenderCmd(this);
+ else
+ return new cc.LabelBMFont.CanvasRenderCmd(this);
+ },
+
+ _setString: function (newString, needUpdateLabel) {
+ if (!needUpdateLabel) {
+ this._string = newString;
+ } else {
+ this._initialString = newString;
+ }
+
+ var locChildren = this._children;
+ if (locChildren) {
+ for (var i = 0; i < locChildren.length; i++) {
+ var selNode = locChildren[i];
+ if (selNode)
+ selNode.setVisible(false);
+ }
+ }
+ if (this._textureLoaded) {
+ if(this._string && this._string.length > 0) {
+ this.createFontChars();
+ }
+ if (needUpdateLabel)
+ this.updateLabel();
+ }
+ },
+
+ /**
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * creates a bitmap font atlas with an initial string and the FNT file.
+ * @param {String} str
+ * @param {String} fntFile
+ * @param {Number} [width=-1]
+ * @param {Number} [alignment=cc.TEXT_ALIGNMENT_LEFT]
+ * @param {cc.Point} [imageOffset=cc.p(0,0)]
+ */
+ ctor: function (str, fntFile, width, alignment, imageOffset) {
+ cc.SpriteBatchNode.prototype.ctor.call(this);
+ this._imageOffset = cc.p(0, 0);
+ this._cascadeColorEnabled = true;
+ this._cascadeOpacityEnabled = true;
+ this.initWithString(str, fntFile, width, alignment, imageOffset);
+ },
+
+ /**
+ * return texture is loaded
+ * @returns {boolean}
+ */
+ textureLoaded: function () {
+ return this._textureLoaded;
+ },
+
+ /**
+ * add texture loaded event listener.
+ * Will execute the callback in the loaded.
+ * @param {Function} callback
+ * @param {Object} target
+ * @deprecated since 3.1, please use addEventListener instead
+ */
+ addLoadedEventListener: function (callback, target) {
+ this.addEventListener("load", callback, target);
+ },
+
+ /**
+ * Conforms to cc.RGBAProtocol protocol.
+ * @return {Boolean}
+ */
+ isOpacityModifyRGB: function () {
+ return this._opacityModifyRGB;
+ },
+
+ /**
+ * Set whether to support cc.RGBAProtocol protocol
+ * @param {Boolean} opacityModifyRGB
+ */
+ setOpacityModifyRGB: function (opacityModifyRGB) {
+ this._opacityModifyRGB = opacityModifyRGB;
+ var locChildren = this._children;
+ if (locChildren) {
+ for (var i = 0; i < locChildren.length; i++) {
+ var node = locChildren[i];
+ if (node)
+ node.opacityModifyRGB = this._opacityModifyRGB;
+ }
+ }
+ },
+
+ _changeTextureColor: function () {
+ this._renderCmd._changeTextureColor();
+ },
+
+ /**
+ * Initialization of the node, please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
+ */
+ init: function () {
+ return this.initWithString(null, null, null, null, null);
+ },
+
+ /**
+ * init a bitmap font atlas with an initial string and the FNT file
+ * @param {String} str
+ * @param {String} fntFile
+ * @param {Number} [width=-1]
+ * @param {Number} [alignment=cc.TEXT_ALIGNMENT_LEFT]
+ * @param {cc.Point} [imageOffset=cc.p(0,0)]
+ * @return {Boolean}
+ */
+ initWithString: function (str, fntFile, width, alignment, imageOffset) {
+ var self = this, theString = str || "";
+
+ if (self._config)
+ cc.log("cc.LabelBMFont.initWithString(): re-init is no longer supported");
+
+ var texture;
+ if (fntFile) {
+ var newConf = cc.loader.getRes(fntFile);
+ if (!newConf) {
+ newConf = cc.FntFrameCache[fntFile] || cc.FntFrameCache[cc.path.basename(fntFile)];
+ if(!newConf) {
+ cc.log("cc.LabelBMFont.initWithString(): Impossible to create font. Please check file");
+ return false;
+ }
+ }
+
+ self._config = newConf;
+ self._fntFile = fntFile;
+ var spriteFrameBaseName = newConf.atlasName;
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(spriteFrameBaseName) || cc.spriteFrameCache.getSpriteFrame(cc.path.basename(spriteFrameBaseName));
+ if(spriteFrame) {
+ texture = spriteFrame.getTexture();
+ this._spriteFrame = spriteFrame;
+ } else {
+ texture = cc.textureCache.addImage(newConf.atlasName);
+ }
+ var locIsLoaded = texture.isLoaded();
+ self._textureLoaded = locIsLoaded;
+ if (!locIsLoaded) {
+ texture.addEventListener("load", function (sender) {
+ var self1 = this;
+ self1._textureLoaded = true;
+ //reset the LabelBMFont
+ self1.initWithTexture(sender, self1._initialString.length);
+ self1.setString(self1._initialString, true);
+ self1.dispatchEvent("load");
+ }, self);
+ }
+ } else {
+ texture = new cc.Texture2D();
+ var image = new Image();
+ texture.initWithElement(image);
+ self._textureLoaded = false;
+ }
+
+ if (self.initWithTexture(texture, theString.length)) {
+ self._alignment = alignment || cc.TEXT_ALIGNMENT_LEFT;
+ self._imageOffset = imageOffset || cc.p(0, 0);
+ self._width = (width === undefined) ? -1 : width;
+
+ self._realOpacity = 255;
+ self._realColor = cc.color(255, 255, 255, 255);
+
+ self._contentSize.width = 0;
+ self._contentSize.height = 0;
+
+ self.setAnchorPoint(0.5, 0.5);
+
+ self.setString(theString, true);
+
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * updates the font chars based on the string to render
+ */
+ createFontChars: function () {
+ var locStr = this._string;
+ var stringLen = locStr ? locStr.length : 0;
+
+ var self = this;
+ var cmd = this._renderCmd;
+ var locTexture = cmd._texture || this._texture;
+
+ var nextFontPositionX = 0;
+
+ var tmpSize = cc.size(0, 0);
+
+ var longestLine = 0;
+
+ var quantityOfLines = 1;
+
+
+ var i, locCfg = self._config, locKerningDict = locCfg.kerningDict,
+ locCommonH = locCfg.commonHeight, locFontDict = locCfg.fontDefDictionary;
+ for (i = 0; i < stringLen - 1; i++) {
+ if (locStr.charCodeAt(i) === 10) quantityOfLines++;
+ }
+
+ var totalHeight = locCommonH * quantityOfLines;
+ var nextFontPositionY = -(locCommonH - locCommonH * quantityOfLines);
+
+ var prev = -1;
+ var fontDef;
+ for (i = 0; i < stringLen; i++) {
+ var key = locStr.charCodeAt(i);
+ if (key === 0) continue;
+
+ if (key === 10) {
+ //new line
+ nextFontPositionX = 0;
+ nextFontPositionY -= locCfg.commonHeight;
+ continue;
+ }
+
+ var kerningAmount = locKerningDict[(prev << 16) | (key & 0xffff)] || 0;
+ fontDef = locFontDict[key];
+ if (!fontDef) {
+ cc.log("cocos2d: LabelBMFont: character not found " + locStr[i]);
+
+ fontDef = {
+ rect: {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0
+ },
+ xOffset: 0,
+ yOffset: 0,
+ xAdvance: 0
+ };
+ }
+
+ var rect = cc.rect(fontDef.rect.x, fontDef.rect.y, fontDef.rect.width, fontDef.rect.height);
+ rect = cc.rectPixelsToPoints(rect);
+ rect.x += self._imageOffset.x;
+ rect.y += self._imageOffset.y;
+
+ var isRotated = false;
+ if(this._spriteFrame) {
+ var textureWidth = locTexture.width;
+ var spriteFrameRect = this._spriteFrame._rect;
+ if(!this._spriteFrame._rotated) {
+ rect.x = rect.x + spriteFrameRect.x;
+ rect.y = rect.y + spriteFrameRect.y;
+ } else {
+ isRotated = true;
+ var originalX = rect.x;
+ rect.x = rect.y + spriteFrameRect.x;
+ rect.y = originalX + spriteFrameRect.y;
+ }
+ }
+
+ var fontChar = self.getChildByTag(i);
+
+ if (!fontChar) {
+ fontChar = new cc.Sprite();
+ fontChar.initWithTexture(locTexture, rect, isRotated);
+ fontChar._newTextureWhenChangeColor = true;
+ this.addChild(fontChar, 0, i);
+ } else {
+ cmd._updateCharTexture(fontChar, rect, key, isRotated);
+ }
+
+ // Apply label properties
+ fontChar.opacityModifyRGB = this._opacityModifyRGB;
+ cmd._updateCharColorAndOpacity(fontChar);
+
+ var yOffset = locCfg.commonHeight - fontDef.yOffset;
+ var fontPos = cc.p(nextFontPositionX + fontDef.xOffset + fontDef.rect.width * 0.5 + kerningAmount,
+ nextFontPositionY + yOffset - rect.height * 0.5 * cc.contentScaleFactor());
+ fontChar.setPosition(cc.pointPixelsToPoints(fontPos));
+
+ // update kerning
+ nextFontPositionX += fontDef.xAdvance + kerningAmount;
+ prev = key;
+
+ if (longestLine < nextFontPositionX)
+ longestLine = nextFontPositionX;
+ }
+
+ //If the last character processed has an xAdvance which is less that the width of the characters image, then we need
+ // to adjust the width of the string to take this into account, or the character will overlap the end of the bounding box
+ if (fontDef && fontDef.xAdvance < fontDef.rect.width)
+ tmpSize.width = longestLine - fontDef.xAdvance + fontDef.rect.width;
+ else
+ tmpSize.width = longestLine;
+ tmpSize.height = totalHeight;
+ self.setContentSize(cc.sizePixelsToPoints(tmpSize));
+ },
+
+ /**
+ * Update String.
+ * Only update this label display string.
+ * @param {Boolean} fromUpdate
+ */
+ updateString: function (fromUpdate) {
+ var self = this;
+ var locChildren = self._children;
+ if (locChildren) {
+ var length = locChildren.length;
+ for (var i = 0, li = length; i < li; i++) {
+ var node = locChildren[i];
+ if (node) node.visible = false;
+ }
+ }
+ if (self._config) {
+ if(self._string && self._string.length > 0) {
+ self.createFontChars();
+ }
+ }
+
+ if (!fromUpdate)
+ self.updateLabel();
+ },
+
+ /**
+ * Gets the text of this label
+ * @return {String}
+ */
+ getString: function () {
+ return this._initialString;
+ },
+
+ /**
+ * Set the text
+ * @param {String} newString
+ * @param {Boolean|null} needUpdateLabel
+ */
+ setString: function (newString, needUpdateLabel) {
+ newString = String(newString);
+ if (needUpdateLabel === undefined)
+ needUpdateLabel = true;
+ if (newString === undefined || typeof newString !== 'string')
+ newString = newString + "";
+
+ this._initialString = newString;
+ this._setString(newString, needUpdateLabel);
+ },
+
+ _setStringForSetter: function (newString) {
+ this.setString(newString, false);
+ },
+
+ /**
+ * Set the text.
+ * Change this Label display string.
+ * @deprecated since v3.0 please use .setString
+ * @param label
+ */
+ setCString: function (label) {
+ this.setString(label, true);
+ },
+
+ // calc the text all with in a line
+ _getCharsWidth: function (startIndex, endIndex) {
+ if (endIndex <= 0) {
+ return 0;
+ }
+ var curTextFirstSprite = this.getChildByTag(startIndex);
+ var curTextLastSprite = this.getChildByTag(startIndex + endIndex);
+ return this._getLetterPosXLeft(curTextLastSprite) - this._getLetterPosXLeft(curTextFirstSprite);
+ },
+
+ _checkWarp: function (strArr, i, maxWidth, initStringWrapNum) {
+ var self = this;
+ var text = strArr[i];
+ var curLength = 0;
+ for (var strArrIndex = 0; strArrIndex < i; strArrIndex++) {
+ curLength += strArr[strArrIndex].length;
+ }
+
+ curLength = curLength + i - initStringWrapNum; // add the wrap line num
+
+ var allWidth = self._getCharsWidth(curLength, strArr[i].length - 1);
+
+ if (allWidth > maxWidth && text.length > 1) {
+ var fuzzyLen = text.length * ( maxWidth / allWidth ) | 0;
+ var tmpText = text.substr(fuzzyLen);
+ var width = allWidth - this._getCharsWidth(curLength + fuzzyLen, tmpText.length - 1);
+ var sLine;
+ var pushNum = 0;
+
+ //Increased while cycle maximum ceiling. default 100 time
+ var checkWhile = 0;
+
+ //Exceeded the size
+ while (width > maxWidth && checkWhile++ < 100) {
+ fuzzyLen *= maxWidth / width;
+ fuzzyLen = fuzzyLen | 0;
+ tmpText = text.substr(fuzzyLen);
+ width = allWidth - this._getCharsWidth(curLength + fuzzyLen, tmpText.length - 1);
+ }
+
+ checkWhile = 0;
+
+ //Find the truncation point
+ while (width < maxWidth && checkWhile++ < 100) {
+ if (tmpText) {
+ var exec = cc.LabelTTF._wordRex.exec(tmpText);
+ pushNum = exec ? exec[0].length : 1;
+ sLine = tmpText;
+ }
+ if (self._lineBreakWithoutSpaces) {
+ pushNum = 0;
+ }
+ fuzzyLen = fuzzyLen + pushNum;
+ tmpText = text.substr(fuzzyLen);
+ width = allWidth - this._getCharsWidth(curLength + fuzzyLen, tmpText.length - 1);
+ }
+
+ fuzzyLen -= pushNum;
+ if (fuzzyLen === 0) {
+ fuzzyLen = 1;
+ sLine = sLine.substr(1);
+ }
+
+ var sText = text.substr(0, fuzzyLen), result;
+
+ //symbol in the first
+ if (cc.LabelTTF.wrapInspection) {
+ if (cc.LabelTTF._symbolRex.test(sLine || tmpText)) {
+ result = cc.LabelTTF._lastWordRex.exec(sText);
+ pushNum = result ? result[0].length : 0;
+ if (self._lineBreakWithoutSpaces) {
+ pushNum = 0;
+ }
+ fuzzyLen -= pushNum;
+
+ sLine = text.substr(fuzzyLen);
+ sText = text.substr(0, fuzzyLen);
+ }
+ }
+
+ //To judge whether a English words are truncated
+ if (cc.LabelTTF._firsrEnglish.test(sLine)) {
+ result = cc.LabelTTF._lastEnglish.exec(sText);
+ if (result && sText !== result[0]) {
+ pushNum = result[0].length;
+ if (self._lineBreakWithoutSpaces) {
+ pushNum = 0;
+ }
+ fuzzyLen -= pushNum;
+ sLine = text.substr(fuzzyLen);
+ sText = text.substr(0, fuzzyLen);
+ }
+ }
+ strArr[i] = sLine || tmpText;
+ strArr.splice(i, 0, sText);
+ }
+ },
+
+ /**
+ * Update Label.
+ * Update this Label display string and more...
+ */
+ updateLabel: function () {
+ var self = this;
+ self.string = self._initialString;
+
+ var i, j, characterSprite;
+ // process string
+ // Step 1: Make multiline
+ if (self._width > 0) {
+ var stringArr = self.string.split('\n');
+ var wrapString = "";
+ var newWrapNum = 0;
+ var oldArrLength = 0;
+ for (i = 0; i < stringArr.length; i++) {
+ oldArrLength = stringArr.length;
+ this._checkWarp(stringArr, i, self._width * this._scaleX, newWrapNum);
+ if (oldArrLength < stringArr.length) {
+ newWrapNum++;
+ }
+ if (i > 0) {
+ wrapString += "\n";
+ }
+ wrapString += stringArr[i];
+ }
+ wrapString = wrapString + String.fromCharCode(0);
+ self._setString(wrapString, false);
+ }
+ // Step 2: Make alignment
+ if (self._alignment !== cc.TEXT_ALIGNMENT_LEFT) {
+ i = 0;
+
+ var lineNumber = 0;
+ var strlen = self._string.length;
+ var last_line = [];
+
+ for (var ctr = 0; ctr < strlen; ctr++) {
+ if (self._string[ctr].charCodeAt(0) === 10 || self._string[ctr].charCodeAt(0) === 0) {
+ var lineWidth = 0;
+ var line_length = last_line.length;
+ // if last line is empty we must just increase lineNumber and work with next line
+ if (line_length === 0) {
+ lineNumber++;
+ continue;
+ }
+ var index = i + line_length - 1 + lineNumber;
+ if (index < 0) continue;
+
+ var lastChar = self.getChildByTag(index);
+ if (lastChar == null)
+ continue;
+ lineWidth = lastChar.getPositionX() + lastChar._getWidth() / 2;
+
+ var shift = 0;
+ switch (self._alignment) {
+ case cc.TEXT_ALIGNMENT_CENTER:
+ shift = self.width / 2 - lineWidth / 2;
+ break;
+ case cc.TEXT_ALIGNMENT_RIGHT:
+ shift = self.width - lineWidth;
+ break;
+ default:
+ break;
+ }
+
+ if (shift !== 0) {
+ for (j = 0; j < line_length; j++) {
+ index = i + j + lineNumber;
+ if (index < 0) continue;
+ characterSprite = self.getChildByTag(index);
+ if (characterSprite)
+ characterSprite.x += shift;
+ }
+ }
+
+ i += line_length;
+ lineNumber++;
+
+ last_line.length = 0;
+ continue;
+ }
+ last_line.push(self._string[i]);
+ }
+ }
+ },
+
+ /**
+ * Set text alignment.
+ * @param {Number} alignment
+ */
+ setAlignment: function (alignment) {
+ this._alignment = alignment;
+ this.updateLabel();
+ },
+
+ _getAlignment: function () {
+ return this._alignment;
+ },
+
+ /**
+ * Set the bounding width.
+ * max with display width. The exceeding string will be wrapping.
+ * @param {Number} width
+ */
+ setBoundingWidth: function (width) {
+ this._width = width;
+ this.updateLabel();
+ },
+
+ _getBoundingWidth: function () {
+ return this._width;
+ },
+
+ /**
+ * Set the param to change English word warp according to whether the space.
+ * default is false.
+ * @param {Boolean} breakWithoutSpace
+ */
+ setLineBreakWithoutSpace: function (breakWithoutSpace) {
+ this._lineBreakWithoutSpaces = breakWithoutSpace;
+ this.updateLabel();
+ },
+
+ /**
+ * Set scale.
+ * Input a number, will be decrease or increase the font size.
+ * @param {Number} scale
+ * @param {Number} [scaleY=null] default is scale
+ */
+ setScale: function (scale, scaleY) {
+ cc.Node.prototype.setScale.call(this, scale, scaleY);
+ this.updateLabel();
+ },
+
+ /**
+ * Set scale of x.
+ * Input a number, will be decrease or increase the font size.
+ * Horizontal scale.
+ * @param {Number} scaleX
+ */
+ setScaleX: function (scaleX) {
+ cc.Node.prototype.setScaleX.call(this, scaleX);
+ this.updateLabel();
+ },
+
+ /**
+ * Set scale of x.
+ * Input a number, will be decrease or increase the font size.
+ * Longitudinal scale.
+ * @param {Number} scaleY
+ */
+ setScaleY: function (scaleY) {
+ cc.Node.prototype.setScaleY.call(this, scaleY);
+ this.updateLabel();
+ },
+
+ /**
+ * set fnt file path.
+ * Change the fnt file path.
+ * @param {String} fntFile
+ */
+ setFntFile: function (fntFile) {
+ var self = this;
+ if (fntFile != null && fntFile !== self._fntFile) {
+ var newConf = cc.loader.getRes(fntFile);
+
+ if (!newConf) {
+ cc.log("cc.LabelBMFont.setFntFile() : Impossible to create font. Please check file");
+ return;
+ }
+
+ self._fntFile = fntFile;
+ self._config = newConf;
+
+ var texture = cc.textureCache.addImage(newConf.atlasName);
+ var locIsLoaded = texture.isLoaded();
+ self._textureLoaded = locIsLoaded;
+ if (!locIsLoaded) {
+ texture.addEventListener("load", function (sender) {
+ var self1 = this;
+ self1._textureLoaded = true;
+ self1.setTexture(sender);
+ if(self1._string && self1._string.length > 0) {
+ self1.createFontChars();
+ }
+
+ self1._changeTextureColor();
+ self1.updateLabel();
+
+ self1.dispatchEvent("load");
+ }, self);
+ } else {
+ self.setTexture(texture);
+ if(self._string && self._string.length > 0) {
+ self.createFontChars();
+ }
+ }
+ }
+ },
+
+ /**
+ * Return the fnt file path.
+ * @return {String}
+ */
+ getFntFile: function () {
+ return this._fntFile;
+ },
+
+ setTexture: function (texture) {
+ this._texture = texture;
+ this._renderCmd.setTexture(texture);
+ },
+
+ /**
+ * Set the AnchorPoint of the labelBMFont.
+ * In order to change the location of label.
+ * @override
+ * @param {cc.Point|Number} point The anchor point of labelBMFont or The anchor point.x of labelBMFont.
+ * @param {Number} [y] The anchor point.y of labelBMFont.
+ */
+ setAnchorPoint: function (point, y) {
+ cc.Node.prototype.setAnchorPoint.call(this, point, y);
+ this.updateLabel();
+ },
+
+ _setAnchorX: function (x) {
+ cc.Node.prototype._setAnchorX.call(this, x);
+ this.updateLabel();
+ },
+
+ _setAnchorY: function (y) {
+ cc.Node.prototype._setAnchorY.call(this, y);
+ this.updateLabel();
+ },
+
+ _atlasNameFromFntFile: function (fntFile) {
+ },
+
+ _kerningAmountForFirst: function (first, second) {
+ var ret = 0;
+ var key = (first << 16) | (second & 0xffff);
+ if (this._configuration.kerningDictionary) {
+ var element = this._configuration.kerningDictionary[key.toString()];
+ if (element)
+ ret = element.amount;
+ }
+ return ret;
+ },
+
+ _getLetterPosXLeft: function (sp) {
+ return sp.getPositionX() * this._scaleX - (sp._getWidth() * this._scaleX * sp._getAnchorX());
+ },
+
+ _getLetterPosXRight: function (sp) {
+ return sp.getPositionX() * this._scaleX + (sp._getWidth() * this._scaleX * sp._getAnchorX());
+ },
+
+ //Checking whether the character is a whitespace
+ _isspace_unicode: function (ch) {
+ ch = ch.charCodeAt(0);
+ return ((ch >= 9 && ch <= 13) || ch === 32 || ch === 133 || ch === 160 || ch === 5760
+ || (ch >= 8192 && ch <= 8202) || ch === 8232 || ch === 8233 || ch === 8239
+ || ch === 8287 || ch === 12288);
+ },
+
+ _utf8_trim_ws: function (str) {
+ var len = str.length;
+
+ if (len <= 0)
+ return;
+
+ var last_index = len - 1;
+
+ // Only start trimming if the last character is whitespace..
+ if (this._isspace_unicode(str[last_index])) {
+ for (var i = last_index - 1; i >= 0; --i) {
+ if (this._isspace_unicode(str[i])) {
+ last_index = i;
+ }
+ else {
+ break;
+ }
+ }
+ this._utf8_trim_from(str, last_index);
+ }
+ },
+
+ //Trims str st str=[0, index) after the operation.
+ //Return value: the trimmed string.
+ _utf8_trim_from: function (str, index) {
+ var len = str.length;
+ if (index >= len || index < 0)
+ return;
+ str.splice(index, len);
+ }
+});
+
+(function () {
+ var p = cc.LabelBMFont.prototype;
+ cc.EventHelper.prototype.apply(p);
+
+ /** @expose */
+ p.string;
+ cc.defineGetterSetter(p, "string", p.getString, p._setStringForSetter);
+ /** @expose */
+ p.boundingWidth;
+ cc.defineGetterSetter(p, "boundingWidth", p._getBoundingWidth, p.setBoundingWidth);
+ /** @expose */
+ p.textAlign;
+ cc.defineGetterSetter(p, "textAlign", p._getAlignment, p.setAlignment);
+
+ // Override properties
+ cc.defineGetterSetter(p, "texture", p.getTexture, p.setTexture);
+})();
+
+/**
+ * creates a bitmap font atlas with an initial string and the FNT file
+ * @deprecated since v3.0 please use new cc.LabelBMFont
+ * @param {String} str
+ * @param {String} fntFile
+ * @param {Number} [width=-1]
+ * @param {Number} [alignment=cc.TEXT_ALIGNMENT_LEFT]
+ * @param {cc.Point} [imageOffset=cc.p(0,0)]
+ * @return {cc.LabelBMFont|Null}
+ */
+cc.LabelBMFont.create = function (str, fntFile, width, alignment, imageOffset) {
+ return new cc.LabelBMFont(str, fntFile, width, alignment, imageOffset);
+};
+
+cc.FntFrameCache = {};
+
+var _fntLoader = {
+ FNT_HEAD: /fntframes [^\n]*(\n|$)/gi,
+ FNT_FRAME_NAME: /fntframe [^\n]*(\n|$)/gi,
+ INFO_EXP: /info [^\n]*(\n|$)/gi,
+ COMMON_EXP: /common [^\n]*(\n|$)/gi,
+ PAGE_EXP: /page [^\n]*(\n|$)/gi,
+ CHAR_EXP: /char [^\n]*(\n|$)/gi,
+ KERNING_EXP: /kerning [^\n]*(\n|$)/gi,
+ ITEM_EXP: /\w+=[^ \r\n]+/gi,
+ INT_EXP: /^[\-]?\d+$/,
+
+ _parseStrToObj: function (str) {
+ var arr = str.match(this.ITEM_EXP);
+ var obj = {};
+ if (arr) {
+ for (var i = 0, li = arr.length; i < li; i++) {
+ var tempStr = arr[i];
+ var index = tempStr.indexOf("=");
+ var key = tempStr.substring(0, index);
+ var value = tempStr.substring(index + 1);
+ if (value.match(this.INT_EXP)) value = parseInt(value);
+ else if (value[0] === '"') value = value.substring(1, value.length - 1);
+ obj[key] = value;
+ }
+ }
+ return obj;
+ },
+
+ _parseFntContent: function (fnt, fntStr, url, useAtlas) {
+ var self = this;
+ //common
+ var commonObj = self._parseStrToObj(fntStr.match(self.COMMON_EXP)[0]);
+ fnt.commonHeight = commonObj["lineHeight"];
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ var texSize = cc.configuration.getMaxTextureSize();
+ if (commonObj["scaleW"] > texSize.width || commonObj["scaleH"] > texSize.height)
+ cc.log("cc.LabelBMFont._parseCommonArguments(): page can't be larger than supported");
+ }
+ if (commonObj["pages"] !== 1) cc.log("cc.LabelBMFont._parseCommonArguments(): only supports 1 page");
+
+ //page
+ var pageObj = self._parseStrToObj(fntStr.match(self.PAGE_EXP)[0]);
+ if (pageObj["id"] !== 0) cc.log("cc.LabelBMFont._parseImageFileName() : file could not be found");
+ if(!useAtlas) {
+ fnt.atlasName = cc.path.changeBasename(url, pageObj["file"]);
+ } else {
+ fnt.atlasName = cc.path.join(cc.path.dirname(useAtlas.path) + pageObj["file"]);
+ }
+
+ //char
+ var charLines = fntStr.match(self.CHAR_EXP);
+ var fontDefDictionary = fnt.fontDefDictionary = {};
+ for (var i = 0, li = charLines.length; i < li; i++) {
+ var charObj = self._parseStrToObj(charLines[i]);
+ var charId = charObj["id"];
+ fontDefDictionary[charId] = {
+ rect: {x: charObj["x"], y: charObj["y"], width: charObj["width"], height: charObj["height"]},
+ xOffset: charObj["xoffset"],
+ yOffset: charObj["yoffset"],
+ xAdvance: charObj["xadvance"]
+ };
+ }
+
+ //kerning
+ var kerningDict = fnt.kerningDict = {};
+ var kerningLines = fntStr.match(self.KERNING_EXP);
+ if (kerningLines) {
+ for (var i = 0, li = kerningLines.length; i < li; i++) {
+ var kerningObj = self._parseStrToObj(kerningLines[i]);
+ kerningDict[(kerningObj["first"] << 16) | (kerningObj["second"] & 0xffff)] = kerningObj["amount"];
+ }
+ }
+
+ return fnt;
+ },
+
+ /**
+ * Parse Fnt string.
+ * @param fntStr
+ * @param url
+ * @returns {{}}
+ */
+ parseFnt: function (fntStr, url) {
+ var self = this, fnt = {};
+ var headString = fntStr.match(self.FNT_HEAD);
+ if(headString) {
+ var headObj = self._parseStrToObj(headString[0]);
+ if(headObj && headObj.count) {
+ fntStr = fntStr.substr(headString[0].length);
+ var fntFrames = fntStr.split("----");
+ for(var i = 0; i < headObj.count; ++i) {
+ var contentString = fntFrames[i];
+ var frameNameStr = contentString.match(self.FNT_FRAME_NAME);
+ if(frameNameStr) {
+ var frameName = self._parseStrToObj(frameNameStr[0]);
+ if(frameName && frameName.name) {
+ fnt = {};
+ var realFntPathKey = cc.path.join(cc.path.dirname(url), frameName.name);
+ cc.FntFrameCache[realFntPathKey] = this._parseFntContent(fnt, contentString.substr(frameNameStr[0].length), url, {path: frameName.name});
+ }
+ }
+ }
+ }
+ } else {
+ fnt = this._parseFntContent(fnt, fntStr, url);
+ }
+ return fnt;
+ },
+
+ /**
+ * load the fnt
+ * @param realUrl
+ * @param url
+ * @param res
+ * @param cb
+ */
+ load: function (realUrl, url, res, cb) {
+ var self = this;
+ cc.loader.loadTxt(realUrl, function (err, txt) {
+ if (err) return cb(err);
+ cb(null, self.parseFnt(txt, url));
+ });
+ }
+};
+cc.loader.register(["fnt"], _fntLoader);
diff --git a/cocos2d/labels/CCLabelBMFontCanvasRenderCmd.js b/cocos2d/labels/CCLabelBMFontCanvasRenderCmd.js
new file mode 100644
index 0000000000..5861daa30a
--- /dev/null
+++ b/cocos2d/labels/CCLabelBMFontCanvasRenderCmd.js
@@ -0,0 +1,101 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+
+ Use any of these editors to generate BMFonts:
+ http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
+ http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
+ http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
+ http://www.angelcode.com/products/bmfont/ (Free, Windows only)
+ ****************************************************************************/
+
+(function () {
+ cc.LabelBMFont.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ };
+
+ var proto = cc.LabelBMFont.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.LabelBMFont.CanvasRenderCmd;
+
+ proto._updateCharTexture = function (fontChar, rect, key) {
+ if (key === 32) {
+ fontChar.setTextureRect(rect, false, cc.size(0, 0));
+ } else {
+ // updating previous sprite
+ fontChar.setTextureRect(rect, false);
+ // restore to default in case they were modified
+ fontChar.visible = true;
+ }
+ };
+
+ proto._updateCharColorAndOpacity = function (fontChar) {
+ // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on
+ fontChar._displayedColor = this._displayedColor;
+ fontChar._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ fontChar._displayedOpacity = this._displayedOpacity;
+ fontChar._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
+ };
+
+ proto.setTexture = function (texture) {
+ var node = this._node;
+ var locChildren = node._children;
+ var locDisplayedColor = this._displayedColor;
+ for (var i = 0; i < locChildren.length; i++) {
+ var selChild = locChildren[i];
+ var cm = selChild._renderCmd;
+ var childDColor = cm._displayedColor;
+ if (node._texture !== cm._texture && (childDColor.r !== locDisplayedColor.r ||
+ childDColor.g !== locDisplayedColor.g || childDColor.b !== locDisplayedColor.b))
+ continue;
+ selChild.texture = texture;
+ }
+ node._texture = texture;
+ };
+
+ proto._changeTextureColor = function () {
+ var node = this._node;
+ var texture = node._texture,
+ contentSize = texture.getContentSize();
+
+ var oTexture = node._texture,
+ oElement = oTexture.getHtmlElementObj();
+ var disColor = this._displayedColor;
+ var textureRect = cc.rect(0, 0, oElement.width, oElement.height);
+ if (texture && contentSize.width > 0) {
+ if (!oElement)
+ return;
+ var textureToRender = oTexture._generateColorTexture(disColor.r, disColor.g, disColor.b, textureRect);
+ node.setTexture(textureToRender);
+ }
+ };
+
+ proto._updateChildrenDisplayedOpacity = function (locChild) {
+ cc.Node.prototype.updateDisplayedOpacity.call(locChild, this._displayedOpacity);
+ };
+
+ proto._updateChildrenDisplayedColor = function (locChild) {
+ cc.Node.prototype.updateDisplayedColor.call(locChild, this._displayedColor);
+ };
+
+})();
diff --git a/extensions/CCBReader/CCBValue.js b/cocos2d/labels/CCLabelBMFontWebGLRenderCmd.js
similarity index 51%
rename from extensions/CCBReader/CCBValue.js
rename to cocos2d/labels/CCLabelBMFontWebGLRenderCmd.js
index 345cb5fa84..09e18a5f6b 100644
--- a/extensions/CCBReader/CCBValue.js
+++ b/cocos2d/labels/CCLabelBMFontWebGLRenderCmd.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,66 +22,36 @@
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.
- ****************************************************************************/
-
-cc.INT_VALUE = 0;
-
-cc.FLOAT_VALUE = 1;
-
-cc.POINTER_VALUE = 2;
-
-cc.BOOL_VALUE = 3;
-cc.UNSIGNEDCHAR_VALUE = 4;
-
-
-cc.Color3BWapper = cc.Class.extend({
- _color:null,
- ctor:function () {
- this._color = new cc.Color3B(0, 0, 0);
- },
- getColor:function () {
- return this._color;
- }
-});
-
-cc.Color3BWapper.create = function (color) {
- var ret = new cc.Color3BWapper();
- if (ret) {
- ret._color.r = color.r;
- ret._color.g = color.g;
- ret._color.b = color.b;
- }
- return ret;
-};
+ Use any of these editors to generate BMFonts:
+ http://glyphdesigner.71squared.com/ (Commercial, Mac OS X)
+ http://www.n4te.com/hiero/hiero.jnlp (Free, Java)
+ http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java)
+ http://www.angelcode.com/products/bmfont/ (Free, Windows only)
+ ****************************************************************************/
-cc.BuilderValue = cc.Class.extend({
- _value:null,
- _type:0,
+(function () {
+ cc.LabelBMFont.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ };
- getIntValue:function () {
- },
- getFloatValue:function () {
- },
- getBoolValue:function () {
- },
- getByteValue:function () {
- },
- getPointer:function () {
- },
+ var proto = cc.LabelBMFont.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.LabelBMFont.WebGLRenderCmd;
- getValue:function(){
- return this._value;
- }
-});
+ proto.setTexture = function (texture) {
+ this._node.setOpacityModifyRGB(this._node._texture.hasPremultipliedAlpha());
+ };
-cc.BuilderValue.create = function (value) {
- var ret = new cc.BuilderValue();
- if(ret){
- if(typeof(value) == "number"){
+ proto._updateCharTexture = function(fontChar, rect, key, isRotated){
+ // updating previous sprite
+ fontChar.setTextureRect(rect, isRotated);
+ // restore to default in case they were modified
+ fontChar.visible = true;
+ };
- }
- }
- return ret;
-};
+ proto._changeTextureColor = function () {
+ };
+ proto._updateCharColorAndOpacity = function () {
+ };
+})();
diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js
deleted file mode 100644
index 5e8e354ef9..0000000000
--- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js
+++ /dev/null
@@ -1,1407 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/** Layer will receive all the touches at once The onTouchesXXX API will be called
- */
-cc.TOUCH_ALL_AT_ONCE = 0;
-
-/** Layer will receive only one touch at the time. The onTouchXXX API will be called */
-cc.TOUCH_ONE_BY_ONE = 1;
-
-/** cc.Layer is a subclass of cc.Node that implements the TouchEventsDelegate protocol.
- * All features from cc.Node are valid, plus the following new features:
- * It can receive iPhone Touches
- * It can receive Accelerometer input
- * @class
- * @extends cc.Node
- */
-cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{
- _isTouchEnabled:false,
- _isAccelerometerEnabled:false,
- _isKeyboardEnabled:false,
- _touchPriority:0,
- _touchMode:cc.TOUCH_ALL_AT_ONCE,
- _isMouseEnabled:false,
- _mousePriority:0,
-
- ctor: function () {
- cc.Node.prototype.ctor.call(this);
- this._isTouchEnabled = false;
- this._isAccelerometerEnabled = false;
- this._isKeyboardEnabled = false;
- this._touchPriority = 0;
- this._touchMode = cc.TOUCH_ALL_AT_ONCE;
- this._isMouseEnabled = false;
- this._mousePriority = 0;
- },
-
- _initLayer:function () {
- this.setAnchorPoint(cc.p(0.5, 0.5));
- this._ignoreAnchorPointForPosition = true;
-
- var director = cc.Director.getInstance();
- this.setContentSize(director.getWinSize());
- },
-
- /**
- *
- * @return {Boolean}
- */
- init:function () {
- cc.Node.prototype.init.call(this);
- this._initLayer();
- return true;
- },
-
- /**
- * If isTouchEnabled, this method is called onEnter.
- */
- registerWithTouchDispatcher:function () {
- if (this._touchMode === cc.TOUCH_ALL_AT_ONCE)
- cc.registerStandardDelegate(this,this._touchPriority);
- else
- cc.registerTargetedDelegate(this._touchPriority, true, this);
- },
-
- isMouseEnabled:function () {
- return this._isMouseEnabled;
- },
-
- setMouseEnabled:function (enabled) {
- if (this._isMouseEnabled != enabled) {
- this._isMouseEnabled = enabled;
- if (this._running) {
- if (enabled)
- cc.Director.getInstance().getMouseDispatcher().addMouseDelegate(this, this._mousePriority);
- else
- cc.Director.getInstance().getMouseDispatcher().removeMouseDelegate(this);
- }
- }
- },
-
- setMousePriority:function (priority) {
- if (this._mousePriority !== priority) {
- this._mousePriority = priority;
- // Update touch priority with handler
- if (this._isMouseEnabled) {
- this.setMouseEnabled(false);
- this.setMouseEnabled(true);
- }
- }
- },
-
- getMousePriority:function () {
- return this._mousePriority;
- },
-
- /**
- * whether or not it will receive Touch events.
- * You can enable / disable touch events with this property.
- * Only the touches of this node will be affected. This "method" is not propagated to it's children.
- * @return {Boolean}
- */
- isTouchEnabled:function () {
- return this._isTouchEnabled;
- },
-
- /**
- * Enable touch events
- * @param {Boolean} enabled
- */
- setTouchEnabled:function (enabled) {
- if (this._isTouchEnabled !== enabled) {
- this._isTouchEnabled = enabled;
-
- if (this._running) {
- if (enabled) {
- this.registerWithTouchDispatcher();
- } else {
- // have problems?
- cc.unregisterTouchDelegate(this);
- }
- }
- }
- },
-
- /** returns the priority of the touch event handler
- * @return {Number}
- */
- getTouchPriority:function () {
- return this._touchPriority;
- },
-
- /** Sets the touch event handler priority. Default is 0.
- * @param {Number} priority
- */
- setTouchPriority:function (priority) {
- if (this._touchPriority !== priority) {
- this._touchPriority = priority;
- // Update touch priority with handler
- if (this._isTouchEnabled) {
- this.setTouchEnabled(false);
- this.setTouchEnabled(true);
- }
- }
- },
-
- /** returns the touch mode.
- * @return {Number}
- */
- getTouchMode:function () {
- return this._touchMode;
- },
-
- /** Sets the touch mode.
- * @param {Number} mode
- */
- setTouchMode:function (mode) {
- if (this._touchMode !== mode) {
- this._touchMode = mode;
- // update the mode with handler
- if (this._isTouchEnabled) {
- this.setTouchEnabled(false);
- this.setTouchEnabled(true);
- }
- }
- },
-
- /**
- * whether or not it will receive Accelerometer events
- * You can enable / disable accelerometer events with this property.
- * @return {Boolean}
- */
- isAccelerometerEnabled:function () {
- return this._isAccelerometerEnabled;
- },
-
- /**
- * isAccelerometerEnabled setter
- * @param {Boolean} enabled
- */
- setAccelerometerEnabled:function (enabled) {
- if (enabled !== this._isAccelerometerEnabled) {
- this._isAccelerometerEnabled = enabled;
-
- if (this._running) {
- var director = cc.Director.getInstance();
- if (enabled) {
- director.getAccelerometer().setDelegate(this);
- } else {
- director.getAccelerometer().setDelegate(null);
- }
- }
- }
- },
-
- /**
- * accelerometerInterval setter
- * @param {Number} interval
- */
- setAccelerometerInterval:function (interval) {
- if (this._isAccelerometerEnabled) {
- cc.Director.getInstance().getAccelerometer().setAccelerometerInterval(interval);
- }
- },
-
- onAccelerometer:function (accelerationValue) {
- cc.Assert(false, "Layer#onAccelerometer override me");
- },
-
- /**
- * whether or not it will receive keyboard events
- * You can enable / disable accelerometer events with this property.
- * it's new in cocos2d-x
- * @return {Boolean}
- */
- isKeyboardEnabled:function () {
- return this._isKeyboardEnabled;
- },
-
- /**
- * Enable Keyboard interaction
- * @param {Boolean} enabled
- */
- setKeyboardEnabled:function (enabled) {
- if (enabled !== this._isKeyboardEnabled) {
- this._isKeyboardEnabled = enabled;
- if (this._running) {
- var director = cc.Director.getInstance();
- if (enabled) {
- director.getKeyboardDispatcher().addDelegate(this);
- } else {
- director.getKeyboardDispatcher().removeDelegate(this);
- }
- }
- }
- },
-
- /**
- * This is run when ever a layer just become visible
- */
- onEnter:function () {
- var director = cc.Director.getInstance();
- // register 'parent' nodes first
- // since events are propagated in reverse order
- if (this._isTouchEnabled)
- this.registerWithTouchDispatcher();
-
- // then iterate over all the children
- cc.Node.prototype.onEnter.call(this);
-
- // add this layer to concern the Accelerometer Sensor
- if (this._isAccelerometerEnabled)
- director.getAccelerometer().setDelegate(this);
-
- // add this layer to concern the kaypad msg
- if (this._isKeyboardEnabled)
- director.getKeyboardDispatcher().addDelegate(this);
-
- if (this._isMouseEnabled)
- director.getMouseDispatcher().addMouseDelegate(this, this._mousePriority);
- },
-
- /**
- * @function
- */
- onExit:function () {
- var director = cc.Director.getInstance();
- if (this._isTouchEnabled)
- cc.unregisterTouchDelegate(this);
-
- // remove this layer from the delegates who concern Accelerometer Sensor
- if (this._isAccelerometerEnabled)
- director.getAccelerometer().setDelegate(null);
-
- // remove this layer from the delegates who concern the kaypad msg
- if (this._isKeyboardEnabled)
- director.getKeyboardDispatcher().removeDelegate(this);
-
- if (this._isMouseEnabled)
- director.getMouseDispatcher().removeMouseDelegate(this);
-
- cc.Node.prototype.onExit.call(this);
- },
-
- /**
- * this is called when ever a layer is a child of a scene that just finished a transition
- */
- onEnterTransitionDidFinish:function () {
- if (this._isAccelerometerEnabled) {
- cc.Director.getInstance().getAccelerometer().setDelegate(this);
- }
- cc.Node.prototype.onEnterTransitionDidFinish.call(this);
- },
-
- // ---------------------CCTouchDelegate interface------------------------------
-
- /**
- * default implements are used to call script callback if exist
- * you must override these touch functions if you wish to utilize them
- * @param {cc.Touch} touch
- * @param {event} event
- * @return {Boolean}
- */
- onTouchBegan:function (touch, event) {
- cc.Assert(false, "Layer#onTouchBegan override me");
- return true;
- },
-
- /**
- * callback when a touch event moved
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchMoved:function (touch, event) {
- },
-
- /**
- * callback when a touch event finished
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchEnded:function (touch, event) {
- },
-
- /**
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchCancelled:function (touch, event) {
- },
-
- /**
- * Touches is the same as Touch, except this one can handle multi-touch
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchesBegan:function (touch, event) {
- },
-
- /**
- * when a touch moved
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchesMoved:function (touch, event) {
- },
-
- /**
- * when a touch finished
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchesEnded:function (touch, event) {
- },
-
- /**
- * @param touch
- * @param event
- */
- onTouchesCancelled:function (touch, event) {
- },
-
- // ---------------------CCMouseEventDelegate interface------------------------------
-
- /**
- * called when the "mouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseMoved" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseMoved:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseUp:function (event) {
- return false;
- },
-
- //right
- /**
- * called when the "rightMouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onRightMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "rightMouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onRightMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "rightMouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onRightMouseUp:function (event) {
- return false;
- },
-
- //other
- /**
- * called when the "otherMouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onOtherMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "otherMouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onOtherMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "otherMouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onOtherMouseUp:function (event) {
- return false;
- },
-
- //scroll wheel
- /**
- * called when the "scrollWheel" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onScrollWheel:function (event) {
- return false;
- },
-
- // enter / exit
- /**
- * called when the "mouseEntered" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param theEvent
- * @return {Boolean}
- */
- onMouseEntered:function (theEvent) {
- return false;
- },
-
- /**
- * called when the "mouseExited" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param theEvent
- * @return {Boolean}
- */
- onMouseExited:function (theEvent) {
- return false;
- },
-
- // ---------------------CCKeyboardDelegate interface------------------------------
-
- /**
- * Call back when a key is pressed down
- * @param {Number} keyCode
- * @example
- * // example
- * if(keyCode == cc.KEY.w){}
- */
- onKeyDown:function (keyCode) {
- },
-
- /**
- * Call back when a key is released
- * @param {Number} keyCode
- * @example
- * // example
- * if(keyCode == cc.KEY.w){}
- */
- onKeyUp:function (keyCode) {
- }
-});
-
-/**
- * creates a layer
- * @example
- * // Example
- * var myLayer = cc.Layer.create();
- * //Yes! it's that simple
- * @return {cc.Layer|Null}
- */
-cc.Layer.create = function () {
- var ret = new cc.Layer();
- if (ret && ret.init())
- return ret;
- return null;
-};
-
-/**
- *
- * CCLayerRGBA is a subclass of CCLayer that implements the CCRGBAProtocol protocol using a solid color as the background.
- * All features from CCLayer are valid, plus the following new features that propagate into children that conform to the CCRGBAProtocol:
- * - opacity
- * - RGB colors
- *
- * @class
- * @extends cc.Layer
- */
-cc.LayerRGBA = cc.Layer.extend(/** @lends cc.LayerRGBA# */{
- RGBAProtocol:true,
- _displayedOpacity: 0,
- _realOpacity: 0,
- _displayedColor: null,
- _realColor: null,
- _cascadeOpacityEnabled: false,
- _cascadeColorEnabled: false,
-
- ctor: function () {
- cc.Layer.prototype.ctor.call(this);
- this.RGBAProtocol = true;
- this._displayedOpacity = 255;
- this._realOpacity = 255;
- this._displayedColor = cc.white();
- this._realColor = cc.white();
- this._cascadeOpacityEnabled = false;
- this._cascadeColorEnabled = false;
- },
-
- init: function () {
- if(cc.Layer.prototype.init.call(this)){
- this.setCascadeOpacityEnabled(false);
- this.setCascadeColorEnabled(false);
-
- return true;
- }
- return false;
- },
-
- /**
- *
- * @returns {number}
- */
- getOpacity: function () {
- return this._realOpacity;
- },
-
- /**
- *
- * @returns {number}
- */
- getDisplayedOpacity: function () {
- return this._displayedOpacity;
- },
-
- /**
- * Override synthesized setOpacity to recurse items
- * @param {Number} opacity
- */
- setOpacity: function (opacity) {
- this._displayedOpacity = this._realOpacity = opacity;
-
- if( this._cascadeOpacityEnabled ) {
- var parentOpacity = 255;
- var locParent = this._parent;
- if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled())
- parentOpacity = locParent.getDisplayedOpacity();
-
- this.updateDisplayedOpacity(parentOpacity);
- }
- },
-
- /**
- *
- * @param {Number} parentOpacity
- */
- updateDisplayedOpacity: function (parentOpacity) {
- this._displayedOpacity = 0|(this._realOpacity * parentOpacity/255.0);
-
- if (this._cascadeOpacityEnabled){
- var locChildren = this._children;
- for(var i = 0; i< locChildren.length; i++){
- var selItem = locChildren[i];
- if(selItem && selItem.RGBAProtocol)
- selItem.updateDisplayedOpacity(this._displayedOpacity);
- }
- }
- },
-
- isCascadeOpacityEnabled: function () {
- return this._cascadeOpacityEnabled;
- },
-
- setCascadeOpacityEnabled: function (cascadeOpacityEnabled) {
- this._cascadeOpacityEnabled = cascadeOpacityEnabled;
- },
-
- getColor: function () {
- var locRealColor = this._realColor;
- return cc.c3b(locRealColor.r, locRealColor.g, locRealColor.b);
- },
-
- getDisplayedColor: function () {
- var locDisplayedColor = this._displayedColor;
- return cc.c3b(locDisplayedColor.r, locDisplayedColor.g, locDisplayedColor.b);
- },
-
- setColor: function (color) {
- var locDisplayed = this._displayedColor, locRealColor = this._realColor;
- locDisplayed.r = locRealColor.r = color.r;
- locDisplayed.g = locRealColor.g = color.g;
- locDisplayed.b = locRealColor.b = color.b;
-
- if (this._cascadeColorEnabled){
- var parentColor;
- var locParent = this._parent;
- if (locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled())
- parentColor = locParent.getDisplayedColor();
- else
- parentColor = cc.white();
- this.updateDisplayedColor(parentColor);
- }
- },
-
- updateDisplayedColor: function (parentColor) {
- var locDisplayedColor = this._displayedColor, locRealColor = this._realColor;
- locDisplayedColor.r = 0|(locRealColor.r * parentColor.r/255.0);
- locDisplayedColor.g = 0|(locRealColor.g * parentColor.g/255.0);
- locDisplayedColor.b = 0|(locRealColor.b * parentColor.b/255.0);
-
- if (this._cascadeColorEnabled){
- var locChildren = this._children;
- for(var i = 0; i < locChildren.length; i++){
- var selItem = locChildren[i];
- if(selItem && selItem.RGBAProtocol)
- selItem.updateDisplayedColor(locDisplayedColor);
- }
- }
- },
-
- isCascadeColorEnabled: function () {
- return this._cascadeColorEnabled;
- },
-
- setCascadeColorEnabled: function (cascadeColorEnabled) {
- this._cascadeColorEnabled = cascadeColorEnabled;
- },
-
- setOpacityModifyRGB: function (bValue) {
- },
-
- isOpacityModifyRGB: function () {
- return false;
- }
-});
-
-/**
- *
- * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.
- * All features from CCLayer are valid, plus the following new features:
- *
- *
- * @class
- * @extends cc.Layer
- */
-cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{
- _blendFunc:null,
-
- /**
- * blendFunc getter
- * @return {cc.BlendFunc}
- */
- getBlendFunc:function () {
- return this._blendFunc;
- },
-
- /**
- * change width and height in Points
- * @param {Number} w width
- * @param {Number} h height
- */
- changeWidthAndHeight:function (w, h) {
- this.setContentSize(cc.size(w, h));
- },
-
- /**
- * change width in Points
- * @param {Number} w width
- */
- changeWidth:function (w) {
- this.setContentSize(cc.size(w, this._contentSize.height));
- },
-
- /**
- * change height in Points
- * @param {Number} h height
- */
- changeHeight:function (h) {
- this.setContentSize(cc.size(this._contentSize.width, h));
- },
-
- /**
- * set OpacityModifyRGB of cc.LayerColor
- * @param {Boolean} value
- */
- setOpacityModifyRGB:function (value) {
- },
-
- /**
- * is OpacityModifyRGB
- * @return {Boolean}
- */
- isOpacityModifyRGB:function () {
- return false;
- },
-
- setColor:function(color){
- cc.LayerRGBA.prototype.setColor.call(this, color);
- this._updateColor();
- },
-
- setOpacity:function(opacity){
- cc.LayerRGBA.prototype.setOpacity.call(this, opacity);
- this._updateColor();
- },
-
- _isLighterMode:false,
- _squareVertices:null,
- _squareColors:null,
- _verticesFloat32Buffer:null,
- _colorsUint8Buffer:null,
- _squareVerticesAB:null,
- _squareColorsAB:null,
-
- _ctorForCanvas: function () {
- cc.LayerRGBA.prototype.ctor.call(this);
- this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
- },
-
- _ctorForWebGL: function () {
- cc.LayerRGBA.prototype.ctor.call(this);
- this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
-
- this._squareVerticesAB = new ArrayBuffer(32);
- this._squareColorsAB = new ArrayBuffer(64);
-
- var locSquareVerticesAB = this._squareVerticesAB, locSquareColorsAB = this._squareColorsAB;
- var locVertex2FLen = cc.Vertex2F.BYTES_PER_ELEMENT, locColor4FLen = cc.Color4F.BYTES_PER_ELEMENT;
- this._squareVertices = [new cc.Vertex2F(0, 0, locSquareVerticesAB, 0),
- new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen),
- new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 2),
- new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 3)];
- this._squareColors = [new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, 0),
- new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen),
- new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 2),
- new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 3)];
- this._verticesFloat32Buffer = cc.renderContext.createBuffer();
- this._colorsUint8Buffer = cc.renderContext.createBuffer();
- },
-
- /**
- * blendFunc setter
- * @param {Number} src
- * @param {Number} dst
- */
- setBlendFunc:function (src, dst) {
- if (arguments.length == 1)
- this._blendFunc = src;
- else
- this._blendFunc = {src:src, dst:dst};
- if(cc.renderContextType === cc.CANVAS)
- this._isLighterMode = (this._blendFunc && (this._blendFunc.src == 1) && (this._blendFunc.dst == 771));
- },
-
- /**
- * @param {cc.Color4B} [color=]
- * @param {Number} [width=]
- * @param {Number} [height=]
- * @return {Boolean}
- */
- init:function (color, width, height) {
- if(!cc.Layer.prototype.init.call(this))
- return false;
-
- if(cc.renderContextType !== cc.CANVAS)
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR));
-
- var winSize = cc.Director.getInstance().getWinSize();
- color = color || new cc.Color4B(0, 0, 0, 255);
- width = width || winSize.width;
- height = height || winSize.height;
-
- var locDisplayedColor = this._displayedColor;
- locDisplayedColor.r = color.r;
- locDisplayedColor.g = color.g;
- locDisplayedColor.b = color.b;
-
- var locRealColor = this._realColor;
- locRealColor.r = color.r;
- locRealColor.g = color.g;
- locRealColor.b = color.b;
-
- this._displayedOpacity = color.a;
- this._realOpacity = color.a;
-
- this.setContentSize(cc.size(width, height));
- this._updateColor();
- return true;
- },
-
- /**
- * override contentSize
- * @param {cc.Size} size
- */
- setContentSize:null,
-
- _setContentSizeForWebGL:function (size) {
- var locSquareVertices = this._squareVertices;
- locSquareVertices[1].x = size.width;
- locSquareVertices[2].y = size.height;
- locSquareVertices[3].x = size.width;
- locSquareVertices[3].y = size.height;
- this._bindLayerVerticesBufferData();
- cc.Layer.prototype.setContentSize.call(this,size);
- },
-
- _updateColor:null,
-
- _updateColorForCanvas:function () {
- },
-
- _updateColorForWebGL:function () {
- var locDisplayedColor = this._displayedColor;
- var locDisplayedOpacity = this._displayedOpacity, locSquareColors = this._squareColors;
- for (var i = 0; i < 4; i++) {
- locSquareColors[i].r = locDisplayedColor.r / 255;
- locSquareColors[i].g = locDisplayedColor.g / 255;
- locSquareColors[i].b = locDisplayedColor.b / 255;
- locSquareColors[i].a = locDisplayedOpacity / 255;
- }
- this._bindLayerColorsBufferData();
- },
-
- _bindLayerVerticesBufferData:function () {
- var glContext = cc.renderContext;
- glContext.bindBuffer(glContext.ARRAY_BUFFER, this._verticesFloat32Buffer);
- glContext.bufferData(glContext.ARRAY_BUFFER, this._squareVerticesAB , glContext.STATIC_DRAW);
- },
-
- _bindLayerColorsBufferData:function () {
- var glContext = cc.renderContext;
- glContext.bindBuffer(glContext.ARRAY_BUFFER, this._colorsUint8Buffer);
- glContext.bufferData(glContext.ARRAY_BUFFER, this._squareColorsAB, glContext.STATIC_DRAW);
- },
-
- /**
- * renders the layer
- * @param {CanvasRenderingContext2D|Null} ctx
- */
- draw:null,
-
- _drawForCanvas:function (ctx) {
- var context = ctx || cc.renderContext;
-
- var locContentSize = this.getContentSize(), locEGLViewer = cc.EGLView.getInstance();
-
- var locDisplayedColor = this._displayedColor;
-
- context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + ","
- + (0 | locDisplayedColor.b) + "," + this._displayedOpacity / 255 + ")";
- context.fillRect(0, 0, locContentSize.width * locEGLViewer.getScaleX(), -locContentSize.height * locEGLViewer.getScaleY());
-
- cc.g_NumberOfDraws++;
- },
-
- _drawForWebGL:function (ctx) {
- var context = ctx || cc.renderContext;
-
- cc.NODE_DRAW_SETUP(this);
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR);
-
- //
- // Attributes
- //
- context.bindBuffer(context.ARRAY_BUFFER, this._verticesFloat32Buffer);
- context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, context.FLOAT, false, 0, 0);
-
- context.bindBuffer(context.ARRAY_BUFFER, this._colorsUint8Buffer);
- context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.FLOAT, false, 0, 0);
-
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
- context.drawArrays(context.TRIANGLE_STRIP, 0, 4);
- }
-});
-
-if(cc.Browser.supportWebGL){
- cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForWebGL;
- cc.LayerColor.prototype.setContentSize = cc.LayerColor.prototype._setContentSizeForWebGL;
- cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForWebGL;
- cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForWebGL;
-} else {
- cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForCanvas;
- cc.LayerColor.prototype.setContentSize = cc.LayerRGBA.prototype.setContentSize;
- cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForCanvas;
- cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForCanvas;
-}
-
-
-/**
- * creates a cc.Layer with color, width and height in Points
- * @param {cc.Color4B} color
- * @param {Number|Null} [width=]
- * @param {Number|Null} [height=]
- * @return {cc.LayerColor}
- * @example
- * // Example
- * //Create a yellow color layer as background
- * var yellowBackground = cc.LayerColor.create(cc.c4b(255,255,0,255));
- * //If you didnt pass in width and height, it defaults to the same size as the canvas
- *
- * //create a yellow box, 200 by 200 in size
- * var yellowBox = cc.LayerColor.create(cc.c4b(255,255,0,255), 200, 200);
- */
-cc.LayerColor.create = function (color, width, height) {
- var ret = new cc.LayerColor();
- switch (arguments.length) {
- case 0:
- ret.init();
- break;
- case 1:
- ret.init(color);
- break;
- case 3:
- ret.init(color, width, height);
- break;
- default :
- ret.init();
- break;
- }
- return ret;
-};
-
-/**
- *
- * CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.
- *
- * All features from cc.LayerColor are valid, plus the following new features:
- *
direction
- * final color
- * interpolation mode
- *
- * Color is interpolated between the startColor and endColor along the given
- * vector (starting at the origin, ending at the terminus). If no vector is
- * supplied, it defaults to (0, -1) -- a fade from top to bottom.
- *
- * If 'compressedInterpolation' is disabled, you will not see either the start or end color for
- * non-cardinal vectors; a smooth gradient implying both end points will be still
- * be drawn, however.
- *
- * If 'compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient.
- *
- * @class
- * @extends cc.LayerColor
- */
-cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{
- _startColor:null,
- _endColor:null,
- _startOpacity:null,
- _endOpacity:null,
- _alongVector:null,
- _compressedInterpolation:false,
- _gradientStartPoint:null,
- _gradientEndPoint:null,
-
- /**
- * Constructor
- * @function
- */
- ctor:function () {
- cc.LayerColor.prototype.ctor.call(this);
-
- this._startColor = new cc.Color3B(0, 0, 0);
- this._endColor = new cc.Color3B(0, 0, 0);
- this._alongVector = cc.p(0, -1);
- this._startOpacity = 255;
- this._endOpacity = 255;
- this._gradientStartPoint = cc.p(0, 0);
- this._gradientEndPoint = cc.p(0, 0);
- },
-
- /**
- * override contentSize
- * @param {cc.Size} size
- */
- setContentSize:function(size){
- cc.LayerColor.prototype.setContentSize.call(this,size);
- this._updateColor();
- },
-
- /**
- * get the starting color
- * @return {cc.Color3B}
- */
- getStartColor:function () {
- return this._realColor;
- },
-
- /**
- * set the starting color
- * @param {cc.Color3B} color
- * @example
- * // Example
- * myGradientLayer.setStartColor(cc.c3b(255,0,0));
- * //set the starting gradient to red
- */
- setStartColor:function (color) {
- this.setColor(color);
- },
-
- /**
- * set the end gradient color
- * @param {cc.Color3B} color
- * @example
- * // Example
- * myGradientLayer.setEndColor(cc.c3b(255,0,0));
- * //set the ending gradient to red
- */
- setEndColor:function (color) {
- this._endColor = color;
- this._updateColor();
- },
-
- /**
- * get the end color
- * @return {cc.Color3B}
- */
- getEndColor:function () {
- return this._endColor;
- },
-
- /**
- * set starting gradient opacity
- * @param {Number} o from 0 to 255, 0 is transparent
- */
- setStartOpacity:function (o) {
- this._startOpacity = o;
- this._updateColor();
- },
-
- /**
- * get the starting gradient opacity
- * @return {Number}
- */
- getStartOpacity:function () {
- return this._startOpacity;
- },
-
- /**
- * set the end gradient opacity
- * @param {Number} o
- */
- setEndOpacity:function (o) {
- this._endOpacity = o;
- this._updateColor();
- },
-
- /**
- * get the end gradient opacity
- * @return {Number}
- */
- getEndOpacity:function () {
- return this._endOpacity;
- },
-
- /**
- * set vector
- * @param {cc.Point} Var
- */
- setVector:function (Var) {
- this._alongVector.x = Var.x;
- this._alongVector.y = Var.y;
- this._updateColor();
- },
-
- /**
- * @return {cc.Point}
- */
- getVector:function () {
- return cc.p(this._alongVector.x, this._alongVector.y);
- },
-
- /** is Compressed Interpolation
- * @return {Boolean}
- */
- isCompressedInterpolation:function () {
- return this._compressedInterpolation;
- },
-
- /**
- * @param {Boolean} compress
- */
- setCompressedInterpolation:function (compress) {
- this._compressedInterpolation = compress;
- this._updateColor();
- },
-
- /**
- * @param {cc.Color4B} start starting color
- * @param {cc.Color4B} end
- * @param {cc.Point|Null} v
- * @return {Boolean}
- */
- init:function (start, end, v) {
- start = start || cc.c4(0,0,0,255);
- end = end || cc.c4(0,0,0,255);
- v = v || cc.p(0, -1);
-
- // Initializes the CCLayer with a gradient between start and end in the direction of v.
- var locStartColor = this._startColor, locEndColor = this._endColor;
- locStartColor.r = start.r;
- locStartColor.g = start.g;
- locStartColor.b = start.b;
- this._startOpacity = start.a;
-
- locEndColor.r = end.r;
- locEndColor.g = end.g;
- locEndColor.b = end.b;
- this._endOpacity = end.a;
-
- this._alongVector = v;
- this._compressedInterpolation = true;
-
- cc.LayerColor.prototype.init.call(this,cc.c4b(start.r, start.g, start.b, 255));
- return true;
- },
-
- draw:function (ctx) {
- if (cc.renderContextType === cc.WEBGL){
- cc.LayerColor.prototype.draw.call(this, ctx);
- return;
- }
-
- var context = ctx || cc.renderContext;
- if (this._isLighterMode)
- context.globalCompositeOperation = 'lighter';
-
- context.save();
- var locEGLViewer = cc.EGLView.getInstance();
- var tWidth = this.getContentSize().width * locEGLViewer.getScaleX();
- var tHeight = this.getContentSize().height * locEGLViewer.getScaleY();
- var tGradient = context.createLinearGradient(this._gradientStartPoint.x, this._gradientStartPoint.y,
- this._gradientEndPoint.x, this._gradientEndPoint.y);
- var locDisplayedColor = this._displayedColor;
- var locEndColor = this._endColor;
- tGradient.addColorStop(0, "rgba(" + Math.round(locDisplayedColor.r) + "," + Math.round(locDisplayedColor.g) + ","
- + Math.round(locDisplayedColor.b) + "," + (this._startOpacity / 255).toFixed(4) + ")");
- tGradient.addColorStop(1, "rgba(" + Math.round(locEndColor.r) + "," + Math.round(locEndColor.g) + ","
- + Math.round(locEndColor.b) + "," + (this._endOpacity / 255).toFixed(4) + ")");
- context.fillStyle = tGradient;
- context.fillRect(0, 0, tWidth, -tHeight);
-
- if (this._rotation != 0)
- context.rotate(this._rotationRadians);
- context.restore();
- },
-
- _updateColor:function () {
- var locAlongVector = this._alongVector;
- if (cc.renderContextType === cc.CANVAS) {
- var tWidth = this.getContentSize().width * 0.5;
- var tHeight = this.getContentSize().height * 0.5;
-
- this._gradientStartPoint = cc.p(tWidth * (-locAlongVector.x) + tWidth, tHeight * locAlongVector.y - tHeight);
- this._gradientEndPoint = cc.p(tWidth * locAlongVector.x + tWidth, tHeight * (-locAlongVector.y) - tHeight);
- } else {
- var h = cc.pLength(locAlongVector);
- if (h === 0)
- return;
-
- var c = Math.sqrt(2.0);
- var u = cc.p(locAlongVector.x / h, locAlongVector.y / h);
-
- // Compressed Interpolation mode
- if (this._compressedInterpolation) {
- var h2 = 1 / ( Math.abs(u.x) + Math.abs(u.y) );
- u = cc.pMult(u, h2 * c);
- }
-
- var opacityf = this._displayedOpacity / 255.0;
- var locDisplayedColor = this._displayedColor, locEndColor = this._endColor;
- var S = { r: locDisplayedColor.r / 255, g: locDisplayedColor.g / 255, b: locDisplayedColor.b / 255, a: (this._startOpacity * opacityf) / 255};
- var E = {r: locEndColor.r / 255, g: locEndColor.g / 255, b: locEndColor.b / 255, a: (this._endOpacity * opacityf) / 255};
-
- // (-1, -1)
- var locSquareColors = this._squareColors;
- var locSquareColor0 = locSquareColors[0], locSquareColor1 = locSquareColors[1], locSquareColor2 = locSquareColors[2],locSquareColor3 = locSquareColors[3];
- locSquareColor0.r = ((E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0 * c))));
- locSquareColor0.g = ((E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0 * c))));
- locSquareColor0.b = ((E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0 * c))));
- locSquareColor0.a = ((E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0 * c))));
- // (1, -1)
- locSquareColor1.r = ((E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0 * c))));
- locSquareColor1.g = ((E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0 * c))));
- locSquareColor1.b = ((E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0 * c))));
- locSquareColor1.a = ((E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0 * c))));
- // (-1, 1)
- locSquareColor2.r = ((E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0 * c))));
- locSquareColor2.g = ((E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0 * c))));
- locSquareColor2.b = ((E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0 * c))));
- locSquareColor2.a = ((E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0 * c))));
- // (1, 1)
- locSquareColor3.r = ((E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0 * c))));
- locSquareColor3.g = ((E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0 * c))));
- locSquareColor3.b = ((E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0 * c))));
- locSquareColor3.a = ((E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0 * c))));
-
- this._bindLayerColorsBufferData();
- }
- }
-});
-
-/**
- * creates a gradient layer
- * @param {cc.Color3B} start starting color
- * @param {cc.Color3B} end ending color
- * @param {cc.Point|Null} v
- * @return {cc.LayerGradient}
- */
-cc.LayerGradient.create = function (start, end, v) {
- var layer = new cc.LayerGradient();
- switch (arguments.length) {
- case 2:
- /** Creates a full-screen CCLayer with a gradient between start and end. */
- if (layer && layer.init(start, end))
- return layer;
- break;
- case 3:
- /** Creates a full-screen CCLayer with a gradient between start and end in the direction of v. */
- if (layer && layer.init(start, end, v))
- return layer;
- break;
- case 0:
- if (layer && layer.init())
- return layer;
- break;
- default:
- throw "Arguments error ";
- break;
- }
- return null;
-};
-
-/**
- * CCMultipleLayer is a CCLayer with the ability to multiplex it's children.
- * Features:
- * - It supports one or more children
- * - Only one children will be active a time
- * @class
- * @extends cc.Layer
- */
-cc.LayerMultiplex = cc.Layer.extend(/** @lends cc.LayerMultiplex# */{
- _enabledLayer:0,
- _layers:null,
-
- /**
- * @param {cc.Layer} layer
- * @deprecated merged with initWithLayers
- * @return {Boolean}
- */
- initWithLayer:function (layer) {
- this._layers = [];
- this._layers.push(layer);
- this._enabledLayer = 0;
- this.addChild(layer);
- return true;
- },
-
- /**
- * @param {Array} args an array of cc.Layer
- * @return {Boolean}
- */
- initWithLayers:function (args) {
- this._layers = args;
- this._enabledLayer = 0;
- this.addChild(this._layers[this._enabledLayer]);
- return true;
- },
-
- /**
- * switches to a certain layer indexed by n.
- * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
- * @param {Number} n the layer index to switch to
- */
- switchTo:function (n) {
- cc.Assert(n < this._layers.length, "Invalid index in MultiplexLayer switchTo message");
-
- this.removeChild(this._layers[this._enabledLayer], true);
-
- this._enabledLayer = n;
-
- this.addChild(this._layers[n]);
- },
-
- /** release the current layer and switches to another layer indexed by n.
- * The current (old) layer will be removed from it's parent with 'cleanup:YES'.
- * @param {Number} n the layer index to switch to
- */
- switchToAndReleaseMe:function (n) {
- cc.Assert(n < this._layers.count(), "Invalid index in MultiplexLayer switchTo message");
-
- this.removeChild(this._layers[this._enabledLayer], true);
-
- //[layers replaceObjectAtIndex:_enabledLayer withObject:[NSNull null]];
- this._layers[this._enabledLayer] = null;
-
- this._enabledLayer = n;
-
- this.addChild(this._layers[n]);
- },
-
- /**
- * @param {cc.Layer} layer
- */
- addLayer:function (layer) {
- cc.Assert(this._layers, "cc.Layer addLayer");
- this._layers.push(layer);
- }
-});
-
-/**
- * creates a cc.LayerMultiplex with one or more layers using a variable argument list.
- * @return {cc.LayerMultiplex|Null}
- * @example
- * // Example
- * var multiLayer = cc.LayerMultiple.create(layer1, layer2, layer3);//any number of layers
- */
-cc.LayerMultiplex.create = function (/*Multiple Arguments*/) {
- if((arguments.length > 0) && (arguments[arguments.length-1] == null))
- cc.log("parameters should not be ending with null in Javascript");
- var multiplexLayer = new cc.LayerMultiplex();
- if (multiplexLayer.initWithLayers(arguments)) {
- return multiplexLayer;
- }
- return null;
-};
-
diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js
deleted file mode 100644
index dec51e86ce..0000000000
--- a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js
+++ /dev/null
@@ -1,1686 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-/**
- * A tag constant for identifying fade scenes
- * @constant
- * @type Number
- */
-cc.SCENE_FADE = 4208917214;
-
-/**
- * cc.TransitionEaseScene can ease the actions of the scene protocol.
- * @class
- * @extends cc.Class
- */
-cc.TransitionEaseScene = cc.Class.extend(/** @lends cc.TransitionEaseScene# */{
- /**
- * returns the Ease action that will be performed on a linear action.
- */
- easeActionWithAction:function () {
- }
-});
-
-/**
- * horizontal orientation Type where the Left is nearer
- * @constant
- * @type Number
- */
-cc.TRANSITION_ORIENTATION_LEFT_OVER = 0;
-/**
- * horizontal orientation type where the Right is nearer
- * @constant
- * @type Number
- */
-cc.TRANSITION_ORIENTATION_RIGHT_OVER = 1;
-/**
- * vertical orientation type where the Up is nearer
- * @constant
- * @type Number
- */
-cc.TRANSITION_ORIENTATION_UP_OVER = 0;
-/**
- * vertical orientation type where the Bottom is nearer
- * @constant
- * @type Number
- */
-cc.TRANSITION_ORIENTATION_DOWN_OVER = 1;
-
-/**
- * @class
- * @extends cc.Scene
- */
-cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{
- _inScene:null,
- _outScene:null,
- _duration:null,
- _isInSceneOnTop:false,
- _isSendCleanupToScene:false,
-
- //private
- _setNewScene:function (dt) {
- this.unschedule(this._setNewScene);
- // Before replacing, save the "send cleanup to scene"
- var director = cc.Director.getInstance();
- this._isSendCleanupToScene = director.isSendCleanupToScene();
- director.replaceScene(this._inScene);
-
- // enable events while transitions
- director.getTouchDispatcher().setDispatchEvents(true);
- // issue #267
- this._outScene.setVisible(true);
- },
-
- //protected
- _sceneOrder:function () {
- this._isInSceneOnTop = true;
- },
-
- /**
- * stuff gets drawn here
- */
- draw:function () {
- if (this._isInSceneOnTop) {
- this._outScene.visit();
- this._inScene.visit();
- } else {
- this._inScene.visit();
- this._outScene.visit();
- }
- },
-
- /**
- * custom onEnter
- */
- onEnter:function () {
- cc.Node.prototype.onEnter.call(this);
-
- // disable events while transitions
- cc.Director.getInstance().getTouchDispatcher().setDispatchEvents(false);
-
- // outScene should not receive the onEnter callback
- // only the onExitTransitionDidStart
- this._outScene.onExitTransitionDidStart();
-
- this._inScene.onEnter();
- },
-
- /**
- * custom onExit
- */
- onExit:function () {
- cc.Node.prototype.onExit.call(this);
-
- // enable events while transitions
- cc.Director.getInstance().getTouchDispatcher().setDispatchEvents(true);
-
- this._outScene.onExit();
-
- // _inScene should not receive the onEnter callback
- // only the onEnterTransitionDidFinish
- this._inScene.onEnterTransitionDidFinish();
- },
-
- /**
- * custom cleanup
- */
- cleanup:function () {
- cc.Node.prototype.cleanup.call(this);
-
- if (this._isSendCleanupToScene)
- this._outScene.cleanup();
- },
-
- /**
- * initializes a transition with duration and incoming scene
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene a scene to transit to
- * @return {Boolean} return false if error
- */
- initWithDuration:function (t, scene) {
- cc.Assert(scene != null, "CCTransitionScene.initWithDuration() Argument scene must be non-nil");
-
- if (this.init()) {
- this._duration = t;
- this.setAnchorPoint(cc.p(0, 0));
- this.setPosition(0, 0);
- // retain
- this._inScene = scene;
- this._outScene = cc.Director.getInstance().getRunningScene();
- if (!this._outScene) {
- this._outScene = cc.Scene.create();
- this._outScene.init();
- }
-
- cc.Assert(this._inScene != this._outScene, "CCTransitionScene.initWithDuration() Incoming scene must be different from the outgoing scene");
-
- this._sceneOrder();
-
- return true;
- } else {
- return false;
- }
- },
-
- /**
- * called after the transition finishes
- */
- finish:function () {
- // clean up
- this._inScene.setVisible(true);
- this._inScene.setPosition(0, 0);
- this._inScene.setScale(1.0);
- this._inScene.setRotation(0.0);
- if(cc.renderContextType === cc.WEBGL)
- this._inScene.getCamera().restore();
-
- this._outScene.setVisible(false);
- this._outScene.setPosition(0, 0);
- this._outScene.setScale(1.0);
- this._outScene.setRotation(0.0);
- if(cc.renderContextType === cc.WEBGL)
- this._outScene.getCamera().restore();
-
- //[self schedule:@selector(setNewScene:) interval:0];
- this.schedule(this._setNewScene, 0);
- },
-
- /**
- * set hide the out scene and show in scene
- */
- hideOutShowIn:function () {
- this._inScene.setVisible(true);
- this._outScene.setVisible(false);
- }
-});
-/**
- * creates a base transition with duration and incoming scene
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene the scene to transit with
- * @return {cc.TransitionScene|Null}
- */
-cc.TransitionScene.create = function (t, scene) {
- var tempScene = new cc.TransitionScene();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * A cc.Transition that supports orientation like.
- * Possible orientation: LeftOver, RightOver, UpOver, DownOver
- * useful for when you want to make a transition happen between 2 orientations
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionSceneOriented = cc.TransitionScene.extend(/** @lends cc.TransitionSceneOriented# */{
- _orientation:0,
-
- /**
- * initialize the transition
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} orientation
- * @return {Boolean}
- */
- initWithDuration:function (t, scene, orientation) {
- if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) {
- this._orientation = orientation;
- }
- return true;
- }
-});
-
-/**
- * creates a base transition with duration and incoming scene
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} orientation
- * @return {cc.TransitionSceneOriented}
- * @example
- * // Example
- * var goHorizontal = cc.TransitionSceneOriented.create(0.5, thisScene, cc.TRANSITION_ORIENTATION_LEFT_OVER)
- */
-cc.TransitionSceneOriented.create = function (t, scene, orientation) {
- var tempScene = new cc.TransitionSceneOriented();
- tempScene.initWithDuration(t, scene, orientation);
-
- return tempScene;
-};
-
-/**
- * Rotate and zoom out the outgoing scene, and then rotate and zoom in the incoming
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionRotoZoom = cc.TransitionScene.extend(/** @lends cc.TransitionRotoZoom# */{
- /**
- * Custom On Enter callback
- * @override
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- this._inScene.setScale(0.001);
- this._outScene.setScale(1.0);
-
- this._inScene.setAnchorPoint(cc.p(0.5, 0.5));
- this._outScene.setAnchorPoint(cc.p(0.5, 0.5));
-
- var rotoZoom = cc.Sequence.create(
- cc.Spawn.create(cc.ScaleBy.create(this._duration / 2, 0.001),
- cc.RotateBy.create(this._duration / 2, 360 * 2)),
- cc.DelayTime.create(this._duration / 2));
-
- this._outScene.runAction(rotoZoom);
- this._inScene.runAction(
- cc.Sequence.create(rotoZoom.reverse(),
- cc.CallFunc.create(this.finish, this)));
- }
-});
-
-/**
- * Creates a Transtion rotation and zoom
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene the scene to work with
- * @return {cc.TransitionRotoZoom}
- * @example
- * // Example
- * var RotoZoomTrans = cc.TransitionRotoZoom.create(2, nextScene);
- */
-cc.TransitionRotoZoom.create = function (t, scene) {
- var tempScene = new cc.TransitionRotoZoom();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Zoom out and jump the outgoing scene, and then jump and zoom in the incoming
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionJumpZoom = cc.TransitionScene.extend(/** @lends cc.TransitionJumpZoom# */{
- /**
- * Custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
- var winSize = cc.Director.getInstance().getWinSize();
-
- this._inScene.setScale(0.5);
- this._inScene.setPosition(winSize.width, 0);
- this._inScene.setAnchorPoint(cc.p(0.5, 0.5));
- this._outScene.setAnchorPoint(cc.p(0.5, 0.5));
-
- var jump = cc.JumpBy.create(this._duration / 4, cc.p(-winSize.width, 0), winSize.width / 4, 2);
- var scaleIn = cc.ScaleTo.create(this._duration / 4, 1.0);
- var scaleOut = cc.ScaleTo.create(this._duration / 4, 0.5);
-
- var jumpZoomOut = cc.Sequence.create(scaleOut, jump);
- var jumpZoomIn = cc.Sequence.create(jump, scaleIn);
-
- var delay = cc.DelayTime.create(this._duration / 2);
- this._outScene.runAction(jumpZoomOut);
- this._inScene.runAction(cc.Sequence.create(delay, jumpZoomIn, cc.CallFunc.create(this.finish, this)));
- }
-});
-
-/**
- * creates a scene transition that zooms then jump across the screen, the same for the incoming scene
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionJumpZoom}
- */
-cc.TransitionJumpZoom.create = function (t, scene) {
- var tempScene = new cc.TransitionJumpZoom();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Move in from to the left the incoming scene.
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionMoveInL = cc.TransitionScene.extend(/** @lends cc.TransitionMoveInL# */{
-
- /**
- * Custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
- this.initScenes();
-
- var action = this.action();
- this._inScene.runAction(
- cc.Sequence.create(this.easeActionWithAction(action), cc.CallFunc.create(this.finish, this))
- );
- },
-
- /**
- * initializes the scenes
- */
- initScenes:function () {
- this._inScene.setPosition(-cc.Director.getInstance().getWinSize().width, 0);
- },
-
- /**
- * returns the action that will be performed
- */
- action:function () {
- return cc.MoveTo.create(this._duration, cc.p(0, 0));
- },
-
- /**
- * creates an ease action from action
- * @param {cc.ActionInterval} action
- * @return {cc.EaseOut}
- */
- easeActionWithAction:function (action) {
- return cc.EaseOut.create(action, 2.0);
- }
-});
-
-/**
- * creates an action that Move in from to the left the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionMoveInL}
- * @example
- * // Example
- * var MoveInLeft = cc.TransitionMoveInL.create(1, nextScene)
- */
-cc.TransitionMoveInL.create = function (t, scene) {
- var tempScene = new cc.TransitionMoveInL();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Move in from to the right the incoming scene.
- * @class
- * @extends cc.TransitionMoveInL
- */
-cc.TransitionMoveInR = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveInR# */{
- /**
- * Init
- */
- initScenes:function () {
- this._inScene.setPosition(cc.Director.getInstance().getWinSize().width, 0);
- }
-});
-
-/**
- * create a scene transition that Move in from to the right the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionMoveInR}
- * @example
- * // Example
- * var MoveInRight = cc.TransitionMoveInR.create(1, nextScene)
- */
-cc.TransitionMoveInR.create = function (t, scene) {
- var tempScene = new cc.TransitionMoveInR();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Move in from to the top the incoming scene.
- * @class
- * @extends cc.TransitionMoveInL
- */
-cc.TransitionMoveInT = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveInT# */{
-
- /**
- * init
- */
- initScenes:function () {
- this._inScene.setPosition(0, cc.Director.getInstance().getWinSize().height);
- }
-});
-
-/**
- * Move in from to the top the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionMoveInT}
- * @example
- * // Example
- * var MoveInTop = cc.TransitionMoveInT.create(1, nextScene)
- */
-cc.TransitionMoveInT.create = function (t, scene) {
- var tempScene = new cc.TransitionMoveInT();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Move in from to the bottom the incoming scene.
- * @class
- * @extends cc.TransitionMoveInL
- */
-cc.TransitionMoveInB = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveInB# */{
-
- /**
- * init
- */
- initScenes:function () {
- this._inScene.setPosition(0, -cc.Director.getInstance().getWinSize().height);
- }
-});
-
-/**
- * create a scene transition that Move in from to the bottom the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionMoveInB}
- * @example
- * // Example
- * var MoveinB = cc.TransitionMoveInB.create(1, nextScene)
- */
-cc.TransitionMoveInB.create = function (t, scene) {
- var tempScene = new cc.TransitionMoveInB();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * The adjust factor is needed to prevent issue #442
- * One solution is to use DONT_RENDER_IN_SUBPIXELS images, but NO
- * The other issue is that in some transitions (and I don't know why)
- * the order should be reversed (In in top of Out or vice-versa).
- * @constant
- * @type Number
- */
-cc.ADJUST_FACTOR = 0.5;
-
-/**
- * a transition that a new scene is slided from left
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionSlideInL = cc.TransitionScene.extend(/** @lends cc.TransitionSlideInL# */{
- _sceneOrder:function () {
- this._isInSceneOnTop = false;
- },
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
- this.initScenes();
-
- var inA = this.action();
- var outA = this.action();
-
- var inAction = this.easeActionWithAction(inA);
- var outAction = cc.Sequence.create(this.easeActionWithAction(outA), cc.CallFunc.create(this.finish, this));
- this._inScene.runAction(inAction);
- this._outScene.runAction(outAction);
- },
-
- /**
- * initializes the scenes
- */
- initScenes:function () {
- this._inScene.setPosition(-(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR), 0);
- },
- /**
- * returns the action that will be performed by the incomming and outgoing scene
- * @return {cc.MoveBy}
- */
- action:function () {
- return cc.MoveBy.create(this._duration, cc.p(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR, 0));
- },
-
- /**
- * @param {cc.ActionInterval} action
- * @return {*}
- */
- easeActionWithAction:function (action) {
- return cc.EaseOut.create(action, 2.0);
- }
-});
-
-/**
- * create a transition that a new scene is slided from left
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionSlideInL}
- * @example
- * // Example
- * var myTransition = cc.TransitionSlideInL.create(1.5, nextScene)
- */
-cc.TransitionSlideInL.create = function (t, scene) {
- var tempScene = new cc.TransitionSlideInL();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Slide in the incoming scene from the right border.
- * @class
- * @extends cc.TransitionSlideInL
- */
-cc.TransitionSlideInR = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSlideInR# */{
- _sceneOrder:function () {
- this._isInSceneOnTop = true;
- },
- /**
- * initializes the scenes
- */
- initScenes:function () {
- this._inScene.setPosition(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR, 0);
- },
- /**
- * returns the action that will be performed by the incomming and outgoing scene
- * @return {cc.MoveBy}
- */
- action:function () {
- return cc.MoveBy.create(this._duration, cc.p(-(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR), 0));
- }
-});
-
-/**
- * create Slide in the incoming scene from the right border.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionSlideInR}
- * @example
- * // Example
- * var myTransition = cc.TransitionSlideInR.create(1.5, nextScene)
- */
-cc.TransitionSlideInR.create = function (t, scene) {
- var tempScene = new cc.TransitionSlideInR();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Slide in the incoming scene from the bottom border.
- * @class
- * @extends cc.TransitionSlideInL
- */
-cc.TransitionSlideInB = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSlideInB# */{
- _sceneOrder:function () {
- this._isInSceneOnTop = false;
- },
-
- /**
- * initializes the scenes
- */
- initScenes:function () {
- this._inScene.setPosition(0, cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR);
- },
-
- /**
- * returns the action that will be performed by the incomming and outgoing scene
- * @return {cc.MoveBy}
- */
- action:function () {
- return cc.MoveBy.create(this._duration, cc.p(0, -(cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR)));
- }
-});
-
-/**
- * create a Slide in the incoming scene from the bottom border.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionSlideInB}
- * @example
- * // Example
- * var myTransition = cc.TransitionSlideInB.create(1.5, nextScene)
- */
-cc.TransitionSlideInB.create = function (t, scene) {
- var tempScene = new cc.TransitionSlideInB();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Slide in the incoming scene from the top border.
- * @class
- * @extends cc.TransitionSlideInL
- */
-cc.TransitionSlideInT = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSlideInT# */{
- _sceneOrder:function () {
- this._isInSceneOnTop = true;
- },
-
- /**
- * initializes the scenes
- */
- initScenes:function () {
- this._inScene.setPosition(0, -(cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR));
- },
-
- /**
- * returns the action that will be performed by the incomming and outgoing scene
- * @return {cc.MoveBy}
- */
- action:function () {
- return cc.MoveBy.create(this._duration, cc.p(0, cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR));
- }
-});
-
-/**
- * create a Slide in the incoming scene from the top border.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionSlideInT}
- * @example
- * // Example
- * var myTransition = cc.TransitionSlideInT.create(1.5, nextScene)
- */
-cc.TransitionSlideInT.create = function (t, scene) {
- var tempScene = new cc.TransitionSlideInT();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Shrink the outgoing scene while grow the incoming scene
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionShrinkGrow = cc.TransitionScene.extend(/** @lends cc.TransitionShrinkGrow# */{
-
- /**
- * Custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- this._inScene.setScale(0.001);
- this._outScene.setScale(1.0);
-
- this._inScene.setAnchorPoint(cc.p(2 / 3.0, 0.5));
- this._outScene.setAnchorPoint(cc.p(1 / 3.0, 0.5));
-
- var scaleOut = cc.ScaleTo.create(this._duration, 0.01);
- var scaleIn = cc.ScaleTo.create(this._duration, 1.0);
-
- this._inScene.runAction(this.easeActionWithAction(scaleIn));
- this._outScene.runAction(
- cc.Sequence.create(this.easeActionWithAction(scaleOut), cc.CallFunc.create(this.finish, this))
- );
- },
-
- /**
- * @param action
- * @return {cc.EaseOut}
- */
- easeActionWithAction:function (action) {
- return cc.EaseOut.create(action, 2.0);
- }
-});
-
-/**
- * Shrink the outgoing scene while grow the incoming scene
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionShrinkGrow}
- * @example
- * // Example
- * var myTransition = cc.TransitionShrinkGrow.create(1.5, nextScene)
- */
-cc.TransitionShrinkGrow.create = function (t, scene) {
- var tempScene = new cc.TransitionShrinkGrow();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Flips the screen horizontally.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @class
- * @extends cc.TransitionSceneOriented
- */
-cc.TransitionFlipX = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionFlipX# */{
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var inA, outA;
- this._inScene.setVisible(false);
-
- var inDeltaZ, inAngleZ, outDeltaZ, outAngleZ;
-
- if (this._orientation === cc.TRANSITION_ORIENTATION_RIGHT_OVER) {
- inDeltaZ = 90;
- inAngleZ = 270;
- outDeltaZ = 90;
- outAngleZ = 0;
- } else {
- inDeltaZ = -90;
- inAngleZ = 90;
- outDeltaZ = -90;
- outAngleZ = 0;
- }
-
- inA = cc.Sequence.create(
- cc.DelayTime.create(this._duration / 2), cc.Show.create(),
- cc.OrbitCamera.create(this._duration / 2, 1, 0, inAngleZ, inDeltaZ, 0, 0),
- cc.CallFunc.create(this.finish, this)
- );
-
- outA = cc.Sequence.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, outAngleZ, outDeltaZ, 0, 0),
- cc.Hide.create(), cc.DelayTime.create(this._duration / 2)
- );
-
- this._inScene.runAction(inA);
- this._outScene.runAction(outA);
- }
-});
-
-/**
- * Flips the screen horizontally.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
- * @return {cc.TransitionFlipX}
- * @example
- * // Example
- * var myTransition = cc.TransitionFlipX.create(1.5, nextScene) //default is cc.TRANSITION_ORIENTATION_RIGHT_OVER
- *
- * //OR
- * var myTransition = cc.TransitionFlipX.create(1.5, nextScene, cc.TRANSITION_ORIENTATION_UP_OVER)
- */
-cc.TransitionFlipX.create = function (t, scene, o) {
- if (o == null)
- o = cc.TRANSITION_ORIENTATION_RIGHT_OVER;
-
- var tempScene = new cc.TransitionFlipX();
- tempScene.initWithDuration(t, scene, o);
- return tempScene;
-};
-
-/**
- * Flips the screen vertically.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @class
- * @extends cc.TransitionSceneOriented
- */
-cc.TransitionFlipY = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionFlipY# */{
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var inA, outA;
- this._inScene.setVisible(false);
-
- var inDeltaZ, inAngleZ, outDeltaZ, outAngleZ;
-
- if (this._orientation == cc.TRANSITION_ORIENTATION_UP_OVER) {
- inDeltaZ = 90;
- inAngleZ = 270;
- outDeltaZ = 90;
- outAngleZ = 0;
- } else {
- inDeltaZ = -90;
- inAngleZ = 90;
- outDeltaZ = -90;
- outAngleZ = 0;
- }
-
- inA = cc.Sequence.create(
- cc.DelayTime.create(this._duration / 2), cc.Show.create(),
- cc.OrbitCamera.create(this._duration / 2, 1, 0, inAngleZ, inDeltaZ, 90, 0),
- cc.CallFunc.create(this.finish, this)
- );
- outA = cc.Sequence.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, outAngleZ, outDeltaZ, 90, 0),
- cc.Hide.create(), cc.DelayTime.create(this._duration / 2)
- );
-
- this._inScene.runAction(inA);
- this._outScene.runAction(outA);
- }
-});
-
-/**
- * Flips the screen vertically.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
- * @return {cc.TransitionFlipY}
- * @example
- * // Example
- * var myTransition = cc.TransitionFlipY.create(1.5, nextScene)//default is cc.TRANSITION_ORIENTATION_UP_OVER
- *
- * //OR
- * var myTransition = cc.TransitionFlipY.create(1.5, nextScene, cc.TRANSITION_ORIENTATION_RIGHT_OVER)
- */
-cc.TransitionFlipY.create = function (t, scene, o) {
- if (o == null)
- o = cc.TRANSITION_ORIENTATION_UP_OVER;
-
- var tempScene = new cc.TransitionFlipY();
- tempScene.initWithDuration(t, scene, o);
-
- return tempScene;
-};
-
-/**
- * Flips the screen half horizontally and half vertically.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @class
- * @extends cc.TransitionSceneOriented
- */
-cc.TransitionFlipAngular = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionFlipAngular# */{
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var inA, outA;
- this._inScene.setVisible(false);
-
- var inDeltaZ, inAngleZ, outDeltaZ, outAngleZ;
-
- if (this._orientation === cc.TRANSITION_ORIENTATION_RIGHT_OVER) {
- inDeltaZ = 90;
- inAngleZ = 270;
- outDeltaZ = 90;
- outAngleZ = 0;
- } else {
- inDeltaZ = -90;
- inAngleZ = 90;
- outDeltaZ = -90;
- outAngleZ = 0;
- }
-
- inA = cc.Sequence.create(
- cc.DelayTime.create(this._duration / 2), cc.Show.create(),
- cc.OrbitCamera.create(this._duration / 2, 1, 0, inAngleZ, inDeltaZ, -45, 0),
- cc.CallFunc.create(this.finish, this)
- );
- outA = cc.Sequence.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, outAngleZ, outDeltaZ, 45, 0),
- cc.Hide.create(), cc.DelayTime.create(this._duration / 2)
- );
-
- this._inScene.runAction(inA);
- this._outScene.runAction(outA);
- }
-});
-
-/**
- * Flips the screen half horizontally and half vertically.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
- * @return {cc.TransitionFlipAngular}
- * @example
- * // Example
- * var myTransition = cc.TransitionFlipAngular.create(1.5, nextScene)//default is cc.TRANSITION_ORIENTATION_RIGHT_OVER
- *
- * //or
- * var myTransition = cc.TransitionFlipAngular.create(1.5, nextScene, cc.TRANSITION_ORIENTATION_DOWN_OVER)
- */
-cc.TransitionFlipAngular.create = function (t, scene, o) {
- if (o == null)
- o = cc.TRANSITION_ORIENTATION_RIGHT_OVER;
-
- var tempScene = new cc.TransitionFlipAngular();
- tempScene.initWithDuration(t, scene, o);
-
- return tempScene;
-};
-
-/**
- * Flips the screen horizontally doing a zoom out/in
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @class
- * @extends cc.TransitionSceneOriented
- */
-cc.TransitionZoomFlipX = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionZoomFlipX# */{
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var inA, outA;
- this._inScene.setVisible(false);
-
- var inDeltaZ, inAngleZ, outDeltaZ, outAngleZ;
-
- if (this._orientation === cc.TRANSITION_ORIENTATION_RIGHT_OVER) {
- inDeltaZ = 90;
- inAngleZ = 270;
- outDeltaZ = 90;
- outAngleZ = 0;
- } else {
- inDeltaZ = -90;
- inAngleZ = 90;
- outDeltaZ = -90;
- outAngleZ = 0;
- }
-
- inA = cc.Sequence.create(
- cc.DelayTime.create(this._duration / 2),
- cc.Spawn.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, inAngleZ, inDeltaZ, 0, 0),
- cc.ScaleTo.create(this._duration / 2, 1), cc.Show.create()),
- cc.CallFunc.create(this.finish, this)
- );
- outA = cc.Sequence.create(
- cc.Spawn.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, outAngleZ, outDeltaZ, 0, 0),
- cc.ScaleTo.create(this._duration / 2, 0.5)),
- cc.Hide.create(),
- cc.DelayTime.create(this._duration / 2)
- );
-
- this._inScene.setScale(0.5);
- this._inScene.runAction(inA);
- this._outScene.runAction(outA);
- }
-});
-
-/**
- * Flips the screen horizontally doing a zoom out/in
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
- * @return {cc.TransitionZoomFlipX}
- * @example
- * // Example
- * var myTransition = cc.TransitionZoomFlipX.create(1.5, nextScene)//default is cc.TRANSITION_ORIENTATION_RIGHT_OVER
- *
- * //OR
- * var myTransition = cc.TransitionZoomFlipX.create(1.5, nextScene, cc.TRANSITION_ORIENTATION_DOWN_OVER)
- */
-cc.TransitionZoomFlipX.create = function (t, scene, o) {
- if (o == null)
- o = cc.TRANSITION_ORIENTATION_RIGHT_OVER;
-
- var tempScene = new cc.TransitionZoomFlipX();
- tempScene.initWithDuration(t, scene, o);
-
- return tempScene;
-};
-
-/**
- * Flips the screen vertically doing a little zooming out/in
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @class
- * @extends cc.TransitionSceneOriented
- */
-cc.TransitionZoomFlipY = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionZoomFlipY# */{
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var inA, outA;
- this._inScene.setVisible(false);
-
- var inDeltaZ, inAngleZ, outDeltaZ, outAngleZ;
-
- if (this._orientation === cc.TRANSITION_ORIENTATION_UP_OVER) {
- inDeltaZ = 90;
- inAngleZ = 270;
- outDeltaZ = 90;
- outAngleZ = 0;
- } else {
- inDeltaZ = -90;
- inAngleZ = 90;
- outDeltaZ = -90;
- outAngleZ = 0;
- }
-
- inA = cc.Sequence.create(
- cc.DelayTime.create(this._duration / 2),
- cc.Spawn.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, inAngleZ, inDeltaZ, 90, 0),
- cc.ScaleTo.create(this._duration / 2, 1), cc.Show.create()),
- cc.CallFunc.create(this.finish, this));
-
- outA = cc.Sequence.create(
- cc.Spawn.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, outAngleZ, outDeltaZ, 90, 0),
- cc.ScaleTo.create(this._duration / 2, 0.5)),
- cc.Hide.create(), cc.DelayTime.create(this._duration / 2));
-
- this._inScene.setScale(0.5);
- this._inScene.runAction(inA);
- this._outScene.runAction(outA);
- }
-});
-
-/**
- * Flips the screen vertically doing a little zooming out/in
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
- * @return {cc.TransitionZoomFlipY}
- * @example
- * // Example
- * var myTransition = cc.TransitionZoomFlipY.create(1.5, nextScene)//default is cc.TRANSITION_ORIENTATION_UP_OVER
- *
- * //OR
- * var myTransition = cc.TransitionZoomFlipY.create(1.5, nextScene, cc.TRANSITION_ORIENTATION_DOWN_OVER)
- */
-cc.TransitionZoomFlipY.create = function (t, scene, o) {
- if (o == null)
- o = cc.TRANSITION_ORIENTATION_UP_OVER;
-
- var tempScene = new cc.TransitionZoomFlipY();
- tempScene.initWithDuration(t, scene, o);
-
- return tempScene;
-};
-
-/**
- * Flips the screen half horizontally and half vertically doing a little zooming out/in.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @class
- * @extends cc.TransitionSceneOriented
- */
-cc.TransitionZoomFlipAngular = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionZoomFlipAngular# */{
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var inA, outA;
- this._inScene.setVisible(false);
-
- var inDeltaZ, inAngleZ, outDeltaZ, outAngleZ;
- if (this._orientation === cc.TRANSITION_ORIENTATION_RIGHT_OVER) {
- inDeltaZ = 90;
- inAngleZ = 270;
- outDeltaZ = 90;
- outAngleZ = 0;
- } else {
- inDeltaZ = -90;
- inAngleZ = 90;
- outDeltaZ = -90;
- outAngleZ = 0;
- }
-
- inA = cc.Sequence.create(
- cc.DelayTime.create(this._duration / 2),
- cc.Spawn.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, inAngleZ, inDeltaZ, -45, 0),
- cc.ScaleTo.create(this._duration / 2, 1), cc.Show.create()),
- cc.Show.create(),
- cc.CallFunc.create(this.finish, this));
- outA = cc.Sequence.create(
- cc.Spawn.create(
- cc.OrbitCamera.create(this._duration / 2, 1, 0, outAngleZ, outDeltaZ, 45, 0),
- cc.ScaleTo.create(this._duration / 2, 0.5)),
- cc.Hide.create(), cc.DelayTime.create(this._duration / 2));
-
- this._inScene.setScale(0.5);
- this._inScene.runAction(inA);
- this._outScene.runAction(outA);
- }
-});
-
-/**
- * Flips the screen half horizontally and half vertically doing a little zooming out/in.
- * The front face is the outgoing scene and the back face is the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
- * @return {cc.TransitionZoomFlipAngular}
- * @example
- * // Example
- * var myTransition = cc.TransitionZoomFlipAngular.create(1.5, nextScene)//default is cc.TRANSITION_ORIENTATION_RIGHT_OVER
- *
- * //OR
- * var myTransition = cc.TransitionZoomFlipAngular.create(1.5, nextScene, cc.TRANSITION_ORIENTATION_DOWN_OVER)
- */
-cc.TransitionZoomFlipAngular.create = function (t, scene, o) {
- if (o == null)
- o = cc.TRANSITION_ORIENTATION_RIGHT_OVER;
-
- var tempScene = new cc.TransitionZoomFlipAngular();
- tempScene.initWithDuration(t, scene, o);
-
- return tempScene;
-};
-
-/**
- * Fade out the outgoing scene and then fade in the incoming scene.
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionFade = cc.TransitionScene.extend(/** @lends cc.TransitionFade# */{
- _color:null,
-
- /**
- * Constructor
- */
- ctor:function () {
- cc.TransitionScene.prototype.ctor.call(this);
- this._color = new cc.Color4B()
- },
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var l = cc.LayerColor.create(this._color);
- this._inScene.setVisible(false);
-
- this.addChild(l, 2, cc.SCENE_FADE);
- var f = this.getChildByTag(cc.SCENE_FADE);
-
- var a = cc.Sequence.create(
- cc.FadeIn.create(this._duration / 2),
- cc.CallFunc.create(this.hideOutShowIn, this), //CCCallFunc.actionWithTarget:self selector:@selector(hideOutShowIn)],
- cc.FadeOut.create(this._duration / 2),
- cc.CallFunc.create(this.finish, this) //:self selector:@selector(finish)],
- );
- f.runAction(a);
- },
-
- /**
- * custom on exit
- */
- onExit:function () {
- cc.TransitionScene.prototype.onExit.call(this);
- this.removeChildByTag(cc.SCENE_FADE, false);
- },
-
- /**
- * initializes the transition with a duration and with an RGB color
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.Color3B} color
- * @return {Boolean}
- */
- initWithDuration:function (t, scene, color) {
- color = color || cc.black();
- if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) {
- this._color.r = color.r;
- this._color.g = color.g;
- this._color.b = color.b;
- this._color.a = 0;
- }
- return true;
- }
-});
-
-
-/**
- * Fade out the outgoing scene and then fade in the incoming scene.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @param {cc.Color3B} color
- * @return {cc.TransitionFade}
- * @example
- * // Example
- * var myTransition = cc.TransitionFade.create(1.5, nextScene, cc.c3b(255,0,0))//fade to red
- */
-cc.TransitionFade.create = function (t, scene, color) {
- var transition = new cc.TransitionFade();
- transition.initWithDuration(t, scene, color);
- return transition;
-};
-
-/**
- * Cross fades two scenes using the cc.RenderTexture object.
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionCrossFade = cc.TransitionScene.extend(/** @lends cc.TransitionCrossFade# */{
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- // create a transparent color layer
- // in which we are going to add our rendertextures
- var color = new cc.Color4B(0, 0, 0, 0);
- var winSize = cc.Director.getInstance().getWinSize();
- var layer = cc.LayerColor.create(color);
-
- // create the first render texture for inScene
- var inTexture = cc.RenderTexture.create(winSize.width, winSize.height);
-
- if (null == inTexture)
- return;
-
- inTexture.getSprite().setAnchorPoint(cc.p(0.5, 0.5));
- inTexture.setPosition(winSize.width / 2, winSize.height / 2);
- inTexture.setAnchorPoint(cc.p(0.5, 0.5));
-
- // render inScene to its texturebuffer
- inTexture.begin();
- this._inScene.visit();
- inTexture.end();
-
- // create the second render texture for outScene
- var outTexture = cc.RenderTexture.create(winSize.width, winSize.height);
- outTexture.getSprite().setAnchorPoint(cc.p(0.5, 0.5));
- outTexture.setPosition(winSize.width / 2, winSize.height / 2);
- outTexture.setAnchorPoint(cc.p(0.5, 0.5));
-
- // render outScene to its texturebuffer
- outTexture.begin();
- this._outScene.visit();
- outTexture.end();
-
- inTexture.getSprite().setBlendFunc(gl.ONE, gl.ONE); // inScene will lay on background and will not be used with alpha
- outTexture.getSprite().setBlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); // we are going to blend outScene via alpha
-
- // add render textures to the layer
- layer.addChild(inTexture);
- layer.addChild(outTexture);
-
- // initial opacity:
- inTexture.getSprite().setOpacity(255);
- outTexture.getSprite().setOpacity(255);
-
- // create the blend action
- var layerAction = cc.Sequence.create(
- cc.FadeTo.create(this._duration, 0), cc.CallFunc.create(this.hideOutShowIn, this),
- cc.CallFunc.create(this.finish, this)
- );
-
- // run the blend action
- outTexture.getSprite().runAction(layerAction);
-
- // add the layer (which contains our two rendertextures) to the scene
- this.addChild(layer, 2, cc.SCENE_FADE);
- },
-
- /**
- * custom on exit
- */
- onExit:function () {
- this.removeChildByTag(cc.SCENE_FADE, false);
- cc.TransitionScene.prototype.onExit.call(this);
- },
-
- /**
- * overide draw
- */
- draw:function () {
- // override draw since both scenes (textures) are rendered in 1 scene
- }
-});
-
-/**
- * Cross fades two scenes using the cc.RenderTexture object.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionCrossFade}
- * @example
- * // Example
- * var myTransition = cc.TransitionCrossFade.create(1.5, nextScene)
- */
-cc.TransitionCrossFade.create = function (t, scene) {
- var Transition = new cc.TransitionCrossFade();
- Transition.initWithDuration(t, scene);
- return Transition;
-};
-
-/**
- * Turn off the tiles of the outgoing scene in random order
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionTurnOffTiles = cc.TransitionScene.extend(/** @lends cc.TransitionTurnOffTiles# */{
- _sceneOrder:function () {
- this._isInSceneOnTop = false;
- },
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
- var winSize = cc.Director.getInstance().getWinSize();
- var aspect = winSize.width / winSize.height;
- var x = 0 | (12 * aspect);
- var y = 12;
- var toff = cc.TurnOffTiles.create(this._duration, cc.size(x, y));
- var action = this.easeActionWithAction(toff);
- this._outScene.runAction(cc.Sequence.create(action, cc.CallFunc.create(this.finish, this), cc.StopGrid.create()));
- },
-
- /**
- * @param {cc.ActionInterval} action
- * @return {cc.ActionInterval}
- */
- easeActionWithAction:function (action) {
- return action;
- }
-});
-
-/**
- * Turn off the tiles of the outgoing scene in random order
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionTurnOffTiles}
- * @example
- * // Example
- * var myTransition = cc.TransitionTurnOffTiles.create(1.5, nextScene)
- */
-cc.TransitionTurnOffTiles.create = function (t, scene) {
- var tempScene = new cc.TransitionTurnOffTiles();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * The odd columns goes upwards while the even columns goes downwards.
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionSplitCols = cc.TransitionScene.extend(/** @lends cc.TransitionSplitCols# */{
-
- /**
- * custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
- this._inScene.setVisible(false);
-
- var split = this.action();
- var seq = cc.Sequence.create(
- split, cc.CallFunc.create(this.hideOutShowIn, this), split.reverse());
-
- this.runAction(
- cc.Sequence.create(this.easeActionWithAction(seq), cc.CallFunc.create(this.finish, this), cc.StopGrid.create())
- );
- },
-
- /**
- * @param {cc.ActionInterval} action
- * @return {cc.EaseInOut}
- */
- easeActionWithAction:function (action) {
- return cc.EaseInOut.create(action, 3.0);
- },
-
- /**
- * @return {*}
- */
- action:function () {
- return cc.SplitCols.create(this._duration / 2.0, 3);
- }
-});
-
-/**
- * The odd columns goes upwards while the even columns goes downwards.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionSplitCols}
- * @example
- * // Example
- * var myTransition = cc.TransitionSplitCols.create(1.5, nextScene)
- */
-cc.TransitionSplitCols.create = function (t, scene) {
- var tempScene = new cc.TransitionSplitCols();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * The odd rows goes to the left while the even rows goes to the right.
- * @class
- * @extends cc.TransitionSplitCols
- */
-cc.TransitionSplitRows = cc.TransitionSplitCols.extend(/** @lends cc.TransitionSplitRows# */{
- /**
- * @return {*}
- */
- action:function () {
- return cc.SplitRows.create(this._duration / 2.0, 3);
- }
-});
-
-/**
- * The odd rows goes to the left while the even rows goes to the right.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionSplitRows}
- * @example
- * // Example
- * var myTransition = cc.TransitionSplitRows.create(1.5, nextScene)
- */
-cc.TransitionSplitRows.create = function (t, scene) {
- var tempScene = new cc.TransitionSplitRows();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Fade the tiles of the outgoing scene from the left-bottom corner the to top-right corner.
- * @class
- * @extends cc.TransitionScene
- */
-cc.TransitionFadeTR = cc.TransitionScene.extend(/** @lends cc.TransitionFadeTR# */{
- _sceneOrder:function () {
- this._isInSceneOnTop = false;
- },
-
- /**
- * Custom on enter
- */
- onEnter:function () {
- cc.TransitionScene.prototype.onEnter.call(this);
-
- var winSize = cc.Director.getInstance().getWinSize();
- var aspect = winSize.width / winSize.height;
- var x = 0 | (12 * aspect);
- var y = 12;
-
- var action = this.actionWithSize(cc.size(x, y));
- this._outScene.runAction(
- cc.Sequence.create(this.easeActionWithAction(action), cc.CallFunc.create(this.finish, this),
- cc.StopGrid.create())
- );
- },
-
- /**
- * @param {cc.ActionInterval} action
- * @return {cc.ActionInterval}
- */
- easeActionWithAction:function (action) {
- return action;
- },
-
- /**
- * @param {cc.Size} size
- * @return {*}
- */
- actionWithSize:function (size) {
- return cc.FadeOutTRTiles.create(this._duration, size);
- }
-});
-
-/**
- * Fade the tiles of the outgoing scene from the left-bottom corner the to top-right corner.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionFadeTR}
- * @example
- * // Example
- * var myTransition = cc.TransitionFadeTR.create(1.5, nextScene)
- */
-cc.TransitionFadeTR.create = function (t, scene) {
- var tempScene = new cc.TransitionFadeTR();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene)))
- return tempScene;
- return null;
-};
-
-/**
- * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
- * @class
- * @extends cc.TransitionFadeTR
- */
-cc.TransitionFadeBL = cc.TransitionFadeTR.extend(/** @lends cc.TransitionFadeBL# */{
-
- /**
- * @param {cc.Size} size
- * @return {*}
- */
- actionWithSize:function (size) {
- return cc.FadeOutBLTiles.create(this._duration, size);
- }
-});
-
-/**
- * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionFadeBL}
- * @example
- * // Example
- * var myTransition = cc.TransitionFadeBL.create(1.5, nextScene)
- */
-cc.TransitionFadeBL.create = function (t, scene) {
- var tempScene = new cc.TransitionFadeBL();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene)))
- return tempScene;
- return null;
-};
-
-/**
- * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
- * @class
- * @extends cc.TransitionFadeTR
- */
-cc.TransitionFadeUp = cc.TransitionFadeTR.extend(/** @lends cc.TransitionFadeUp# */{
-
- /**
- * @param {cc.Size} size
- * @return {*}
- */
- actionWithSize:function (size) {
- return cc.FadeOutUpTiles.create(this._duration, size);
- }
-});
-
-/**
- * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionFadeUp}
- * @example
- * // Example
- * var myTransition = cc.TransitionFadeUp.create(1.5, nextScene)
- */
-cc.TransitionFadeUp.create = function (t, scene) {
- var tempScene = new cc.TransitionFadeUp();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
-
-/**
- * Fade the tiles of the outgoing scene from the top to the bottom.
- * @class
- * @extends cc.TransitionFadeTR
- */
-cc.TransitionFadeDown = cc.TransitionFadeTR.extend(/** @lends cc.TransitionFadeDown# */{
-
- /**
- * @param {cc.Size} size
- * @return {*}
- */
- actionWithSize:function (size) {
- return cc.FadeOutDownTiles.create( this._duration, size);
- }
-});
-
-/**
- * Fade the tiles of the outgoing scene from the top to the bottom.
- * @param {Number} t time in seconds
- * @param {cc.Scene} scene
- * @return {cc.TransitionFadeDown}
- * @example
- * // Example
- * var myTransition = cc.TransitionFadeDown.create(1.5, nextScene)
- */
-cc.TransitionFadeDown.create = function (t, scene) {
- var tempScene = new cc.TransitionFadeDown();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
-};
diff --git a/cocos2d/menu_nodes/CCMenuItem.js b/cocos2d/menu_nodes/CCMenuItem.js
deleted file mode 100644
index 94204b1a34..0000000000
--- a/cocos2d/menu_nodes/CCMenuItem.js
+++ /dev/null
@@ -1,1204 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-/**
- * default size for font size
- * @constant
- * @type Number
- */
-cc.ITEM_SIZE = 32;
-
-cc._globalFontSize = cc.ITEM_SIZE;
-cc._globalFontName = "Arial";
-cc._globalFontNameRelease = false;
-
-/**
- * default tag for current item
- * @constant
- * @type Number
- */
-cc.CURRENT_ITEM = 0xc0c05001;
-/**
- * default tag for zoom action tag
- * @constant
- * @type Number
- */
-cc.ZOOM_ACTION_TAG = 0xc0c05002;
-/**
- * default tag for normal
- * @constant
- * @type Number
- */
-cc.NORMAL_TAG = 8801;
-
-/**
- * default selected tag
- * @constant
- * @type Number
- */
-cc.SELECTED_TAG = 8802;
-
-/**
- * default disabled tag
- * @constant
- * @type Number
- */
-cc.DISABLE_TAG = 8803;
-
-/**
- * Subclass cc.MenuItem (or any subclass) to create your custom cc.MenuItem objects.
- * @class
- * @extends cc.NodeRGBA
- */
-cc.MenuItem = cc.NodeRGBA.extend(/** @lends cc.MenuItem# */{
- _target:null,
- _callback:null,
- _isSelected:false,
- _isEnabled:false,
-
- ctor:function(){
- cc.NodeRGBA.prototype.ctor.call(this);
- this._target = null;
- this._callback = null;
- this._isSelected = false;
- this._isEnabled = false;
- },
-
- /**
- * MenuItem is selected
- * @return {Boolean}
- */
- isSelected:function () {
- return this._isSelected;
- },
-
- setOpacityModifyRGB:function (value) {
- },
-
- isOpacityModifyRGB:function () {
- return false;
- },
-
- /**
- * set the target/selector of the menu item
- * @param {function|String} selector
- * @param {cc.Node} rec
- * @deprecated
- */
- setTarget:function (selector, rec) {
- this._target = rec;
- this._callback = selector;
- },
-
- /**
- * MenuItem is Enabled
- * @return {Boolean}
- */
- isEnabled:function () {
- return this._isEnabled;
- },
-
- /**
- * set enable value of MenuItem
- * @param {Boolean} enable
- */
- setEnabled:function (enable) {
- this._isEnabled = enable;
- },
-
- /**
- * @param {function|String} callback
- * @param {cc.Node} target
- * @return {Boolean}
- */
- initWithCallback:function (callback, target) {
- this.setAnchorPoint(cc.p(0.5, 0.5));
- this._target = target;
- this._callback = callback;
- this._isEnabled = true;
- this._isSelected = false;
- return true;
- },
-
- /**
- * return rect value of cc.MenuItem
- * @return {cc.Rect}
- */
- rect:function () {
- var locPosition = this._position, locContentSize = this._contentSize, locAnchorPoint = this._anchorPoint;
- return cc.rect(locPosition.x - locContentSize.width * locAnchorPoint.x,
- locPosition.y - locContentSize.height * locAnchorPoint.y,
- locContentSize.width, locContentSize.height);
- },
-
- /**
- * same as setIsSelected(true)
- */
- selected:function () {
- this._isSelected = true;
- },
-
- /**
- * same as setIsSelected(false)
- */
- unselected:function () {
- this._isSelected = false;
- },
-
- /**
- * set the callback to the menu item
- * @param {function|String} callback
- * @param {cc.Node} target
- */
- setCallback:function (callback, target) {
- this._target = target;
- this._callback = callback;
- },
-
- /**
- * call the selector with target
- */
- activate:function () {
- if (this._isEnabled) {
- var locTarget = this._target, locCallback = this._callback;
- if(!locCallback)
- return ;
- if (locTarget && (typeof(locCallback) == "string")) {
- locTarget[locCallback](this);
- } else if (locTarget && (typeof(locCallback) == "function")) {
- locCallback.call(locTarget, this);
- } else
- locCallback(this);
- }
- }
-});
-
-/**
- * creates an empty menu item with target and callback
- * Not recommended to use the base class, should use more defined menu item classes
- * @param {function|String} callback callback
- * @param {cc.Node} target
- * @return {cc.MenuItem}
- */
-cc.MenuItem.create = function (callback, target) {
- var ret = new cc.MenuItem();
- ret.initWithCallback(callback,target);
- return ret;
-};
-
-/**
- * Any cc.Node that supports the cc.LabelProtocol protocol can be added.
- * Supported nodes:
- * - cc.BitmapFontAtlas
- * - cc.LabelAtlas
- * - cc.LabelTTF
- * @class
- * @extends cc.MenuItem
- */
-cc.MenuItemLabel = cc.MenuItem.extend(/** @lends cc.MenuItemLabel# */{
- _disabledColor: null,
- _label: null,
- _orginalScale: 0,
- _colorBackup: null,
-
- ctor: function () {
- cc.MenuItem.prototype.ctor.call(this);
- this._disabledColor = null;
- this._label = null;
- this._orginalScale = 0;
- this._colorBackup = null;
- },
-
- /**
- * @return {cc.Color3B}
- */
- getDisabledColor:function () {
- return this._disabledColor;
- },
-
- /**
- * @param {cc.Color3B} color
- */
- setDisabledColor:function (color) {
- this._disabledColor = color;
- },
-
- /**
- * return label of MenuItemLabel
- * @return {cc.Node}
- */
- getLabel:function () {
- return this._label;
- },
-
- /**
- * @param {cc.Node} label
- */
- setLabel:function (label) {
- if (label) {
- this.addChild(label);
- label.setAnchorPoint(cc.p(0, 0));
- this.setContentSize(label.getContentSize());
- }
-
- if (this._label) {
- this.removeChild(this._label, true);
- }
-
- this._label = label;
- },
-
- /**
- * @param {Boolean} enabled
- */
- setEnabled:function (enabled) {
- if (this._isEnabled != enabled) {
- var locLabel = this._label;
- if (!enabled) {
- this._colorBackup = locLabel.getColor();
- locLabel.setColor(this._disabledColor);
- } else {
- locLabel.setColor(this._colorBackup);
- }
- }
- cc.MenuItem.prototype.setEnabled.call(this, enabled);
- },
-
- /**
- * @param {Number} opacity from 0-255
- */
- setOpacity:function (opacity) {
- this._label.setOpacity(opacity);
- },
-
- /**
- * @return {Number}
- */
- getOpacity:function () {
- return this._label.getOpacity();
- },
-
- /**
- * @param {cc.Color3B} color
- */
- setColor:function (color) {
- this._label.setColor(color);
- },
-
- /**
- * @return {cc.Color3B}
- */
- getColor:function () {
- return this._label.getColor();
- },
-
- /**
- * @param {cc.Node} label
- * @param {function|String} selector
- * @param {cc.Node} target
- * @return {Boolean}
- */
- initWithLabel:function (label, selector, target) {
- this.initWithCallback(selector, target);
- this._originalScale = 1.0;
- this._colorBackup = cc.white();
- this._disabledColor = cc.c3b(126, 126, 126);
- this.setLabel(label);
-
- this.setCascadeColorEnabled(true);
- this.setCascadeOpacityEnabled(true);
-
- return true;
- },
-
- /**
- * @param {String} label
- */
- setString:function (label) {
- this._label.setString(label);
- this.setContentSize(this._label.getContentSize());
- },
-
- /**
- * activate the menu item
- */
- activate:function () {
- if (this._isEnabled) {
- this.stopAllActions();
- this.setScale(this._originalScale);
- cc.MenuItem.prototype.activate.call(this);
- }
- },
-
- /**
- * menu item is selected (runs callback)
- */
- selected:function () {
- if (this._isEnabled) {
- cc.MenuItem.prototype.selected.call(this);
-
- var action = this.getActionByTag(cc.ZOOM_ACTION_TAG);
- if (action)
- this.stopAction(action);
- else
- this._originalScale = this.getScale();
-
- var zoomAction = cc.ScaleTo.create(0.1, this._originalScale * 1.2);
- zoomAction.setTag(cc.ZOOM_ACTION_TAG);
- this.runAction(zoomAction);
- }
- },
-
- /**
- * menu item goes back to unselected state
- */
- unselected:function () {
- if (this._isEnabled) {
- cc.MenuItem.prototype.unselected.call(this);
- this.stopActionByTag(cc.ZOOM_ACTION_TAG);
- var zoomAction = cc.ScaleTo.create(0.1, this._originalScale);
- zoomAction.setTag(cc.ZOOM_ACTION_TAG);
- this.runAction(zoomAction);
- }
- }
-});
-
-/**
- * @param {cc.Node} label
- * @param {function|String|Null} selector
- * @param {cc.Node|Null} target
- * @return {cc.MenuItemLabel}
- */
-cc.MenuItemLabel.create = function (label, selector, target) {
- var ret = new cc.MenuItemLabel();
- ret.initWithLabel(label, selector, target);
- return ret;
-};
-
-/**
- * Helper class that creates a MenuItemLabel class with a LabelAtlas
- * @class
- * @extends cc.MenuItemLabel
- */
-cc.MenuItemAtlasFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemAtlasFont# */{
- /**
- * @param {String} value
- * @param {String} charMapFile
- * @param {Number} itemWidth
- * @param {Number} itemHeight
- * @param {String} startCharMap a single character
- * @param {function|String|Null} callback
- * @param {cc.Node|Null} target
- * @return {Boolean}
- */
- initWithString:function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
- cc.Assert(value != null && value.length != 0, "value length must be greater than 0");
- var label = new cc.LabelAtlas();
- label.initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap);
- if (this.initWithLabel(label, callback, target)) {
- // do something ?
- }
- return true;
- }
-});
-
-/**
- * create menu item from string with font
- * @param {String} value the text to display
- * @param {String} charMapFile the character map file
- * @param {Number} itemWidth
- * @param {Number} itemHeight
- * @param {String} startCharMap a single character
- * @param {function|String|Null} [callback=null]
- * @param {cc.Node|Null} [target=]
- * @return {cc.MenuItemAtlasFont}
- * @example
- * // Example
- * var item = cc.MenuItemAtlasFont.create('text to display', 'font.fnt', 12, 32, ' ')
- *
- * //OR
- * var item = cc.MenuItemAtlasFont.create('text to display', 'font.fnt', 12, 32, ' ', game.run, game)
- */
-cc.MenuItemAtlasFont.create = function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
- var ret = new cc.MenuItemAtlasFont();
- ret.initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target);
- return ret;
-};
-
-/**
- * Helper class that creates a CCMenuItemLabel class with a Label
- * @class
- * @extends cc.MenuItemLabel
- */
-cc.MenuItemFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemFont# */{
- _fontSize:null,
- _fontName:null,
-
- ctor:function(){
- cc.MenuItemLabel.prototype.ctor.call(this);
- this._fontSize = 0;
- this._fontName = "";
- },
-
- /**
- * @param {String} value text for the menu item
- * @param {function|String} callback
- * @param {cc.Node} target
- * @return {Boolean}
- */
- initWithString:function (value, callback, target) {
- cc.Assert(value != null && value.length != 0, "Value length must be greater than 0");
-
- this._fontName = cc._globalFontName;
- this._fontSize = cc._globalFontSize;
-
- var label = cc.LabelTTF.create(value, this._fontName, this._fontSize);
- if (this.initWithLabel(label, callback, target)) {
- // do something ?
- }
- return true;
- },
-
- /**
- * @param {Number} s
- */
- setFontSize:function (s) {
- this._fontSize = s;
- this._recreateLabel();
- },
-
- /**
- *
- * @return {Number}
- */
- fontSize:function () {
- return this._fontSize;
- },
-
- /**
- * @param {String} name
- */
- setFontName:function (name) {
- this._fontName = name;
- this._recreateLabel();
- },
-
- /**
- * @return {String}
- */
- fontName:function () {
- return this._fontName;
- },
-
- _recreateLabel:function () {
- var label = cc.LabelTTF.create(this._label.getString(),
- this._fontName, this._fontSize);
- this.setLabel(label);
- }
-});
-
-/**
- * a shared function to set the fontSize for menuitem font
- * @param {Number} fontSize
- */
-cc.MenuItemFont.setFontSize = function (fontSize) {
- cc._globalFontSize = fontSize;
-};
-
-/**
- * a shared function to get the font size for menuitem font
- * @return {Number}
- */
-cc.MenuItemFont.fontSize = function () {
- return cc._globalFontSize;
-};
-
-/**
- * a shared function to set the fontsize for menuitem font
- * @param name
- */
-cc.MenuItemFont.setFontName = function (name) {
- if (cc._globalFontNameRelease) {
- cc._globalFontName = '';
- }
- cc._globalFontName = name;
- cc._globalFontNameRelease = true;
-};
-
-/**
- * a shared function to get the font name for menuitem font
- * @return {String}
- */
-cc.MenuItemFont.fontName = function () {
- return cc._globalFontName;
-};
-
-/**
- * create a menu item from string
- * @param {String} value the text to display
- * @param {String|function|Null} callback the callback to run, either in function name or pass in the actual function
- * @param {cc.Node|Null} target the target to run callback
- * @return {cc.MenuItemFont}
- * @example
- * // Example
- * var item = cc.MenuItemFont.create("Game start", 'start', Game)
- * //creates a menu item from string "Game start", and when clicked, it will run Game.start()
- *
- * var item = cc.MenuItemFont.create("Game start", game.start, Game)//same as above
- *
- * var item = cc.MenuItemFont.create("i do nothing")//create a text menu item that does nothing
- *
- * //you can set font size and name before or after
- * cc.MenuItemFont.setFontName('my Fancy Font');
- * cc.MenuItemFont.setFontSize(62);
- */
-cc.MenuItemFont.create = function (value, callback, target) {
- var ret = new cc.MenuItemFont();
- ret.initWithString(value, callback, target);
- return ret;
-};
-
-
-/**
- * CCMenuItemSprite accepts CCNode objects as items.
- * The images has 3 different states:
- * - unselected image
- * - selected image
- * - disabled image
- * @class
- * @extends cc.MenuItem
- */
-cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{
- _normalImage:null,
- _selectedImage:null,
- _disabledImage:null,
-
- ctor: function(){
- cc.MenuItem.prototype.ctor.call(this);
- this._normalImage = null;
- this._selectedImage = null;
- this._disabledImage = null;
- },
-
- /**
- * @return {cc.Sprite}
- */
- getNormalImage:function () {
- return this._normalImage;
- },
-
- /**
- * @param {cc.Sprite} normalImage
- */
- setNormalImage:function (normalImage) {
- if (this._normalImage == normalImage) {
- return;
- }
- if (normalImage) {
- this.addChild(normalImage, 0, cc.NORMAL_TAG);
- normalImage.setAnchorPoint(cc.p(0, 0));
- }
- if (this._normalImage) {
- this.removeChild(this._normalImage, true);
- }
-
- this._normalImage = normalImage;
- if(normalImage.textureLoaded()){
- this.setContentSize(this._normalImage.getContentSize());
- this._updateImagesVisibility();
- } else {
- normalImage.addLoadedEventListener(function(sender){
- this.setContentSize(sender.getContentSize());
- this._updateImagesVisibility();
- }, this);
- }
- },
-
- /**
- * @return {cc.Sprite}
- */
- getSelectedImage:function () {
- return this._selectedImage;
- },
-
- /**
- * @param {cc.Sprite} selectedImage
- */
- setSelectedImage:function (selectedImage) {
- if (this._selectedImage == selectedImage)
- return;
-
- if (selectedImage) {
- this.addChild(selectedImage, 0, cc.SELECTED_TAG);
- selectedImage.setAnchorPoint(cc.p(0, 0));
- }
-
- if (this._selectedImage) {
- this.removeChild(this._selectedImage, true);
- }
-
- this._selectedImage = selectedImage;
- if(selectedImage.textureLoaded()){
- this._updateImagesVisibility();
- } else {
- selectedImage.addLoadedEventListener(function(sender){
- this._updateImagesVisibility();
- }, this);
- }
- },
-
- /**
- * @return {cc.Sprite}
- */
- getDisabledImage:function () {
- return this._disabledImage;
- },
-
- /**
- * @param {cc.Sprite} disabledImage
- */
- setDisabledImage:function (disabledImage) {
- if (this._disabledImage == disabledImage)
- return;
-
- if (disabledImage) {
- this.addChild(disabledImage, 0, cc.DISABLE_TAG);
- disabledImage.setAnchorPoint(cc.p(0, 0));
- }
-
- if (this._disabledImage)
- this.removeChild(this._disabledImage, true);
-
- this._disabledImage = disabledImage;
- if(disabledImage.textureLoaded()){
- this._updateImagesVisibility();
- } else {
- disabledImage.addLoadedEventListener(function(sender){
- this._updateImagesVisibility();
- }, this);
- }
- },
-
- /**
- * @param {cc.Node} normalSprite
- * @param {cc.Node} selectedSprite
- * @param {cc.Node} disabledSprite
- * @param {function|String} callback
- * @param {cc.Node} target
- * @return {Boolean}
- */
- initWithNormalSprite:function (normalSprite, selectedSprite, disabledSprite, callback, target) {
- this.initWithCallback(callback, target);
- this.setNormalImage(normalSprite);
- this.setSelectedImage(selectedSprite);
- this.setDisabledImage(disabledSprite);
- var locNormalImage = this._normalImage;
- if (locNormalImage){
- if(locNormalImage.textureLoaded()){
- this.setContentSize(locNormalImage.getContentSize());
- this.setCascadeColorEnabled(true);
- this.setCascadeOpacityEnabled(true);
- } else{
- locNormalImage.addLoadedEventListener(function(sender){
- this.setContentSize(sender.getContentSize());
- this.setCascadeColorEnabled(true);
- this.setCascadeOpacityEnabled(true);
- }, this);
- }
- }
-
-
- return true;
- },
-
- /**
- * @param {cc.Color3B} color
- */
- setColor:function (color) {
- this._normalImage.setColor(color);
-
- if (this._selectedImage)
- this._selectedImage.setColor(color);
-
- if (this._disabledImage)
- this._disabledImage.setColor(color);
- },
-
- /**
- * @return {cc.Color3B}
- */
- getColor:function () {
- return this._normalImage.getColor();
- },
-
- /**
- * @param {Number} opacity 0 - 255
- */
- setOpacity:function (opacity) {
- this._normalImage.setOpacity(opacity);
-
- if (this._selectedImage)
- this._selectedImage.setOpacity(opacity);
-
- if (this._disabledImage)
- this._disabledImage.setOpacity(opacity);
- },
-
- /**
- * @return {Number} opacity from 0 - 255
- */
- getOpacity:function () {
- return this._normalImage.getOpacity();
- },
-
- /**
- * menu item is selected (runs callback)
- */
- selected:function () {
- cc.MenuItem.prototype.selected.call(this);
- if (this._normalImage) {
- if (this._disabledImage)
- this._disabledImage.setVisible(false);
-
- if (this._selectedImage) {
- this._normalImage.setVisible(false);
- this._selectedImage.setVisible(true);
- } else
- this._normalImage.setVisible(true);
- }
- },
-
- /**
- * menu item goes back to unselected state
- */
- unselected:function () {
- cc.MenuItem.prototype.unselected.call(this);
- if (this._normalImage) {
- this._normalImage.setVisible(true);
-
- if (this._selectedImage)
- this._selectedImage.setVisible(false);
-
- if (this._disabledImage)
- this._disabledImage.setVisible(false);
- }
- },
-
- /**
- * @param {Boolean} bEnabled
- */
- setEnabled:function (bEnabled) {
- if (this._isEnabled != bEnabled) {
- cc.MenuItem.prototype.setEnabled.call(this, bEnabled);
- this._updateImagesVisibility();
- }
- },
-
- _updateImagesVisibility:function () {
- var locNormalImage = this._normalImage, locSelImage = this._selectedImage, locDisImage = this._disabledImage;
- if (this._isEnabled) {
- if (locNormalImage)
- locNormalImage.setVisible(true);
- if (locSelImage)
- locSelImage.setVisible(false);
- if (locDisImage)
- locDisImage.setVisible(false);
- } else {
- if (locDisImage) {
- if (locNormalImage)
- locNormalImage.setVisible(false);
- if (locSelImage)
- locSelImage.setVisible(false);
- if (locDisImage)
- locDisImage.setVisible(true);
- } else {
- if (locNormalImage)
- locNormalImage.setVisible(true);
- if (locSelImage)
- locSelImage.setVisible(false);
- }
- }
- }
-});
-
-/**
- * create a menu item from sprite
- * @param {Image} normalSprite normal state image
- * @param {Image|Null} selectedSprite selected state image
- * @param {Image|cc.Node|Null} three disabled state image OR target node
- * @param {String|function|cc.Node|Null} four callback function name in string or actual function, OR target Node
- * @param {String|function|Null} five callback function name in string or actual function
- * @return {cc.MenuItemSprite}
- * @example
- * // Example
- * var item = cc.MenuItemSprite.create(normalImage)//create a menu item from a sprite with no functionality
- *
- * var item = cc.MenuItemSprite.create(normalImage, selectedImage)//create a menu Item, nothing will happen when clicked
- *
- * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, disabledImage)//same above, but with disabled state image
- *
- * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, 'callback', targetNode)//create a menu item, when clicked runs targetNode.callback()
- *
- * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, disabledImage, targetNode.callback, targetNode)
- * //same as above, but with disabled image, and passing in callback function
- */
-cc.MenuItemSprite.create = function (normalSprite, selectedSprite, three, four, five) {
- var len = arguments.length;
- normalSprite = arguments[0];
- selectedSprite = arguments[1];
- var disabledImage, target, callback;
- var ret = new cc.MenuItemSprite();
- //when you send 4 arguments, five is undefined
- if (len == 5) {
- disabledImage = arguments[2];
- callback = arguments[3];
- target = arguments[4];
- } else if (len == 4 && typeof arguments[3] === "function") {
- disabledImage = arguments[2];
- callback = arguments[3];
- } else if (len == 4 && typeof arguments[2] === "function") {
- target = arguments[3];
- callback = arguments[2];
- } else if (len <= 2) {
- disabledImage = arguments[2];
- }
- ret.initWithNormalSprite(normalSprite, selectedSprite, disabledImage, callback, target);
- return ret;
-};
-
-/**
- * cc.MenuItemImage accepts images as items.
- * The images has 3 different states:
- * - unselected image
- * - selected image
- * - disabled image
- *
- * For best results try that all images are of the same size
- * @class
- * @extends cc.MenuItemSprite
- */
-cc.MenuItemImage = cc.MenuItemSprite.extend(/** @lends cc.MenuItemImage# */{
- /**
- * sets the sprite frame for the normal image
- * @param {cc.SpriteFrame} frame
- */
- setNormalSpriteFrame:function (frame) {
- this.setNormalImage(cc.Sprite.createWithSpriteFrame(frame));
- },
-
- /**
- * sets the sprite frame for the selected image
- * @param {cc.SpriteFrame} frame
- */
- setSelectedSpriteFrame:function (frame) {
- this.setSelectedImage(cc.Sprite.createWithSpriteFrame(frame));
- },
-
- /**
- * sets the sprite frame for the disabled image
- * @param {cc.SpriteFrame} frame
- */
- setDisabledSpriteFrame:function (frame) {
- this.setDisabledImage(cc.Sprite.createWithSpriteFrame(frame));
- },
-
- /**
- * @param {string|null} normalImage
- * @param {string|null} selectedImage
- * @param {string|null} disabledImage
- * @param {function|string|null} callback
- * @param {cc.Node|null} target
- * @returns {boolean}
- */
- initWithNormalImage:function (normalImage, selectedImage, disabledImage, callback, target) {
- var normalSprite = null;
- var selectedSprite = null;
- var disabledSprite = null;
-
- if (normalImage) {
- normalSprite = cc.Sprite.create(normalImage);
- }
- if (selectedImage) {
- selectedSprite = cc.Sprite.create(selectedImage);
- }
- if (disabledImage) {
- disabledSprite = cc.Sprite.create(disabledImage);
- }
- return this.initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, callback, target);
- }
-});
-
-/**
- * creates a new menu item image
- * @param {String} normalImage file name for normal state
- * @param {String} selectedImage image for selected state
- * @param {String|cc.Node} three Disabled image OR allback function
- * @param {String|function|Null} four callback function, either name in string or pass the whole function OR the target
- * @param {cc.Node|String|function|Null} five cc.Node target to run callback when clicked
- * @return {cc.MenuItemImage}
- * @example
- * // Example
- * //create a dom menu item with normal and selected state, when clicked it will run the run function from gameScene object
- * var item = cc.MenuItemImage.create('normal.png', 'selected.png', 'run', gameScene)
- *
- * //same as above, but pass in the actual function and disabled image
- * var item = cc.MenuItemImage.create('normal.png', 'selected.png', 'disabled.png', gameScene.run, gameScene)
- */
-cc.MenuItemImage.create = function (normalImage, selectedImage, three, four, five) {
- if (arguments.length == 0) {
- return cc.MenuItemImage.create(null, null, null, null, null);
- }
- if (arguments.length == 3) {
- return cc.MenuItemImage.create(normalImage, selectedImage, null, three, null);
- }
- if (arguments.length == 4) {
- return cc.MenuItemImage.create(normalImage, selectedImage, null, three, four);
- }
- var ret = new cc.MenuItemImage();
- if (ret.initWithNormalImage(normalImage, selectedImage, three, four, five))
- return ret;
- return null;
-};
-
-
-/**
- * A simple container class that "toggles" it's inner items
- * The inner items can be any MenuItem
- * @class
- * @extends cc.MenuItem
- */
-cc.MenuItemToggle = cc.MenuItem.extend(/** @lends cc.MenuItemToggle# */{
- _selectedIndex:0,
- _subItems:null,
- _opacity:null,
- _color:null,
-
- ctor: function(){
- cc.MenuItem.prototype.ctor.call(this);
- this._selectedIndex = 0;
- this._subItems = [];
- this._opacity = 0;
- this._color = cc.white();
- },
-
- /**
- * @return {Number}
- */
- getOpacity:function () {
- return this._opacity;
- },
-
- /**
- * @param {Number} Opacity
- */
- setOpacity:function (Opacity) {
- this._opacity = Opacity;
- if (this._subItems && this._subItems.length > 0) {
- for (var it = 0; it < this._subItems.length; it++) {
- this._subItems[it].setOpacity(Opacity);
- }
- }
- },
-
- /**
- * @return {cc.Color3B}
- */
- getColor:function () {
- return this._color;
- },
-
- /**
- * @param {cc.Color3B} Color
- */
- setColor:function (Color) {
- this._color = Color;
- if (this._subItems && this._subItems.length > 0) {
- for (var it = 0; it < this._subItems.length; it++) {
- this._subItems[it].setColor(Color);
- }
- }
- },
-
- /**
- * @return {Number}
- */
- getSelectedIndex:function () {
- return this._selectedIndex;
- },
-
- /**
- * @param {Number} SelectedIndex
- */
- setSelectedIndex:function (SelectedIndex) {
- if (SelectedIndex != this._selectedIndex) {
- this._selectedIndex = SelectedIndex;
- var currItem = this.getChildByTag(cc.CURRENT_ITEM);
- if (currItem)
- currItem.removeFromParent(false);
-
- var item = this._subItems[this._selectedIndex];
- this.addChild(item, 0, cc.CURRENT_ITEM);
- var s = item.getContentSize();
- this.setContentSize(s);
- item.setPosition(s.width / 2, s.height / 2);
- }
- },
-
- /**
- * similar to get children
- * @return {cc.MenuItem}
- */
- getSubItems:function () {
- return this._subItems;
- },
-
- /**
- * @param {cc.MenuItem} SubItems
- */
- setSubItems:function (SubItems) {
- this._subItems = SubItems;
- },
-
- /**
- * @param {cc.MenuItem} args[0...last-2] the rest in the array are cc.MenuItems
- * @param {function|String} args[last-1] the second item in the args array is the callback
- * @param {cc.Node} args[last] the first item in the args array is a target
- * @return {Boolean}
- */
- initWithItems:function (args) {
- var l = args.length;
- // passing callback.
- if (typeof args[args.length-2] === 'function') {
- this.initWithCallback( args[args.length-2], args[args.length-1] );
- l = l-2;
- } else if(typeof args[args.length-1] === 'function'){
- this.initWithCallback( args[args.length-1], null );
- l = l-1;
- } else {
- this.initWithCallback(null, null);
- }
-
- this._subItems = [];
- for (var i = 0; i < l; i++) {
- if (args[i])
- this._subItems.push(args[i]);
- }
- this._selectedIndex = cc.UINT_MAX;
- this.setSelectedIndex(0);
-
- this.setCascadeColorEnabled(true);
- this.setCascadeOpacityEnabled(true);
-
- return true;
- },
-
- /**
- * @param {cc.MenuItem} item
- */
- addSubItem:function (item) {
- this._subItems.push(item);
- },
-
- /**
- * activate the menu item
- */
- activate:function () {
- // update index
- if (this._isEnabled) {
- var newIndex = (this._selectedIndex + 1) % this._subItems.length;
- this.setSelectedIndex(newIndex);
- }
- cc.MenuItem.prototype.activate.call(this);
- },
-
- /**
- * menu item is selected (runs callback)
- */
- selected:function () {
- cc.MenuItem.prototype.selected.call(this);
- this._subItems[this._selectedIndex].selected();
- },
-
- /**
- * menu item goes back to unselected state
- */
- unselected:function () {
- cc.MenuItem.prototype.unselected.call(this);
- this._subItems[this._selectedIndex].unselected();
- },
-
- /**
- * @param {Boolean} enabled
- */
- setEnabled:function (enabled) {
- if (this._isEnabled != enabled) {
- cc.MenuItem.prototype.setEnabled.call(this, enabled);
- var locItems = this._subItems;
- if (locItems && locItems.length > 0) {
- for (var it = 0; it < locItems.length; it++)
- locItems[it].setEnabled(enabled);
- }
- }
- },
-
- /**
- * returns the selected item
- * @return {cc.MenuItem}
- */
- selectedItem:function () {
- return this._subItems[this._selectedIndex];
- },
-
- onEnter:function () {
- cc.Node.prototype.onEnter.call(this);
- this.setSelectedIndex(this._selectedIndex);
- }
-});
-
-/**
- * create a simple container class that "toggles" it's inner items
- * The inner items can be any MenuItem
- * @return {cc.MenuItemToggle}
- * @example
- * // Example
- *
- * //create a toggle item with 2 menu items (which you can then toggle between them later)
- * var toggler = cc.MenuItemToggle.create( cc.MenuItemFont.create("On"), cc.MenuItemFont.create("Off"), this.callback, this)
- * //Note: the first param is the target, the second is the callback function, afterwards, you can pass in any number of menuitems
- *
- * //if you pass only 1 variable, then it must be a cc.MenuItem
- * var notYetToggler = cc.MenuItemToggle.create(cc.MenuItemFont.create("On"));//it is useless right now, until you add more stuff to it
- * notYetToggler.addSubItem(cc.MenuItemFont.create("Off"));
- * //this is useful for constructing a toggler without a callback function (you wish to control the behavior from somewhere else)
- */
-cc.MenuItemToggle.create = function (/*Multiple arguments follow*/) {
- if((arguments.length > 0) && (arguments[arguments.length-1] == null))
- cc.log("parameters should not be ending with null in Javascript");
- var ret = new cc.MenuItemToggle();
- ret.initWithItems(arguments);
- return ret;
-};
diff --git a/cocos2d/menu_nodes/CCMenu.js b/cocos2d/menus/CCMenu.js
similarity index 54%
rename from cocos2d/menu_nodes/CCMenu.js
rename to cocos2d/menus/CCMenu.js
index f2c5f4bcf4..e3edd737ee 100644
--- a/cocos2d/menu_nodes/CCMenu.js
+++ b/cocos2d/menus/CCMenu.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -46,80 +46,89 @@ cc.MENU_HANDLER_PRIORITY = -128;
cc.DEFAULT_PADDING = 5;
/**
- * Features and Limitation:
+ *
Features and Limitation:
* - You can add MenuItem objects in runtime using addChild:
- * - But the only accecpted children are MenuItem objects
+ * - But the only accepted children are MenuItem objects
* @class
- * @extends cc.LayerRGBA
+ * @extends cc.Layer
+ * @param {...cc.MenuItem|null} menuItems
+ * @example
+ * var layer = new cc.Menu(menuitem1, menuitem2, menuitem3);
*/
-cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
- _color:null,
- _enabled:false,
- _opacity:0,
- _selectedItem:null,
- _state:-1,
-
- ctor:function(){
- cc.LayerRGBA.prototype.ctor.call(this);
- this._color = cc.white();
- this._enabled = false;
- this._opacity = 255;
- this._selectedItem = null;
- this._state = -1;
- },
+cc.Menu = cc.Layer.extend(/** @lends cc.Menu# */{
+ enabled: false,
- /**
- * @return {cc.Color3B}
- */
- getColor:function () {
- return this._color;
- },
+ _selectedItem: null,
+ _state: -1,
+ _touchListener: null,
+ _className: "Menu",
/**
- * @param {cc.Color3B} color
+ * Constructor of cc.Menu override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {...cc.MenuItem|null} menuItems
*/
- setColor:function (color) {
- this._color = color;
- var locChildren = this._children;
- if (locChildren && locChildren.length > 0) {
- for (var i = 0; i < locChildren.length; i++)
- locChildren[i].setColor(color);
- }
- },
+ ctor: function (menuItems) {
+ cc.Layer.prototype.ctor.call(this);
+ this._color = cc.color.WHITE;
+ this.enabled = false;
+ this._opacity = 255;
+ this._selectedItem = null;
+ this._state = -1;
- /**
- * @return {Number}
- */
- getOpacity:function () {
- return this._opacity;
+ this._touchListener = cc.EventListener.create({
+ event: cc.EventListener.TOUCH_ONE_BY_ONE,
+ swallowTouches: true,
+ onTouchBegan: this._onTouchBegan,
+ onTouchMoved: this._onTouchMoved,
+ onTouchEnded: this._onTouchEnded,
+ onTouchCancelled: this._onTouchCancelled
+ });
+
+ var argc = arguments.length, items;
+ if (menuItems instanceof Array) {
+ items = menuItems;
+ }
+ else if (argc === 0) {
+ items = [];
+ }
+ else if (argc > 0) {
+ items = [];
+ for (var i = 0; i < argc; i++) {
+ if (arguments[i])
+ items.push(arguments[i]);
+ }
+ }
+ this.initWithArray(items);
},
-
/**
- * @param {Number} opa
+ *
+ * Event callback that is invoked every time when CCMenu enters the 'stage'.
+ * If the CCMenu enters the 'stage' with a transition, this event is called when the transition starts.
+ * During onEnter you can't access a "sister/brother" node.
+ * If you override onEnter, you must call its parent's onEnter function with this._super().
+ *
*/
- setOpacity:function (opa) {
- this._opacity = opa;
- var locChildren = this._children;
- if (locChildren && locChildren.length > 0) {
- for (var i = 0; i < locChildren.length; i++)
- locChildren[i].setOpacity(opa);
- }
+ onEnter: function () {
+ var locListener = this._touchListener;
+ if (!locListener._isRegistered())
+ cc.eventManager.addListener(locListener, this);
+ cc.Node.prototype.onEnter.call(this);
},
/**
* return whether or not the menu will receive events
* @return {Boolean}
*/
- isEnabled:function () {
- return this._enabled;
+ isEnabled: function () {
+ return this.enabled;
},
/**
* set whether or not the menu will receive events
* @param {Boolean} enabled
*/
- setEnabled:function (enabled) {
- this._enabled = enabled;
+ setEnabled: function (enabled) {
+ this.enabled = enabled;
},
/**
@@ -127,7 +136,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
* @param {Array} args
* @return {Boolean}
*/
- initWithItems:function (args) {
+ initWithItems: function (args) {
var pArray = [];
if (args) {
for (var i = 0; i < args.length; i++) {
@@ -141,51 +150,64 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
/**
* initializes a cc.Menu with a Array of cc.MenuItem objects
+ * @param {Array} arrayOfItems array Of cc.MenuItem Items
+ * @return {Boolean}
*/
- initWithArray:function (arrayOfItems) {
- if (this.init()) {
- this.setTouchPriority(cc.MENU_HANDLER_PRIORITY);
- this.setTouchMode(cc.TOUCH_ONE_BY_ONE);
- this.setTouchEnabled(true);
- this._enabled = true;
+ initWithArray: function (arrayOfItems) {
+ if (cc.Layer.prototype.init.call(this)) {
+ this.enabled = true;
// menu in the center of the screen
- var winSize = cc.Director.getInstance().getWinSize();
- this.ignoreAnchorPointForPosition(true);
- this.setAnchorPoint(cc.p(0.5, 0.5));
- this.setContentSize(winSize);
+ var winSize = cc.winSize;
this.setPosition(winSize.width / 2, winSize.height / 2);
+ this.setContentSize(winSize);
+ this.setAnchorPoint(0.5, 0.5);
+ this.ignoreAnchorPointForPosition(true);
if (arrayOfItems) {
for (var i = 0; i < arrayOfItems.length; i++)
- this.addChild(arrayOfItems[i],i);
+ this.addChild(arrayOfItems[i], i);
}
this._selectedItem = null;
this._state = cc.MENU_STATE_WAITING;
// enable cascade color and opacity on menus
- this.setCascadeColorEnabled(true);
- this.setCascadeOpacityEnabled(true);
+ this.cascadeColor = true;
+ this.cascadeOpacity = true;
+
return true;
}
return false;
},
/**
+ * add a child for cc.Menu
* @param {cc.Node} child
- * @param {Number|Null} [zOrder=]
- * @param {Number|Null} [tag=]
+ * @param {Number|Null} [zOrder=] zOrder for the child
+ * @param {Number|Null} [tag=] tag for the child
*/
- addChild:function (child, zOrder, tag) {
- cc.Assert((child instanceof cc.MenuItem), "Menu only supports MenuItem objects as children");
+ addChild: function (child, zOrder, tag) {
+ if (!(child instanceof cc.MenuItem))
+ throw new Error("cc.Menu.addChild() : Menu only supports MenuItem objects as children");
cc.Layer.prototype.addChild.call(this, child, zOrder, tag);
},
+ updateAlign: function () {
+ switch (this._align) {
+ case 'vertically':
+ this.alignItemsVertically();
+ break;
+ case 'horizontally':
+ this.alignItemsHorizontally();
+ break;
+ }
+ },
+
/**
* align items vertically with default padding
*/
- alignItemsVertically:function () {
+ alignItemsVertically: function () {
this.alignItemsVerticallyWithPadding(cc.DEFAULT_PADDING);
},
@@ -193,18 +215,19 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
* align items vertically with specified padding
* @param {Number} padding
*/
- alignItemsVerticallyWithPadding:function (padding) {
+ alignItemsVerticallyWithPadding: function (padding) {
+ this._align = 'vertically';
var height = -padding, locChildren = this._children, len, i, locScaleY, locHeight, locChild;
if (locChildren && locChildren.length > 0) {
for (i = 0, len = locChildren.length; i < len; i++)
- height += locChildren[i].getContentSize().height * locChildren[i].getScaleY() + padding;
+ height += locChildren[i].height * locChildren[i].scaleY + padding;
var y = height / 2.0;
for (i = 0, len = locChildren.length; i < len; i++) {
locChild = locChildren[i];
- locHeight = locChild.getContentSize().height;
- locScaleY = locChild.getScaleY();
+ locHeight = locChild.height;
+ locScaleY = locChild.scaleY;
locChild.setPosition(0, y - locHeight * locScaleY / 2);
y -= locHeight * locScaleY + padding;
}
@@ -214,7 +237,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
/**
* align items horizontally with default padding
*/
- alignItemsHorizontally:function () {
+ alignItemsHorizontally: function () {
this.alignItemsHorizontallyWithPadding(cc.DEFAULT_PADDING);
},
@@ -222,18 +245,19 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
* align items horizontally with specified padding
* @param {Number} padding
*/
- alignItemsHorizontallyWithPadding:function (padding) {
+ alignItemsHorizontallyWithPadding: function (padding) {
+ this._align = 'horizontally';
var width = -padding, locChildren = this._children, i, len, locScaleX, locWidth, locChild;
if (locChildren && locChildren.length > 0) {
for (i = 0, len = locChildren.length; i < len; i++)
- width += locChildren[i].getContentSize().width * locChildren[i].getScaleX() + padding;
+ width += locChildren[i].width * locChildren[i].scaleX + padding;
var x = -width / 2.0;
for (i = 0, len = locChildren.length; i < len; i++) {
locChild = locChildren[i];
- locScaleX = locChild.getScaleX();
- locWidth = locChildren[i].getContentSize().width;
+ locScaleX = locChild.scaleX;
+ locWidth = locChildren[i].width;
locChild.setPosition(x + locWidth * locScaleX / 2, 0);
x += locWidth * locScaleX + padding;
}
@@ -248,12 +272,12 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
*
* menu.alignItemsInColumns(3,3)//this creates 2 columns, each have 3 items
*/
- alignItemsInColumns:function (/*Multiple Arguments*/) {
- if((arguments.length > 0) && (arguments[arguments.length-1] == null))
+ alignItemsInColumns: function (/*Multiple Arguments*/) {
+ if ((arguments.length > 0) && (arguments[arguments.length - 1] == null))
cc.log("parameters should not be ending with null in Javascript");
- var rows = [];
- for (var i = 0; i < arguments.length; i++) {
+ var i, rows = [];
+ for (i = 0; i < arguments.length; i++) {
rows.push(arguments[i]);
}
var height = -5;
@@ -264,13 +288,15 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
var locChildren = this._children;
if (locChildren && locChildren.length > 0) {
for (i = 0, len = locChildren.length; i < len; i++) {
- cc.Assert(row < rows.length, "");
+ if (row >= rows.length)
+ continue;
rowColumns = rows[row];
// can not have zero columns on a row
- cc.Assert(rowColumns, "");
+ if (!rowColumns)
+ continue;
- tmp = locChildren[i].getContentSize().height;
+ tmp = locChildren[i].height;
rowHeight = ((rowHeight >= tmp || isNaN(tmp)) ? rowHeight : tmp);
++columnsOccupied;
@@ -284,8 +310,8 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
}
}
// check if too many rows/columns for available menu items
- cc.Assert(!columnsOccupied, "");
- var winSize = cc.Director.getInstance().getWinSize();
+ //cc.assert(!columnsOccupied, ""); //?
+ var winSize = cc.director.getWinSize();
row = 0;
rowHeight = 0;
@@ -297,13 +323,13 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
if (locChildren && locChildren.length > 0) {
for (i = 0, len = locChildren.length; i < len; i++) {
var child = locChildren[i];
- if (rowColumns == 0) {
+ if (rowColumns === 0) {
rowColumns = rows[row];
w = winSize.width / (1 + rowColumns);
x = w;
}
- tmp = child.getContentSize().height;
+ tmp = child._getHeight();
rowHeight = ((rowHeight >= tmp || isNaN(tmp)) ? rowHeight : tmp);
child.setPosition(x - winSize.width / 2, y - tmp / 2);
@@ -322,16 +348,17 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
},
/**
* align menu items in rows
+ * @param {Number}
* @example
* // Example
* menu.alignItemsInRows(5,3)//this will align items to 2 rows, first row with 5 items, second row with 3
*
* menu.alignItemsInRows(4,4,4,4)//this creates 4 rows each have 4 items
*/
- alignItemsInRows:function (/*Multiple arguments*/) {
- if((arguments.length > 0) && (arguments[arguments.length-1] == null))
+ alignItemsInRows: function (/*Multiple arguments*/) {
+ if ((arguments.length > 0) && (arguments[arguments.length - 1] == null))
cc.log("parameters should not be ending with null in Javascript");
- var columns = [], i;
+ var i, columns = [];
for (i = 0; i < arguments.length; i++) {
columns.push(arguments[i]);
}
@@ -343,25 +370,26 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
var column = 0;
var columnWidth = 0;
var rowsOccupied = 0;
- var columnRows, child, len, tmp, locContentSize;
+ var columnRows, child, len, tmp;
var locChildren = this._children;
if (locChildren && locChildren.length > 0) {
for (i = 0, len = locChildren.length; i < len; i++) {
child = locChildren[i];
// check if too many menu items for the amount of rows/columns
- cc.Assert(column < columns.length, "");
+ if (column >= columns.length)
+ continue;
columnRows = columns[column];
// can't have zero rows on a column
- cc.Assert(columnRows, "");
+ if (!columnRows)
+ continue;
// columnWidth = fmaxf(columnWidth, [item contentSize].width);
- locContentSize = child.getContentSize();
- tmp = locContentSize.width;
+ tmp = child.width;
columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp);
- columnHeight += (locContentSize.height + 5);
+ columnHeight += (child.height + 5);
++rowsOccupied;
if (rowsOccupied >= columnRows) {
@@ -377,9 +405,8 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
}
}
// check if too many rows/columns for available menu items.
- cc.Assert(!rowsOccupied, "");
-
- var winSize = cc.Director.getInstance().getWinSize();
+ //cc.assert(!rowsOccupied, "");
+ var winSize = cc.director.getWinSize();
column = 0;
columnWidth = 0;
@@ -390,19 +417,18 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
if (locChildren && locChildren.length > 0) {
for (i = 0, len = locChildren.length; i < len; i++) {
child = locChildren[i];
- if (columnRows == 0) {
+ if (columnRows === 0) {
columnRows = columns[column];
y = columnHeights[column];
}
// columnWidth = fmaxf(columnWidth, [item contentSize].width);
- locContentSize = child.getContentSize();
- tmp = locContentSize.width;
+ tmp = child._getWidth();
columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp);
child.setPosition(x + columnWidths[column] / 2, y - winSize.height / 2);
- y -= locContentSize.height + 10;
+ y -= child.height + 10;
++rowsOccupied;
if (rowsOccupied >= columnRows) {
@@ -417,118 +443,127 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
},
/**
- * make the menu clickable
+ * remove a child from cc.Menu
+ * @param {cc.Node} child the child you want to remove
+ * @param {boolean} cleanup whether to cleanup
*/
- registerWithTouchDispatcher:function () {
- cc.registerTargetedDelegate(this.getTouchPriority(), true, this);
- },
-
- /**
- * @param {cc.Node} child
- * @param {boolean} cleanup
- */
- removeChild:function(child, cleanup){
- if(child== null)
+ removeChild: function (child, cleanup) {
+ if (child == null)
+ return;
+ if (!(child instanceof cc.MenuItem)) {
+ cc.log("cc.Menu.removeChild():Menu only supports MenuItem objects as children");
return;
+ }
- cc.Assert((child instanceof cc.MenuItem), "Menu only supports MenuItem objects as children");
- if (this._selectedItem == child)
+ if (this._selectedItem === child)
this._selectedItem = null;
cc.Node.prototype.removeChild.call(this, child, cleanup);
},
- /**
- * @param {cc.Touch} touch
- * @param {Object} e
- * @return {Boolean}
- */
- onTouchBegan:function (touch, e) {
- if (this._state != cc.MENU_STATE_WAITING || !this._visible || !this._enabled) {
+ _onTouchBegan: function (touch, event) {
+ var target = event.getCurrentTarget();
+ if (target._state !== cc.MENU_STATE_WAITING || !target._visible || !target.enabled)
return false;
- }
- for (var c = this._parent; c != null; c = c.getParent()) {
+ for (var c = target.parent; c != null; c = c.parent) {
if (!c.isVisible())
return false;
}
- this._selectedItem = this._itemForTouch(touch);
- if (this._selectedItem) {
- this._state = cc.MENU_STATE_TRACKING_TOUCH;
- this._selectedItem.selected();
+ target._selectedItem = target._itemForTouch(touch);
+ if (target._selectedItem) {
+ target._state = cc.MENU_STATE_TRACKING_TOUCH;
+ target._selectedItem.selected();
+ target._selectedItem.setNodeDirty();
return true;
}
return false;
},
- /**
- * when a touch ended
- */
- onTouchEnded:function (touch, e) {
- cc.Assert(this._state == cc.MENU_STATE_TRACKING_TOUCH, "[Menu onTouchEnded] -- invalid state");
- if (this._selectedItem) {
- this._selectedItem.unselected();
- this._selectedItem.activate();
+ _onTouchEnded: function (touch, event) {
+ var target = event.getCurrentTarget();
+ if (target._state !== cc.MENU_STATE_TRACKING_TOUCH) {
+ cc.log("cc.Menu.onTouchEnded(): invalid state");
+ return;
}
- this._state = cc.MENU_STATE_WAITING;
+ if (target._selectedItem) {
+ target._selectedItem.unselected();
+ target._selectedItem.setNodeDirty();
+ target._selectedItem.activate();
+ }
+ target._state = cc.MENU_STATE_WAITING;
},
- /**
- * touch cancelled
- */
- onTouchCancelled:function (touch, e) {
- cc.Assert(this._state == cc.MENU_STATE_TRACKING_TOUCH, "[Menu onTouchCancelled] -- invalid state");
- if (this._selectedItem) {
- this._selectedItem.unselected();
+ _onTouchCancelled: function (touch, event) {
+ var target = event.getCurrentTarget();
+ if (target._state !== cc.MENU_STATE_TRACKING_TOUCH) {
+ cc.log("cc.Menu.onTouchCancelled(): invalid state");
+ return;
+ }
+ if (target._selectedItem) {
+ target._selectedItem.unselected();
+ target._selectedItem.setNodeDirty();
}
- this._state = cc.MENU_STATE_WAITING;
+ target._state = cc.MENU_STATE_WAITING;
},
- /**
- * touch moved
- * @param {cc.Touch} touch
- * @param {Object} e
- */
- onTouchMoved:function (touch, e) {
- cc.Assert(this._state == cc.MENU_STATE_TRACKING_TOUCH, "[Menu onTouchMoved] -- invalid state");
- var currentItem = this._itemForTouch(touch);
- if (currentItem != this._selectedItem) {
- if (this._selectedItem) {
- this._selectedItem.unselected();
+ _onTouchMoved: function (touch, event) {
+ var target = event.getCurrentTarget();
+ if (target._state !== cc.MENU_STATE_TRACKING_TOUCH) {
+ cc.log("cc.Menu.onTouchMoved(): invalid state");
+ return;
+ }
+ var currentItem = target._itemForTouch(touch);
+ if (currentItem !== target._selectedItem) {
+ if (target._selectedItem) {
+ target._selectedItem.unselected();
+ target._selectedItem.setNodeDirty();
}
- this._selectedItem = currentItem;
- if (this._selectedItem) {
- this._selectedItem.selected();
+ target._selectedItem = currentItem;
+ if (target._selectedItem) {
+ target._selectedItem.selected();
+ target._selectedItem.setNodeDirty();
}
}
},
/**
- * custom on exit
+ *
+ * callback that is called every time the cc.Menu leaves the 'stage'.
+ * If the cc.Menu leaves the 'stage' with a transition, this callback is called when the transition finishes.
+ * During onExit you can't access a sibling node.
+ * If you override onExit, you shall call its parent's onExit with this._super().
+ *
*/
- onExit:function () {
- if (this._state == cc.MENU_STATE_TRACKING_TOUCH) {
- if(this._selectedItem){
+ onExit: function () {
+ if (this._state === cc.MENU_STATE_TRACKING_TOUCH) {
+ if (this._selectedItem) {
this._selectedItem.unselected();
this._selectedItem = null;
}
this._state = cc.MENU_STATE_WAITING;
}
- cc.Layer.prototype.onExit.call(this);
+ cc.Node.prototype.onExit.call(this);
},
-
- setOpacityModifyRGB:function (value) {
+ /**
+ * only use for jsbinding
+ * @param value
+ */
+ setOpacityModifyRGB: function (value) {
},
-
- isOpacityModifyRGB:function () {
+ /**
+ * only use for jsbinding
+ * @returns {boolean}
+ */
+ isOpacityModifyRGB: function () {
return false;
},
- _itemForTouch:function (touch) {
+ _itemForTouch: function (touch) {
var touchLocation = touch.getLocation();
var itemChildren = this._children, locItemChild;
if (itemChildren && itemChildren.length > 0) {
- for (var i = 0; i < itemChildren.length; i++) {
+ for (var i = itemChildren.length - 1; i >= 0; i--) {
locItemChild = itemChildren[i];
if (locItemChild.isVisible() && locItemChild.isEnabled()) {
var local = locItemChild.convertToNodeSpace(touchLocation);
@@ -541,39 +576,33 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{
}
}
return null;
- },
-
- /**
- * set event handler priority. By default it is: kCCMenuTouchPriority
- * @param {Number} newPriority
- */
- setHandlerPriority:function (newPriority) {
- cc.Director.getInstance().getTouchDispatcher().setPriority(newPriority, this);
}
});
+var _p = cc.Menu.prototype;
+
+// Extended properties
+/** @expose */
+_p.enabled;
+
/**
* create a new menu
+ * @deprecated since v3.0, please use new cc.Menu(menuitem1, menuitem2, menuitem3) to create a new menu
+ * @param {...cc.MenuItem|null} menuItems
+ * todo: need to use new
* @return {cc.Menu}
- * @example
- * // Example
- * //there is no limit on how many menu item you can pass in
- * var myMenu = cc.Menu.create(menuitem1, menuitem2, menuitem3);
*/
-cc.Menu.create = function (/*Multiple Arguments*/) {
- if((arguments.length > 0) && (arguments[arguments.length-1] == null))
+cc.Menu.create = function (menuItems) {
+ var argc = arguments.length;
+ if ((argc > 0) && (arguments[argc - 1] == null))
cc.log("parameters should not be ending with null in Javascript");
- var ret = new cc.Menu();
-
- if (arguments.length == 0) {
- ret.initWithItems(null, null);
- } else if (arguments.length == 1) {
- if (arguments[0] instanceof Array) {
- ret.initWithArray(arguments[0]);
- return ret;
- }
- }
- ret.initWithItems(arguments);
+ var ret;
+ if (argc === 0)
+ ret = new cc.Menu();
+ else if (argc === 1)
+ ret = new cc.Menu(menuItems);
+ else
+ ret = new cc.Menu(Array.prototype.slice.call(arguments, 0));
return ret;
};
diff --git a/cocos2d/menus/CCMenuItem.js b/cocos2d/menus/CCMenuItem.js
new file mode 100644
index 0000000000..de25beecd9
--- /dev/null
+++ b/cocos2d/menus/CCMenuItem.js
@@ -0,0 +1,1371 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc._globalFontSize = cc.ITEM_SIZE;
+cc._globalFontName = "Arial";
+cc._globalFontNameRelease = false;
+
+/**
+ * Subclass cc.MenuItem (or any subclass) to create your custom cc.MenuItem objects.
+ * @class
+ * @extends cc.Node
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ */
+cc.MenuItem = cc.Node.extend(/** @lends cc.MenuItem# */{
+ _enabled: false,
+ _target: null,
+ _callback: null,
+ _isSelected: false,
+ _className: "MenuItem",
+
+ /**
+ * Constructor of cc.MenuItem
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ */
+ ctor: function (callback, target) {
+ var nodeP = cc.Node.prototype;
+ nodeP.ctor.call(this);
+ this._target = null;
+ this._callback = null;
+ this._isSelected = false;
+ this._enabled = false;
+
+ nodeP.setAnchorPoint.call(this, 0.5, 0.5);
+ this._target = target || null;
+ this._callback = callback || null;
+ if (this._callback) {
+ this._enabled = true;
+ }
+ },
+
+ /**
+ * return whether MenuItem is selected
+ * @return {Boolean}
+ */
+ isSelected: function () {
+ return this._isSelected;
+ },
+ /**
+ * only use for jsbinding
+ * @param value
+ */
+ setOpacityModifyRGB: function (value) {
+ },
+ /**
+ * only use for jsbinding
+ * @returns {boolean}
+ */
+ isOpacityModifyRGB: function () {
+ return false;
+ },
+
+ /**
+ * set the target/selector of the menu item
+ * @param {function|String} selector
+ * @param {cc.Node} rec
+ * @deprecated since v3.0
+ */
+ setTarget: function (selector, rec) {
+ this._target = rec;
+ this._callback = selector;
+ },
+
+ /**
+ * return whether MenuItem is Enabled
+ * @return {Boolean}
+ */
+ isEnabled: function () {
+ return this._enabled;
+ },
+
+ /**
+ * set enable value of MenuItem
+ * @param {Boolean} enable
+ */
+ setEnabled: function (enable) {
+ this._enabled = enable;
+ },
+
+ /**
+ * initializes a cc.MenuItem with callback
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ * @return {Boolean}
+ */
+ initWithCallback: function (callback, target) {
+ this.anchorX = 0.5;
+ this.anchorY = 0.5;
+ this._target = target;
+ this._callback = callback;
+ this._enabled = true;
+ this._isSelected = false;
+ return true;
+ },
+
+ /**
+ * return rect value of cc.MenuItem
+ * @return {cc.Rect}
+ */
+ rect: function () {
+ var locPosition = this._position, locContentSize = this._contentSize, locAnchorPoint = this._anchorPoint;
+ return cc.rect(locPosition.x - locContentSize.width * locAnchorPoint.x,
+ locPosition.y - locContentSize.height * locAnchorPoint.y,
+ locContentSize.width, locContentSize.height);
+ },
+
+ /**
+ * set the cc.MenuItem selected same as setIsSelected(true)
+ */
+ selected: function () {
+ this._isSelected = true;
+ },
+
+ /**
+ * set the cc.MenuItem unselected same as setIsSelected(false)
+ */
+ unselected: function () {
+ this._isSelected = false;
+ },
+
+ /**
+ * set the callback to the menu item
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ */
+ setCallback: function (callback, target) {
+ this._target = target;
+ this._callback = callback;
+ },
+
+ /**
+ * call the selector with target
+ */
+ activate: function () {
+ if (this._enabled) {
+ var locTarget = this._target, locCallback = this._callback;
+ if (!locCallback)
+ return;
+ if (locTarget && cc.isString(locCallback)) {
+ locTarget[locCallback](this);
+ } else if (locTarget && cc.isFunction(locCallback)) {
+ locCallback.call(locTarget, this);
+ } else
+ locCallback(this);
+ }
+ }
+});
+
+var _p = cc.MenuItem.prototype;
+
+// Extended properties
+/** @expose */
+_p.enabled;
+cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled);
+
+/**
+ * creates an empty menu item with target and callback
+ * Not recommended to use the base class, should use more defined menu item classes
+ * @deprecated since v3.0, please use new cc.MenuItem(callback,target) instead
+ * @param {function|String} callback callback
+ * @param {cc.Node} target
+ * @return {cc.MenuItem}
+ */
+cc.MenuItem.create = function (callback, target) {
+ return new cc.MenuItem(callback, target);
+};
+
+/**
+ * Any cc.Node that supports the cc.LabelProtocol protocol can be added.
+ * Supported nodes:
+ * - cc.BitmapFontAtlas
+ * - cc.LabelAtlas
+ * - cc.LabelTTF
+ * @class
+ * @extends cc.MenuItem
+ * @param {cc.Node} label
+ * @param {function|String} selector
+ * @param {cc.Node} target
+ * @example
+ * var menuitemLabel = new cc.MenuItemLabel(label,selector,target);
+ *
+ * @property {String} string - Content string of label item
+ * @property {cc.Node} label - Label of label item
+ * @property {cc.Color} disabledColor - Color of label when it's disabled
+ */
+cc.MenuItemLabel = cc.MenuItem.extend(/** @lends cc.MenuItemLabel# */{
+ _disabledColor: null,
+ _label: null,
+ _originalScale: 0,
+ _colorBackup: null,
+
+ /**
+ * Constructor of cc.MenuItemLabel
+ * @param {cc.Node} label
+ * @param {function|String} selector
+ * @param {cc.Node} target
+ */
+ ctor: function (label, selector, target) {
+ cc.MenuItem.prototype.ctor.call(this, selector, target);
+ this._disabledColor = null;
+ this._label = null;
+ this._colorBackup = null;
+
+ if (label) {
+ this._originalScale = 1.0;
+ this._colorBackup = cc.color.WHITE;
+ this._disabledColor = cc.color(126, 126, 126);
+ this.setLabel(label);
+
+ if (label.textureLoaded && !label.textureLoaded()) {
+ label.addEventListener("load", function (sender) {
+ this.width = sender.width;
+ this.height = sender.height;
+ if (this.parent instanceof cc.Menu) {
+ this.parent.updateAlign();
+ }
+ }, this);
+ }
+
+ this.setCascadeColorEnabled(true);
+ this.setCascadeOpacityEnabled(true);
+ }
+ },
+
+ /**
+ * return the disable color for this cc.MenuItemLabel
+ * @return {cc.Color}
+ */
+ getDisabledColor: function () {
+ return this._disabledColor;
+ },
+
+ /**
+ * set the disable color for this cc.MenuItemLabel
+ * @param {cc.Color} color
+ */
+ setDisabledColor: function (color) {
+ this._disabledColor = color;
+ },
+
+ /**
+ * return label of cc.MenuItemLabel
+ * @return {cc.Node}
+ */
+ getLabel: function () {
+ return this._label;
+ },
+
+ /**
+ * set a label for cc.MenuItemLabel
+ * @param {cc.Node} label
+ */
+ setLabel: function (label) {
+ if (label) {
+ this.addChild(label);
+ label.anchorX = 0;
+ label.anchorY = 0;
+ this.width = label.width;
+ this.height = label.height;
+ label.setCascadeColorEnabled(true);
+ }
+
+ if (this._label) {
+ this.removeChild(this._label, true);
+ }
+
+ this._label = label;
+ },
+
+ /**
+ * set enable value to cc.MenuItemLabel
+ * @param {Boolean} enabled
+ */
+ setEnabled: function (enabled) {
+ if (this._enabled !== enabled) {
+ if (!enabled) {
+ this._colorBackup = this.color;
+ this.setColor(this._disabledColor);
+ } else {
+ this.setColor(this._colorBackup);
+ }
+ }
+ cc.MenuItem.prototype.setEnabled.call(this, enabled);
+ },
+
+ /**
+ * initializes a cc.MenuItemLabel with a label
+ * @param {cc.Node} label
+ * @param {function|String} selector
+ * @param {cc.Node} target
+ * @return {Boolean}
+ */
+ initWithLabel: function (label, selector, target) {
+ this.initWithCallback(selector, target);
+ this._originalScale = 1.0;
+ this._colorBackup = cc.color.WHITE;
+ this._disabledColor = cc.color(126, 126, 126);
+ this.setLabel(label);
+
+ this.setCascadeColorEnabled(true);
+ this.setCascadeOpacityEnabled(true);
+
+ return true;
+ },
+
+ /**
+ * set the string for cc.MenuItemLabel
+ * @param {String} label
+ */
+ setString: function (label) {
+ this._label.string = label;
+ this.width = this._label.width;
+ this.height = this._label.height;
+ },
+ /**
+ * return the string of cc.MenuItemLabel
+ * @returns {String}
+ */
+ getString: function () {
+ return this._label.string;
+ },
+
+ /**
+ * activate the menu item
+ */
+ activate: function () {
+ if (this._enabled) {
+ this.stopAllActions();
+ this.scale = this._originalScale;
+ cc.MenuItem.prototype.activate.call(this);
+ }
+ },
+
+ /**
+ * menu item is selected (runs callback)
+ */
+ selected: function () {
+ if (this._enabled) {
+ cc.MenuItem.prototype.selected.call(this);
+
+ var action = this.getActionByTag(cc.ZOOM_ACTION_TAG);
+ if (action)
+ this.stopAction(action);
+ else
+ this._originalScale = this.scale;
+
+ var zoomAction = cc.scaleTo(0.1, this._originalScale * 1.2);
+ zoomAction.setTag(cc.ZOOM_ACTION_TAG);
+ this.runAction(zoomAction);
+ }
+ },
+
+ /**
+ * menu item goes back to unselected state
+ */
+ unselected: function () {
+ if (this._enabled) {
+ cc.MenuItem.prototype.unselected.call(this);
+ this.stopActionByTag(cc.ZOOM_ACTION_TAG);
+ var zoomAction = cc.scaleTo(0.1, this._originalScale);
+ zoomAction.setTag(cc.ZOOM_ACTION_TAG);
+ this.runAction(zoomAction);
+ }
+ }
+});
+
+var _p = cc.MenuItemLabel.prototype;
+
+// Extended properties
+/** @expose */
+_p.string;
+cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
+/** @expose */
+_p.disabledColor;
+cc.defineGetterSetter(_p, "disabledColor", _p.getDisabledColor, _p.setDisabledColor);
+/** @expose */
+_p.label;
+cc.defineGetterSetter(_p, "label", _p.getLabel, _p.setLabel);
+
+
+/**
+ * @deprecated since v3.0 ,please use new cc.MenuItemLabel(label,selector,target) instead
+ * @param {cc.Node} label
+ * @param {function|String|Null} [selector=]
+ * @param {cc.Node|Null} [target=]
+ * @return {cc.MenuItemLabel}
+ */
+cc.MenuItemLabel.create = function (label, selector, target) {
+ return new cc.MenuItemLabel(label, selector, target);
+};
+
+/**
+ * Helper class that creates a MenuItemLabel class with a LabelAtlas
+ * @class
+ * @extends cc.MenuItemLabel
+ * @param {String} value
+ * @param {String} charMapFile
+ * @param {Number} itemWidth
+ * @param {Number} itemHeight
+ * @param {String} startCharMap a single character
+ * @param {function|String|Null} callback
+ * @param {cc.Node|Null} target
+ * @example
+ * var menuItem = new cc.MenuItemAtlasFont(param1,param2...);
+ */
+cc.MenuItemAtlasFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemAtlasFont# */{
+
+ /**
+ * the contructor of cc.MenuItemAtlasFont
+ * @param {String} value
+ * @param {String} charMapFile
+ * @param {Number} itemWidth
+ * @param {Number} itemHeight
+ * @param {String} startCharMap a single character
+ * @param {function|String|Null} callback
+ * @param {cc.Node|Null} target
+ */
+ ctor: function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
+ var label;
+ if (value && value.length > 0) {
+ label = new cc.LabelAtlas(value, charMapFile, itemWidth, itemHeight, startCharMap);
+ }
+
+ cc.MenuItemLabel.prototype.ctor.call(this, label, callback, target);
+ },
+
+ /**
+ * initializes a cc.MenuItemAtlasFont with string
+ * @param {String} value
+ * @param {String} charMapFile
+ * @param {Number} itemWidth
+ * @param {Number} itemHeight
+ * @param {String} startCharMap a single character
+ * @param {function|String|Null} callback
+ * @param {cc.Node|Null} target
+ * @return {Boolean}
+ */
+ initWithString: function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
+ if (!value || value.length === 0)
+ throw new Error("cc.MenuItemAtlasFont.initWithString(): value should be non-null and its length should be greater than 0");
+
+ var label = new cc.LabelAtlas();
+ label.initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap);
+ if (this.initWithLabel(label, callback, target)) {
+ // do something ?
+ }
+ return true;
+ }
+});
+
+/**
+ * create menu item from string with font
+ * @deprecated since v3.0 ,please use new cc.MenuItemAtlasFont() instead.
+ * @param {String} value the text to display
+ * @param {String} charMapFile the character map file
+ * @param {Number} itemWidth
+ * @param {Number} itemHeight
+ * @param {String} startCharMap a single character
+ * @param {function|String|Null} [callback=null]
+ * @param {cc.Node|Null} [target=]
+ * @return {cc.MenuItemAtlasFont}
+ */
+cc.MenuItemAtlasFont.create = function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) {
+ return new cc.MenuItemAtlasFont(value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target);
+};
+
+/**
+ * Helper class that creates a CCMenuItemLabel class with a Label
+ * @class
+ * @extends cc.MenuItemLabel
+ * @param {String} value text for the menu item
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ * @example
+ * var menuItem = new cc.MenuItemFont(value, callback, target);
+ *
+ * @property {Number} fontSize - Font size of font item
+ * @property {String} fontName - Font name of font item
+ */
+cc.MenuItemFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemFont# */{
+ _fontSize: null,
+ _fontName: null,
+
+ /**
+ * Constructor of cc.MenuItemFont
+ * @param {String} value text for the menu item
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ */
+ ctor: function (value, callback, target) {
+ var label;
+ if (value && value.length > 0) {
+ this._fontName = cc._globalFontName;
+ this._fontSize = cc._globalFontSize;
+ label = new cc.LabelTTF(value, this._fontName, this._fontSize);
+ }
+ else {
+ this._fontSize = 0;
+ this._fontName = "";
+ }
+
+ cc.MenuItemLabel.prototype.ctor.call(this, label, callback, target);
+ },
+
+ /**
+ * initializes cc.MenuItemFont with string
+ * @param {String} value text for the menu item
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ * @return {Boolean}
+ */
+ initWithString: function (value, callback, target) {
+ if (!value || value.length === 0)
+ throw new Error("Value should be non-null and its length should be greater than 0");
+
+ this._fontName = cc._globalFontName;
+ this._fontSize = cc._globalFontSize;
+
+ var label = new cc.LabelTTF(value, this._fontName, this._fontSize);
+ if (this.initWithLabel(label, callback, target)) {
+ // do something ?
+ }
+ return true;
+ },
+
+ /**
+ * set the font size for cc.MenuItemFont
+ * @param {Number} s
+ */
+ setFontSize: function (s) {
+ this._fontSize = s;
+ this._recreateLabel();
+ },
+
+ /**
+ *return the font size of cc.MenuItemFont
+ * @return {Number}
+ */
+ getFontSize: function () {
+ return this._fontSize;
+ },
+
+ /**
+ * set the font name for cc.MenuItemFont
+ * @param {String} name
+ */
+ setFontName: function (name) {
+ this._fontName = name;
+ this._recreateLabel();
+ },
+
+ /**
+ * return the font name for cc.MenuItemFont
+ * @return {String}
+ */
+ getFontName: function () {
+ return this._fontName;
+ },
+
+ _recreateLabel: function () {
+ var label = new cc.LabelTTF(this._label.string, this._fontName, this._fontSize);
+ this.setLabel(label);
+ }
+});
+
+/**
+ * a shared function to set the fontSize for menuitem font
+ * @param {Number} fontSize
+ */
+cc.MenuItemFont.setFontSize = function (fontSize) {
+ cc._globalFontSize = fontSize;
+};
+
+/**
+ * a shared function to get the font size for menuitem font
+ * @return {Number}
+ */
+cc.MenuItemFont.fontSize = function () {
+ return cc._globalFontSize;
+};
+
+/**
+ * a shared function to set the fontsize for menuitem font
+ * @param name
+ */
+cc.MenuItemFont.setFontName = function (name) {
+ if (cc._globalFontNameRelease) {
+ cc._globalFontName = '';
+ }
+ cc._globalFontName = name;
+ cc._globalFontNameRelease = true;
+};
+
+var _p = cc.MenuItemFont.prototype;
+
+// Extended properties
+/** @expose */
+_p.fontSize;
+cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
+/** @expose */
+_p.fontName;
+cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
+
+
+/**
+ * a shared function to get the font name for menuitem font
+ * @return {String}
+ */
+cc.MenuItemFont.fontName = function () {
+ return cc._globalFontName;
+};
+
+/**
+ * create a menu item from string
+ * @deprecated since v3.0, please use new construction instead
+ * @param {String} value the text to display
+ * @param {String|function|Null} callback the callback to run, either in function name or pass in the actual function
+ * @param {cc.Node|Null} target the target to run callback
+ * @return {cc.MenuItemFont}
+ */
+cc.MenuItemFont.create = function (value, callback, target) {
+ return new cc.MenuItemFont(value, callback, target);
+};
+
+
+/**
+ * CCMenuItemSprite accepts CCNode objects as items.
+ * The images has 3 different states:
+ * - unselected image
+ * - selected image
+ * - disabled image
+ * @class
+ * @extends cc.MenuItem
+ * @param {Image|Null} normalSprite normal state image
+ * @param {Image|Null} selectedSprite selected state image
+ * @param {Image|cc.Node|Null} three disabled state image OR target node
+ * @param {String|function|cc.Node|Null} four callback function name in string or actual function, OR target Node
+ * @param {String|function|Null} five callback function name in string or actual function
+ *
+ * @example
+ * var item = new cc.MenuItemSprite(normalImage)//create a menu item from a sprite with no functionality
+ * var item = new cc.MenuItemSprite(normalImage, selectedImage)//create a menu Item, nothing will happen when clicked
+ * var item = new cc.MenuItemSprite(normalImage, SelectedImage, disabledImage)//same above, but with disabled state image
+ * var item = new cc.MenuItemSprite(normalImage, SelectedImage, 'callback', targetNode)//create a menu item, when clicked runs targetNode.callback()
+ * var item = new cc.MenuItemSprite(normalImage, SelectedImage, disabledImage, targetNode.callback, targetNode)
+ * //same as above, but with disabled image, and passing in callback function
+ *
+ * @property {cc.Sprite} normalImage - Sprite in normal state
+ * @property {cc.Sprite} selectedImage - Sprite in selected state
+ * @property {cc.Sprite} disabledImage - Sprite in disabled state
+ */
+cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{
+ _normalImage: null,
+ _selectedImage: null,
+ _disabledImage: null,
+
+ /**
+ * Constructor of cc.MenuItemSprite
+ * @param {Image|Null} normalSprite normal state image
+ * @param {Image|Null} selectedSprite selected state image
+ * @param {Image|cc.Node|Null} three disabled state image OR target node
+ * @param {String|function|cc.Node|Null} four callback function name in string or actual function, OR target Node
+ * @param {String|function|Null} five callback function name in string or actual function
+ */
+ ctor: function (normalSprite, selectedSprite, three, four, five) {
+ cc.MenuItem.prototype.ctor.call(this);
+ this._normalImage = null;
+ this._selectedImage = null;
+ this._disabledImage = null;
+ this._loader = new cc.Sprite.LoadManager();
+
+ if (normalSprite !== undefined) {
+ //normalSprite = normalSprite;
+ selectedSprite = selectedSprite || null;
+ var disabledImage, target, callback;
+ //when you send 4 arguments, five is undefined
+ if (five !== undefined) {
+ disabledImage = three;
+ callback = four;
+ target = five;
+ } else if (four !== undefined && cc.isFunction(four)) {
+ disabledImage = three;
+ callback = four;
+ } else if (four !== undefined && cc.isFunction(three)) {
+ target = four;
+ callback = three;
+ disabledImage = null;
+ } else if (three === undefined) {
+ disabledImage = null;
+ }
+
+ this._loader.clear();
+ if (normalSprite.textureLoaded && !normalSprite.textureLoaded()) {
+ this._loader.once(normalSprite, function () {
+ this.initWithNormalSprite(normalSprite, selectedSprite, disabledImage, callback, target);
+ }, this);
+ return false;
+ }
+
+ this.initWithNormalSprite(normalSprite, selectedSprite, disabledImage, callback, target);
+ return true;
+ }
+ },
+
+ /**
+ * return the normal status image(cc.Sprite)
+ * @return {cc.Sprite}
+ */
+ getNormalImage: function () {
+ return this._normalImage;
+ },
+
+ /**
+ * set the normal status image(cc.Sprite)
+ * @param {cc.Sprite} normalImage
+ */
+ setNormalImage: function (normalImage) {
+ if (this._normalImage === normalImage) {
+ return;
+ }
+ if (normalImage) {
+ this.addChild(normalImage, 0, cc.NORMAL_TAG);
+ normalImage.anchorX = 0;
+ normalImage.anchorY = 0;
+ }
+ if (this._normalImage) {
+ this.removeChild(this._normalImage, true);
+ }
+
+ this._normalImage = normalImage;
+ if(!this._normalImage)
+ return;
+
+ this.width = this._normalImage.width;
+ this.height = this._normalImage.height;
+ this._updateImagesVisibility();
+
+ if (normalImage.textureLoaded && !normalImage.textureLoaded()) {
+ normalImage.addEventListener("load", function (sender) {
+ this.width = sender.width;
+ this.height = sender.height;
+ if (this.parent instanceof cc.Menu) {
+ this.parent.updateAlign();
+ }
+ }, this);
+ }
+ },
+
+ /**
+ * return the selected status image(cc.Sprite) of cc.MenuItemSprite
+ * @return {cc.Sprite}
+ */
+ getSelectedImage: function () {
+ return this._selectedImage;
+ },
+
+ /**
+ * set the selected status image(cc.Sprite)
+ * @param {cc.Sprite} selectedImage
+ */
+ setSelectedImage: function (selectedImage) {
+ if (this._selectedImage === selectedImage)
+ return;
+
+ if (selectedImage) {
+ this.addChild(selectedImage, 0, cc.SELECTED_TAG);
+ selectedImage.anchorX = 0;
+ selectedImage.anchorY = 0;
+ }
+
+ if (this._selectedImage) {
+ this.removeChild(this._selectedImage, true);
+ }
+
+ this._selectedImage = selectedImage;
+ this._updateImagesVisibility();
+ },
+
+ /**
+ * return the disabled status of cc.MenuItemSprite
+ * @return {cc.Sprite}
+ */
+ getDisabledImage: function () {
+ return this._disabledImage;
+ },
+
+ /**
+ * set the disabled status image(cc.Sprite)
+ * @param {cc.Sprite} disabledImage
+ */
+ setDisabledImage: function (disabledImage) {
+ if (this._disabledImage === disabledImage)
+ return;
+
+ if (disabledImage) {
+ this.addChild(disabledImage, 0, cc.DISABLE_TAG);
+ disabledImage.anchorX = 0;
+ disabledImage.anchorY = 0;
+ }
+
+ if (this._disabledImage)
+ this.removeChild(this._disabledImage, true);
+
+ this._disabledImage = disabledImage;
+ this._updateImagesVisibility();
+ },
+
+ /**
+ * initializes cc.MenuItemSprite with a cc.Sprite
+ * @param {cc.Node} normalSprite
+ * @param {cc.Node} selectedSprite
+ * @param {cc.Node} disabledSprite
+ * @param {function|String} callback
+ * @param {cc.Node} target
+ * @return {Boolean}
+ */
+ initWithNormalSprite: function (normalSprite, selectedSprite, disabledSprite, callback, target) {
+ this._loader.clear();
+ if (normalSprite.textureLoaded && !normalSprite.textureLoaded()) {
+ this._loader.once(normalSprite, function () {
+ this.initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, callback, target);
+ }, this);
+ return false;
+ }
+ this.initWithCallback(callback, target);
+ this.setNormalImage(normalSprite);
+ this.setSelectedImage(selectedSprite);
+ this.setDisabledImage(disabledSprite);
+ var locNormalImage = this._normalImage;
+ if (locNormalImage) {
+ this.width = locNormalImage.width;
+ this.height = locNormalImage.height;
+ }
+ this.setCascadeColorEnabled(true);
+ this.setCascadeOpacityEnabled(true);
+ return true;
+ },
+
+ /**
+ * menu item is selected (runs callback)
+ */
+ selected: function () {
+ cc.MenuItem.prototype.selected.call(this);
+ if (this._normalImage) {
+ if (this._disabledImage)
+ this._disabledImage.visible = false;
+
+ if (this._selectedImage) {
+ this._normalImage.visible = false;
+ this._selectedImage.visible = true;
+ } else
+ this._normalImage.visible = true;
+ }
+ },
+
+ /**
+ * menu item goes back to unselected state
+ */
+ unselected: function () {
+ cc.MenuItem.prototype.unselected.call(this);
+ if (this._normalImage) {
+ this._normalImage.visible = true;
+
+ if (this._selectedImage)
+ this._selectedImage.visible = false;
+
+ if (this._disabledImage)
+ this._disabledImage.visible = false;
+ }
+ },
+
+ /**
+ * set cc.MenuItemSprite enable to receive the touch event
+ * @param {Boolean} bEnabled
+ */
+ setEnabled: function (bEnabled) {
+ if (this._enabled !== bEnabled) {
+ cc.MenuItem.prototype.setEnabled.call(this, bEnabled);
+ this._updateImagesVisibility();
+ }
+ },
+
+ _updateImagesVisibility: function () {
+ var locNormalImage = this._normalImage, locSelImage = this._selectedImage, locDisImage = this._disabledImage;
+ if (this._enabled) {
+ if (locNormalImage)
+ locNormalImage.visible = true;
+ if (locSelImage)
+ locSelImage.visible = false;
+ if (locDisImage)
+ locDisImage.visible = false;
+ } else {
+ if (locDisImage) {
+ if (locNormalImage)
+ locNormalImage.visible = false;
+ if (locSelImage)
+ locSelImage.visible = false;
+ if (locDisImage)
+ locDisImage.visible = true;
+ } else {
+ if (locNormalImage)
+ locNormalImage.visible = true;
+ if (locSelImage)
+ locSelImage.visible = false;
+ }
+ }
+ }
+});
+
+var _p = cc.MenuItemSprite.prototype;
+
+// Extended properties
+/** @expose */
+_p.normalImage;
+cc.defineGetterSetter(_p, "normalImage", _p.getNormalImage, _p.setNormalImage);
+/** @expose */
+_p.selectedImage;
+cc.defineGetterSetter(_p, "selectedImage", _p.getSelectedImage, _p.setSelectedImage);
+/** @expose */
+_p.disabledImage;
+cc.defineGetterSetter(_p, "disabledImage", _p.getDisabledImage, _p.setDisabledImage);
+
+/**
+ * create a menu item from sprite
+ * @deprecated since v3.0 please use new cc.MenuItemSprite(normalSprite, selectedSprite, three, four, five) instead
+ * @param {Image} normalSprite normal state image
+ * @param {Image|Null} selectedSprite selected state image
+ * @param {Image|cc.Node|Null} three disabled state image OR target node
+ * @param {String|function|cc.Node|Null} four callback function name in string or actual function, OR target Node
+ * @param {String|function|Null} five callback function name in string or actual function
+ * @return {cc.MenuItemSprite}
+ */
+cc.MenuItemSprite.create = function (normalSprite, selectedSprite, three, four, five) {
+ return new cc.MenuItemSprite(normalSprite, selectedSprite, three, four, five || undefined);
+};
+
+/**
+ * cc.MenuItemImage accepts images as items.
+ * The images has 3 different states:
+ * - unselected image
+ * - selected image
+ * - disabled image
+ *
+ * For best results try that all images are of the same size
+ * @class
+ * @extends cc.MenuItemSprite
+ * @param {string|null} normalImage
+ * @param {string|null} selectedImage
+ * @param {string|null} disabledImage
+ * @param {function|string|null} callback
+ * @param {cc.Node|null} target
+ * @example
+ * var menuItem = new cc.MenuItemImage(normalImage, selectedImage, three, four, five);
+ */
+cc.MenuItemImage = cc.MenuItemSprite.extend(/** @lends cc.MenuItemImage# */{
+
+ /**
+ * Constructor of cc.MenuItemImage
+ * @param {string|null} normalImage
+ * @param {string|null} selectedImage
+ * @param {string|null} disabledImage
+ * @param {function|string|null} callback
+ * @param {cc.Node|null} target
+ */
+ ctor: function (normalImage, selectedImage, three, four, five) {
+ var normalSprite = null,
+ selectedSprite = null,
+ disabledSprite = null,
+ callback = null,
+ target = null;
+
+ if (normalImage === undefined || normalImage === null) {
+ cc.MenuItemSprite.prototype.ctor.call(this);
+ }
+ else {
+ normalSprite = new cc.Sprite(normalImage);
+ selectedImage &&
+ (selectedSprite = new cc.Sprite(selectedImage));
+
+ if (four === undefined) {
+ callback = three;
+ }
+ else if (five === undefined) {
+ callback = three;
+ target = four;
+ }
+ else if (five) {
+ disabledSprite = new cc.Sprite(three);
+ callback = four;
+ target = five;
+ }
+ cc.MenuItemSprite.prototype.ctor.call(this, normalSprite, selectedSprite, disabledSprite, callback, target);
+ }
+ },
+
+ /**
+ * sets the sprite frame for the normal image
+ * @param {cc.SpriteFrame} frame
+ */
+ setNormalSpriteFrame: function (frame) {
+ this.setNormalImage(new cc.Sprite(frame));
+ },
+
+ /**
+ * sets the sprite frame for the selected image
+ * @param {cc.SpriteFrame} frame
+ */
+ setSelectedSpriteFrame: function (frame) {
+ this.setSelectedImage(new cc.Sprite(frame));
+ },
+
+ /**
+ * sets the sprite frame for the disabled image
+ * @param {cc.SpriteFrame} frame
+ */
+ setDisabledSpriteFrame: function (frame) {
+ this.setDisabledImage(new cc.Sprite(frame));
+ },
+
+ /**
+ * initializes a cc.MenuItemImage
+ * @param {string|null} normalImage
+ * @param {string|null} selectedImage
+ * @param {string|null} disabledImage
+ * @param {function|string|null} callback
+ * @param {cc.Node|null} target
+ * @returns {boolean}
+ */
+ initWithNormalImage: function (normalImage, selectedImage, disabledImage, callback, target) {
+ var normalSprite = null;
+ var selectedSprite = null;
+ var disabledSprite = null;
+
+ if (normalImage) {
+ normalSprite = new cc.Sprite(normalImage);
+ }
+ if (selectedImage) {
+ selectedSprite = new cc.Sprite(selectedImage);
+ }
+ if (disabledImage) {
+ disabledSprite = new cc.Sprite(disabledImage);
+ }
+ return this.initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, callback, target);
+ }
+});
+
+/**
+ * creates a new menu item image
+ * @deprecated since v3.0, please use new cc.MenuItemImage(normalImage, selectedImage, three, four, five) instead.
+ * @param {String} normalImage file name for normal state
+ * @param {String} selectedImage image for selected state
+ * @param {String|cc.Node} three Disabled image OR callback function
+ * @param {String|function|Null} [four] callback function, either name in string or pass the whole function OR the target
+ * @param {cc.Node|String|function|Null} [five] cc.Node target to run callback when clicked
+ * @return {cc.MenuItemImage}
+ */
+cc.MenuItemImage.create = function (normalImage, selectedImage, three, four, five) {
+ return new cc.MenuItemImage(normalImage, selectedImage, three, four, five);
+};
+
+
+/**
+ * A simple container class that "toggles" it's inner items
+ * The inner items can be any MenuItem
+ * @class
+ * @extends cc.MenuItem
+ *
+ * @property {Array} subItems - Sub items
+ * @property {Number} selectedIndex - Index of selected sub item
+ *
+ *@example
+ * // Example
+ * //create a toggle item with 2 menu items (which you can then toggle between them later)
+ * var toggler = new cc.MenuItemToggle( new cc.MenuItemFont("On"), new cc.MenuItemFont("Off"), this.callback, this)
+ * //Note: the first param is the target, the second is the callback function, afterwards, you can pass in any number of menuitems
+ *
+ * //if you pass only 1 variable, then it must be a cc.MenuItem
+ * var notYetToggler = new cc.MenuItemToggle(cc.MenuItemFont("On"));//it is useless right now, until you add more stuff to it
+ * notYetToggler.addSubItem(new cc.MenuItemFont("Off"));
+ * //this is useful for constructing a toggler without a callback function (you wish to control the behavior from somewhere else)
+ */
+cc.MenuItemToggle = cc.MenuItem.extend(/** @lends cc.MenuItemToggle# */{
+ subItems: null,
+
+ _selectedIndex: 0,
+ _opacity: null,
+ _color: null,
+
+ /**
+ * Constructor of cc.MenuItemToggle
+ */
+ ctor: function (/*Multiple arguments follow*/) {
+
+ cc.MenuItem.prototype.ctor.call(this);
+ this._selectedIndex = 0;
+ this.subItems = [];
+ this._opacity = 0;
+ this._color = cc.color.WHITE;
+
+ if(arguments.length > 0)
+ this.initWithItems(Array.prototype.slice.apply(arguments));
+
+ },
+
+ /**
+ * return the opacity of cc.MenuItemToggle
+ * @return {Number}
+ */
+ getOpacity: function () {
+ return this._opacity;
+ },
+
+ /**
+ * set the opacity for cc.MenuItemToggle
+ * @param {Number} opacity
+ */
+ setOpacity: function (opacity) {
+ this._opacity = opacity;
+ if (this.subItems && this.subItems.length > 0) {
+ for (var it = 0; it < this.subItems.length; it++) {
+ this.subItems[it].opacity = opacity;
+ }
+ }
+ this._color.a = opacity;
+ },
+
+ /**
+ * return the color of cc.MenuItemToggle
+ * @return {cc.Color}
+ */
+ getColor: function () {
+ var locColor = this._color;
+ return cc.color(locColor.r, locColor.g, locColor.b, locColor.a);
+ },
+
+ /**
+ * set the color for cc.MenuItemToggle
+ * @param {cc.Color} Color
+ */
+ setColor: function (color) {
+ var locColor = this._color;
+ locColor.r = color.r;
+ locColor.g = color.g;
+ locColor.b = color.b;
+
+ if (this.subItems && this.subItems.length > 0) {
+ for (var it = 0; it < this.subItems.length; it++) {
+ this.subItems[it].setColor(color);
+ }
+ }
+
+ if (color.a !== undefined && !color.a_undefined) {
+ this.setOpacity(color.a);
+ }
+ },
+
+ /**
+ * return the index of selected
+ * @return {Number}
+ */
+ getSelectedIndex: function () {
+ return this._selectedIndex;
+ },
+
+ /**
+ * set the seleceted index for cc.MenuItemToggle
+ * @param {Number} SelectedIndex
+ */
+ setSelectedIndex: function (SelectedIndex) {
+ if (SelectedIndex !== this._selectedIndex) {
+ this._selectedIndex = SelectedIndex;
+ var currItem = this.getChildByTag(cc.CURRENT_ITEM);
+ if (currItem)
+ currItem.removeFromParent(false);
+
+ var item = this.subItems[this._selectedIndex];
+ this.addChild(item, 0, cc.CURRENT_ITEM);
+ var w = item.width, h = item.height;
+ this.width = w;
+ this.height = h;
+ item.setPosition(w / 2, h / 2);
+ }
+ },
+
+ /**
+ * similar to get children,return the sumItem array.
+ * @return {Array}
+ */
+ getSubItems: function () {
+ return this.subItems;
+ },
+
+ /**
+ * set the subitem for cc.MenuItemToggle
+ * @param {cc.MenuItem} subItems
+ */
+ setSubItems: function (subItems) {
+ this.subItems = subItems;
+ },
+
+ /**
+ * initializes a cc.MenuItemToggle with items
+ * @param {...cc.MenuItem} array the rest in the array are cc.MenuItems
+ * @param {function|String} secondTolast the second item in the args array is the callback
+ * @param {cc.Node} last the first item in the args array is a target
+ * @return {Boolean}
+ */
+ initWithItems: function (args) {
+ var l = args.length;
+ // passing callback.
+ if (cc.isFunction(args[args.length - 2])) {
+ this.initWithCallback(args[args.length - 2], args[args.length - 1]);
+ l = l - 2;
+ } else if (cc.isFunction(args[args.length - 1])) {
+ this.initWithCallback(args[args.length - 1], null);
+ l = l - 1;
+ } else {
+ this.initWithCallback(null, null);
+ }
+
+ var locSubItems = this.subItems;
+ locSubItems.length = 0;
+ for (var i = 0; i < l; i++) {
+ if (args[i])
+ locSubItems.push(args[i]);
+ }
+ this._selectedIndex = cc.UINT_MAX;
+ this.setSelectedIndex(0);
+
+ this.setCascadeColorEnabled(true);
+ this.setCascadeOpacityEnabled(true);
+
+ return true;
+ },
+
+ /**
+ * add the subitem for cc.MenuItemToggle
+ * @param {cc.MenuItem} item
+ */
+ addSubItem: function (item) {
+ this.subItems.push(item);
+ },
+
+ /**
+ * activate the menu item
+ */
+ activate: function () {
+ // update index
+ if (this._enabled) {
+ var newIndex = (this._selectedIndex + 1) % this.subItems.length;
+ this.setSelectedIndex(newIndex);
+ }
+ cc.MenuItem.prototype.activate.call(this);
+ },
+
+ /**
+ * menu item is selected (runs callback)
+ */
+ selected: function () {
+ cc.MenuItem.prototype.selected.call(this);
+ this.subItems[this._selectedIndex].selected();
+ },
+
+ /**
+ * menu item goes back to unselected state
+ */
+ unselected: function () {
+ cc.MenuItem.prototype.unselected.call(this);
+ this.subItems[this._selectedIndex].unselected();
+ },
+
+ /**
+ * set the enable status for cc.MenuItemToggle
+ * @param {Boolean} enabled
+ */
+ setEnabled: function (enabled) {
+ if (this._enabled !== enabled) {
+ cc.MenuItem.prototype.setEnabled.call(this, enabled);
+ var locItems = this.subItems;
+ if (locItems && locItems.length > 0) {
+ for (var it = 0; it < locItems.length; it++)
+ locItems[it].enabled = enabled;
+ }
+ }
+ },
+
+ /**
+ * returns the selected item (deprecated in -x, please use getSelectedItem instead.)
+ * @return {cc.MenuItem}
+ */
+ selectedItem: function () {
+ return this.subItems[this._selectedIndex];
+ },
+
+ /**
+ * returns the selected item.
+ * @return {cc.MenuItem}
+ */
+ getSelectedItem: function() {
+ return this.subItems[this._selectedIndex];
+ },
+
+ /**
+ * *
+ * Event callback that is invoked every time when cc.MenuItemToggle enters the 'stage'.
+ * If the cc.MenuItemToggle enters the 'stage' with a transition, this event is called when the transition starts.
+ * During onEnter you can't access a "sister/brother" node.
+ * If you override onEnter, you must call its parent's onEnter function with this._super().
+ *
+ */
+ onEnter: function () {
+ cc.Node.prototype.onEnter.call(this);
+ this.setSelectedIndex(this._selectedIndex);
+ }
+});
+
+var _p = cc.MenuItemToggle.prototype;
+
+// Extended properties
+/** @expose */
+_p.selectedIndex;
+cc.defineGetterSetter(_p, "selectedIndex", _p.getSelectedIndex, _p.setSelectedIndex);
+
+
+/**
+ * create a simple container class that "toggles" it's inner items
+ * The inner items can be any MenuItem
+ * @deprecated since v3.0 please use new cc.MenuItemToggle(params) instead
+ * @return {cc.MenuItemToggle}
+ */
+cc.MenuItemToggle.create = function (/*Multiple arguments follow*/) {
+ if ((arguments.length > 0) && (arguments[arguments.length - 1] == null))
+ cc.log("parameters should not be ending with null in Javascript");
+ var ret = new cc.MenuItemToggle();
+ ret.initWithItems(Array.prototype.slice.apply(arguments));
+ return ret;
+};
diff --git a/cocos2d/misc_nodes/CCClippingNode.js b/cocos2d/misc_nodes/CCClippingNode.js
deleted file mode 100644
index c9d3f08985..0000000000
--- a/cocos2d/misc_nodes/CCClippingNode.js
+++ /dev/null
@@ -1,346 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2013 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
- Copyright (c) 2012 Pierre-David Bélanger
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.stencilBits = -1;
-
-cc.setProgram = function(node, program){
- node.setShaderProgram(program);
-
- var children = node.getChildren();
- if(!children)
- return;
-
- for(var i = 0; i < children.length;i++)
- cc.setProgram(children[i],program);
-};
-
-/**
- *
- * cc.ClippingNode is a subclass of cc.Node.
- * It draws its content (childs) clipped using a stencil.
- * The stencil is an other cc.Node that will not be drawn.
- * The clipping is done using the alpha part of the stencil (adjusted with an alphaThreshold).
- *
- * @class
- * @extends cc.Node
- */
-cc.ClippingNode = cc.Node.extend(/** @lends cc.ClippingNode# */{
- _stencil:null,
- _alphaThreshold:0,
- _inverted:false,
-
- ctor:function(){
- cc.Node.prototype.ctor.call(this);
- this._stencil = null;
- this._alphaThreshold = 0;
- this._inverted = false;
- },
-
- /**
- * Initializes a clipping node with an other node as its stencil.
- * The stencil node will be retained, and its parent will be set to this clipping node.
- * @param {cc.Node} [stencil=null]
- */
- init:function(stencil){
- this._stencil = stencil;
-
- this._alphaThreshold = 1;
- this._inverted = false;
- // get (only once) the number of bits of the stencil buffer
- cc.ClippingNode._init_once = true;
- if(cc.ClippingNode._init_once){
- cc.stencilBits = cc.renderContext.getParameter(cc.renderContext.STENCIL_BITS);
- if(cc.stencilBits <= 0)
- cc.log("Stencil buffer is not enabled.");
- cc.ClippingNode._init_once = false;
- }
- return true;
- },
-
- onEnter:function(){
- cc.Node.prototype.onEnter.call(this);
- this._stencil.onEnter();
- },
-
- onEnterTransitionDidFinish:function(){
- cc.Node.prototype.onEnterTransitionDidFinish.call(this);
- this._stencil.onEnterTransitionDidFinish();
- },
-
- onExitTransitionDidStart:function(){
- this._stencil.onExitTransitionDidStart();
- cc.Node.prototype.onExitTransitionDidStart.call(this);
- },
-
- onExit:function(){
- this._stencil.onExit();
- cc.Node.prototype.onExit.call(this);
- },
-
- visit:function(ctx){
- var gl = ctx || cc.renderContext;
-
- // if stencil buffer disabled
- if (cc.stencilBits < 1) {
- // draw everything, as if there where no stencil
- cc.Node.prototype.visit.call(this, ctx);
- return;
- }
-
- // return fast (draw nothing, or draw everything if in inverted mode) if:
- // - nil stencil node
- // - or stencil node invisible:
- if (!this._stencil || !this._stencil.isVisible()) {
- if (this._inverted)
- cc.Node.prototype.visit.call(this, ctx); // draw everything
- return;
- }
-
- // store the current stencil layer (position in the stencil buffer),
- // this will allow nesting up to n CCClippingNode,
- // where n is the number of bits of the stencil buffer.
- cc.ClippingNode._layer = -1;
-
- // all the _stencilBits are in use?
- if (cc.ClippingNode._layer + 1 == cc.stencilBits) {
- // warn once
- cc.ClippingNode._visit_once = true;
- if (cc.ClippingNode._visit_once) {
- cc.log("Nesting more than " + cc.stencilBits + "stencils is not supported. Everything will be drawn without stencil for this node and its childs.");
- cc.ClippingNode._visit_once = false;
- }
- // draw everything, as if there where no stencil
- cc.Node.prototype.visit.call(this, ctx);
- return;
- }
-
- ///////////////////////////////////
- // INIT
-
- // increment the current layer
- cc.ClippingNode._layer++;
-
- // mask of the current layer (ie: for layer 3: 00000100)
- var mask_layer = 0x1 << cc.ClippingNode._layer;
- // mask of all layers less than the current (ie: for layer 3: 00000011)
- var mask_layer_l = mask_layer - 1;
- // mask of all layers less than or equal to the current (ie: for layer 3: 00000111)
- var mask_layer_le = mask_layer | mask_layer_l;
-
- // manually save the stencil state
- var currentStencilEnabled = gl.isEnabled(gl.STENCIL_TEST);
- var currentStencilWriteMask = gl.getParameter(gl.STENCIL_WRITEMASK);
- var currentStencilFunc = gl.getParameter(gl.STENCIL_FUNC);
- var currentStencilRef = gl.getParameter(gl.STENCIL_REF);
- var currentStencilValueMask = gl.getParameter(gl.STENCIL_VALUE_MASK);
- var currentStencilFail = gl.getParameter(gl.STENCIL_FAIL);
- var currentStencilPassDepthFail = gl.getParameter(gl.STENCIL_PASS_DEPTH_FAIL);
- var currentStencilPassDepthPass = gl.getParameter(gl.STENCIL_PASS_DEPTH_PASS);
-
- // enable stencil use
- gl.enable(gl.STENCIL_TEST);
- // check for OpenGL error while enabling stencil test
- //cc.CHECK_GL_ERROR_DEBUG();
-
- // all bits on the stencil buffer are readonly, except the current layer bit,
- // this means that operation like glClear or glStencilOp will be masked with this value
- gl.stencilMask(mask_layer);
-
- // manually save the depth test state
- //GLboolean currentDepthTestEnabled = GL_TRUE;
- //currentDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
- var currentDepthWriteMask = gl.getParameter(gl.DEPTH_WRITEMASK);
-
- // disable depth test while drawing the stencil
- //glDisable(GL_DEPTH_TEST);
- // disable update to the depth buffer while drawing the stencil,
- // as the stencil is not meant to be rendered in the real scene,
- // it should never prevent something else to be drawn,
- // only disabling depth buffer update should do
- gl.depthMask(false);
-
- ///////////////////////////////////
- // CLEAR STENCIL BUFFER
-
- // manually clear the stencil buffer by drawing a fullscreen rectangle on it
- // setup the stencil test func like this:
- // for each pixel in the fullscreen rectangle
- // never draw it into the frame buffer
- // if not in inverted mode: set the current layer value to 0 in the stencil buffer
- // if in inverted mode: set the current layer value to 1 in the stencil buffer
- gl.stencilFunc(gl.NEVER, mask_layer, mask_layer);
- gl.stencilOp(!this._inverted ? gl.ZERO : gl.REPLACE, gl.KEEP, gl.KEEP);
-
- // draw a fullscreen solid rectangle to clear the stencil buffer
- //ccDrawSolidRect(CCPointZero, ccpFromSize([[CCDirector sharedDirector] winSize]), ccc4f(1, 1, 1, 1));
- cc.drawingUtil.drawSolidRect(cc.PointZero(), cc.pFromSize(cc.Director.getInstance().getWinSize()), cc.c4f(1, 1, 1, 1));
-
- ///////////////////////////////////
- // DRAW CLIPPING STENCIL
-
- // setup the stencil test func like this:
- // for each pixel in the stencil node
- // never draw it into the frame buffer
- // if not in inverted mode: set the current layer value to 1 in the stencil buffer
- // if in inverted mode: set the current layer value to 0 in the stencil buffer
- gl.stencilFunc(gl.NEVER, mask_layer, mask_layer);
- gl.stencilOp(!this._inverted ? gl.REPLACE : gl.ZERO, gl.KEEP, gl.KEEP);
-
- if (this._alphaThreshold < 1) {
- // since glAlphaTest do not exists in OES, use a shader that writes
- // pixel only if greater than an alpha threshold
- var program = cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLORALPHATEST);
- var alphaValueLocation = gl.getUniformLocation(program.getProgram(), cc.UNIFORM_ALPHA_TEST_VALUE_S);
- // set our alphaThreshold
- cc.glUseProgram(program.getProgram());
- program.setUniformLocationWith1f(alphaValueLocation, this._alphaThreshold);
- // we need to recursively apply this shader to all the nodes in the stencil node
- // XXX: we should have a way to apply shader to all nodes without having to do this
- cc.setProgram(this._stencil, program);
- }
-
- // draw the stencil node as if it was one of our child
- // (according to the stencil test func/op and alpha (or alpha shader) test)
- cc.kmGLPushMatrix();
- this.transform();
- this._stencil.visit();
- cc.kmGLPopMatrix();
-
- // restore alpha test state
- //if (this._alphaThreshold < 1) {
- // XXX: we need to find a way to restore the shaders of the stencil node and its childs
- //}
-
- // restore the depth test state
- gl.depthMask(currentDepthWriteMask);
- //if (currentDepthTestEnabled) {
- // glEnable(GL_DEPTH_TEST);
- //}
-
- ///////////////////////////////////
- // DRAW CONTENT
-
- // setup the stencil test func like this:
- // for each pixel of this node and its childs
- // if all layers less than or equals to the current are set to 1 in the stencil buffer
- // draw the pixel and keep the current layer in the stencil buffer
- // else
- // do not draw the pixel but keep the current layer in the stencil buffer
- gl.stencilFunc(gl.EQUAL, mask_layer_le, mask_layer_le);
- gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
-
- // draw (according to the stencil test func) this node and its childs
- cc.Node.prototype.visit.call(this, ctx);
-
- ///////////////////////////////////
- // CLEANUP
-
- // manually restore the stencil state
- gl.stencilFunc(currentStencilFunc, currentStencilRef, currentStencilValueMask);
- gl.stencilOp(currentStencilFail, currentStencilPassDepthFail, currentStencilPassDepthPass);
- gl.stencilMask(currentStencilWriteMask);
- if (!currentStencilEnabled)
- gl.disable(gl.STENCIL_TEST);
-
- // we are done using this layer, decrement
- cc.ClippingNode._layer--;
- },
-
- /**
- * The cc.Node to use as a stencil to do the clipping.
- * The stencil node will be retained. This default to nil.
- * @return {cc.Node}
- */
- getStencil:function(){
- return this._stencil;
- },
-
- /**
- * @param {cc.Node} stencil
- */
- setStencil:function(stencil){
- this._stencil = stencil;
- },
-
- /**
- *
- * The alpha threshold.
- * The content is drawn only where the stencil have pixel with alpha greater than the alphaThreshold.
- * Should be a float between 0 and 1.
- * This default to 1 (so alpha test is disabled).
- *
- * @return {Number}
- */
- getAlphaThreshold:function(){
- return this._alphaThreshold;
- },
-
- /**
- * set alpha threshold.
- * @param {Number} alphaThreshold
- */
- setAlphaThreshold:function(alphaThreshold){
- this._alphaThreshold = alphaThreshold;
- },
-
- /**
- *
- * Inverted. If this is set to YES,
- * the stencil is inverted, so the content is drawn where the stencil is NOT drawn.
- * This default to NO.
- *
- * @return {Boolean}
- */
- isInverted:function(){
- return this._inverted;
- },
-
-
- /**
- * set whether or not invert of stencil
- * @param {Boolean} inverted
- */
- setInverted:function(inverted){
- this._inverted = inverted;
- }
-});
-
-cc.ClippingNode._init_once = null;
-cc.ClippingNode._visit_once = null;
-cc.ClippingNode._layer = null;
-
-/**
- * Creates and initializes a clipping node with an other node as its stencil.
- * The stencil node will be retained.
- * @param {cc.Node} [stencil=null]
- * @return {cc.ClippingNode}
- */
-cc.ClippingNode.create = function(stencil){
- var node = new cc.ClippingNode();
- node.init(stencil);
- return node;
-};
\ No newline at end of file
diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js
deleted file mode 100644
index a122d75bb4..0000000000
--- a/cocos2d/misc_nodes/CCProgressTimer.js
+++ /dev/null
@@ -1,925 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2011 cocos2d-x.org
- Copyright (c) 2010 Lam Pham
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-/**
- * Radial Counter-Clockwise
- * @type Number
- * @constant
- */
-cc.PROGRESS_TIMER_TYPE_RADIAL = 0;
-/**
- * Bar
- * @type Number
- * @constant
- */
-cc.PROGRESS_TIMER_TYPE_BAR = 1;
-
-/**
- * @constant
- * @type Number
- */
-cc.PROGRESS_TEXTURE_COORDS_COUNT = 4;
-
-/**
- * @constant
- * @type Number
- */
-cc.PROGRESS_TEXTURE_COORDS = 0x4b;
-
-/**
- * cc.Progresstimer is a subclass of cc.Node.
- * It renders the inner sprite according to the percentage.
- * The progress can be Radial, Horizontal or vertical.
- * @class
- * @extends cc.NodeRGBA
- */
-cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{
- _type:null,
- _percentage:0.0,
- _sprite:null,
-
- _midPoint:null,
- _barChangeRate:null,
- _reverseDirection:false,
-
- /**
- * Midpoint is used to modify the progress start position.
- * If you're using radials type then the midpoint changes the center point
- * If you're using bar type the the midpoint changes the bar growth
- * it expands from the center but clamps to the sprites edge so:
- * you want a left to right then set the midpoint all the way to cc.p(0,y)
- * you want a right to left then set the midpoint all the way to cc.p(1,y)
- * you want a bottom to top then set the midpoint all the way to cc.p(x,0)
- * you want a top to bottom then set the midpoint all the way to cc.p(x,1)
- * @return {cc.Point}
- */
- getMidpoint:function () {
- return cc.p(this._midPoint.x, this._midPoint);
- },
-
- /**
- * Midpoint setter
- * @param {cc.Point} mpoint
- */
- setMidpoint:function (mpoint) {
- this._midPoint = cc.pClamp(mpoint, cc.p(0, 0), cc.p(1, 1));
- },
-
- /**
- * This allows the bar type to move the component at a specific rate
- * Set the component to 0 to make sure it stays at 100%.
- * For example you want a left to right bar but not have the height stay 100%
- * Set the rate to be cc.p(0,1); and set the midpoint to = cc.p(0,.5f);
- * @return {cc.Point}
- */
- getBarChangeRate:function () {
- return cc.p(this._barChangeRate.x, this._barChangeRate.y);
- },
-
- /**
- * @param {cc.Point} barChangeRate
- */
- setBarChangeRate:function (barChangeRate) {
- this._barChangeRate = cc.pClamp(barChangeRate, cc.p(0, 0), cc.p(1, 1));
- },
-
- /**
- * Change the percentage to change progress
- * @return {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR}
- */
- getType:function () {
- return this._type;
- },
-
- /**
- * Percentages are from 0 to 100
- * @return {Number}
- */
- getPercentage:function () {
- return this._percentage;
- },
-
- /**
- * The image to show the progress percentage, retain
- * @return {cc.Sprite}
- */
- getSprite:function () {
- return this._sprite;
- },
-
- /**
- * from 0-100
- * @param {Number} percentage
- */
- setPercentage:function (percentage) {
- if (this._percentage != percentage) {
- this._percentage = cc.clampf(percentage, 0, 100);
- this._updateProgress();
- }
- },
-
- setOpacityModifyRGB:function (bValue) {
- },
-
- isOpacityModifyRGB:function () {
- return false;
- },
-
- isReverseDirection:function () {
- return this._reverseDirection;
- },
-
- _boundaryTexCoord:function (index) {
- if (index < cc.PROGRESS_TEXTURE_COORDS_COUNT) {
- var locProTextCoords = cc.PROGRESS_TEXTURE_COORDS;
- if (this._reverseDirection)
- return cc.p((locProTextCoords >> (7 - (index << 1))) & 1, (locProTextCoords >> (7 - ((index << 1) + 1))) & 1);
- else
- return cc.p((locProTextCoords >> ((index << 1) + 1)) & 1, (locProTextCoords >> (index << 1)) & 1);
- }
- return cc.PointZero();
- },
-
- _origin:null,
- _startAngle:270,
- _endAngle:270,
- _radius:0,
- _counterClockWise:false,
- _barRect:null,
-
- _vertexDataCount:0,
- _vertexData:null,
- _vertexArrayBuffer:null,
- _vertexWebGLBuffer:null,
- _vertexDataDirty:false,
-
- ctor: null,
-
- _ctorForCanvas: function () {
- cc.NodeRGBA.prototype.ctor.call(this);
-
- this._type = cc.PROGRESS_TIMER_TYPE_RADIAL;
- this._percentage = 0.0;
- this._midPoint = cc.p(0, 0);
- this._barChangeRate = cc.p(0, 0);
- this._reverseDirection = false;
-
- this._sprite = null;
-
- this._origin = cc.PointZero();
- this._startAngle = 270;
- this._endAngle = 270;
- this._radius = 0;
- this._counterClockWise = false;
- this._barRect = cc.RectZero();
- },
-
- _ctorForWebGL: function () {
- cc.NodeRGBA.prototype.ctor.call(this);
- this._type = cc.PROGRESS_TIMER_TYPE_RADIAL;
- this._percentage = 0.0;
- this._midPoint = cc.p(0, 0);
- this._barChangeRate = cc.p(0, 0);
- this._reverseDirection = false;
-
- this._sprite = null;
-
- this._vertexWebGLBuffer = cc.renderContext.createBuffer();
- this._vertexDataCount = 0;
- this._vertexData = null;
- this._vertexArrayBuffer = null;
- this._vertexDataDirty = false;
- },
-
- /**
- * set color of sprite
- * @param {cc.Color3B} color
- */
- setColor:function (color) {
- this._sprite.setColor(color);
- },
-
- /**
- * Opacity
- * @param {Number} opacity
- */
- setOpacity:function (opacity) {
- this._sprite.setOpacity(opacity);
- },
-
- /**
- * return color of sprite
- * @return {cc.Color3B}
- */
- getColor:function () {
- return this._sprite.getColor();
- },
-
- /**
- * return Opacity of sprite
- * @return {Number}
- */
- getOpacity:function () {
- return this._sprite.getOpacity();
- },
-
- /**
- * @param {Boolean} reverse
- */
- setReverseProgress:null,
-
- _setReverseProgressForCanvas:function (reverse) {
- if (this._reverseDirection !== reverse)
- this._reverseDirection = reverse;
- },
-
- _setReverseProgressForWebGL:function (reverse) {
- if (this._reverseDirection !== reverse) {
- this._reverseDirection = reverse;
-
- // release all previous information
- this._vertexData = null;
- this._vertexArrayBuffer = null;
- this._vertexDataCount = 0;
- }
- },
-
- /**
- * @param {cc.Sprite} sprite
- */
- setSprite:null,
-
- _setSpriteForCanvas:function (sprite) {
- if (this._sprite != sprite) {
- this._sprite = sprite;
- this.setContentSize(this._sprite.getContentSize());
- }
- },
-
- _setSpriteForWebGL:function (sprite) {
- if (sprite && this._sprite != sprite) {
- this._sprite = sprite;
- this.setContentSize(sprite.getContentSize());
-
- // Everytime we set a new sprite, we free the current vertex data
- if (this._vertexData) {
- this._vertexData = null;
- this._vertexArrayBuffer = null;
- this._vertexDataCount = 0;
- }
- }
- },
-
- /**
- * set Progress type of cc.ProgressTimer
- * @param {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} type
- */
- setType:null,
-
- _setTypeForCanvas:function (type) {
- if (type !== this._type)
- this._type = type;
- },
-
- _setTypeForWebGL:function (type) {
- if (type !== this._type) {
- // release all previous information
- if (this._vertexData) {
- this._vertexData = null;
- this._vertexArrayBuffer = null;
- this._vertexDataCount = 0;
- }
- this._type = type;
- }
- },
-
- /**
- * Reverse Progress setter
- * @param {Boolean} reverse
- */
- setReverseDirection: null,
-
- _setReverseDirectionForCanvas: function (reverse) {
- if (this._reverseDirection !== reverse)
- this._reverseDirection = reverse;
- },
-
- _setReverseDirectionForWebGL: function (reverse) {
- if (this._reverseDirection !== reverse) {
- this._reverseDirection = reverse;
- //release all previous information
- this._vertexData = null;
- this._vertexArrayBuffer = null;
- this._vertexDataCount = 0;
- }
- },
-
- /**
- * @param {cc.Point} alpha
- * @return {cc.Vertex2F | Object} the vertex position from the texture coordinate
- * @private
- */
- _textureCoordFromAlphaPoint:function (alpha) {
- var locSprite = this._sprite;
- if (!locSprite) {
- return {u:0, v:0}; //new cc.Tex2F(0, 0);
- }
- var quad = locSprite.getQuad();
- var min = cc.p(quad.bl.texCoords.u, quad.bl.texCoords.v);
- var max = cc.p(quad.tr.texCoords.u, quad.tr.texCoords.v);
-
- // Fix bug #1303 so that progress timer handles sprite frame texture rotation
- if (locSprite.isTextureRectRotated()) {
- var temp = alpha.x;
- alpha.x = alpha.y;
- alpha.y = temp;
- }
- return {u: min.x * (1 - alpha.x) + max.x * alpha.x, v: min.y * (1 - alpha.y) + max.y * alpha.y};
- },
-
- _vertexFromAlphaPoint:function (alpha) {
- if (!this._sprite) {
- return {x: 0, y: 0};
- }
- var quad = this._sprite.getQuad();
- var min = cc.p(quad.bl.vertices.x, quad.bl.vertices.y);
- var max = cc.p(quad.tr.vertices.x, quad.tr.vertices.y);
- return {x: min.x * (1 - alpha.x) + max.x * alpha.x, y: min.y * (1 - alpha.y) + max.y * alpha.y};
- },
-
- /**
- * Initializes a progress timer with the sprite as the shape the timer goes through
- * @param {cc.Sprite} sprite
- * @return {Boolean}
- */
- initWithSprite:null,
-
- _initWithSpriteForCanvas:function (sprite) {
- this.setPercentage(0);
- this.setAnchorPoint(cc.p(0.5, 0.5));
-
- this._type = cc.PROGRESS_TIMER_TYPE_RADIAL;
- this._reverseDirection = false;
- this.setMidpoint(cc.p(0.5, 0.5));
- this.setBarChangeRate(cc.p(1, 1));
- this.setSprite(sprite);
-
- return true;
- },
-
- _initWithSpriteForWebGL:function (sprite) {
- this.setPercentage(0);
- this._vertexData = null;
- this._vertexArrayBuffer = null;
- this._vertexDataCount = 0;
- this.setAnchorPoint(cc.p(0.5, 0.5));
-
- this._type = cc.PROGRESS_TIMER_TYPE_RADIAL;
- this._reverseDirection = false;
- this.setMidpoint(cc.p(0.5, 0.5));
- this.setBarChangeRate(cc.p(1, 1));
- this.setSprite(sprite);
-
- //shader program
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
- return true;
- },
-
- /**
- * stuff gets drawn here
- * @param {CanvasRenderingContext2D} ctx
- */
- draw:null,
-
- _drawForCanvas:function (ctx) {
- var context = ctx || cc.renderContext;
-
- var locSprite = this._sprite;
- if (locSprite._isLighterMode)
- context.globalCompositeOperation = 'lighter';
-
- var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY();
-
- context.globalAlpha = locSprite._displayedOpacity / 255;
- var locRect = locSprite._rect, locContentSize = locSprite._contentSize, locOffsetPosition = locSprite._offsetPosition, locDrawSizeCanvas = locSprite._drawSize_Canvas;
- var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height, locTextureCoord = locSprite._textureRect_Canvas;
- locDrawSizeCanvas.width = locRect.width * locEGL_ScaleX;
- locDrawSizeCanvas.height = locRect.height * locEGL_ScaleY;
-
- context.save();
- if (locSprite._flippedX) {
- flipXOffset = -locOffsetPosition.x - locRect.width;
- context.scale(-1, 1);
- }
- if (locSprite._flippedY) {
- flipYOffset = locOffsetPosition.y;
- context.scale(1, -1);
- }
-
- flipXOffset *= locEGL_ScaleX;
- flipYOffset *= locEGL_ScaleY;
-
- //clip
- if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) {
- var locBarRect = this._barRect;
- context.beginPath();
- context.rect(locBarRect.x * locEGL_ScaleX, locBarRect.y * locEGL_ScaleY, locBarRect.width * locEGL_ScaleX, locBarRect.height * locEGL_ScaleY);
- context.clip();
- context.closePath();
- } else if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) {
- var locOriginX = this._origin.x * locEGL_ScaleX;
- var locOriginY = this._origin.y * locEGL_ScaleY;
- context.beginPath();
- context.arc(locOriginX, locOriginY, this._radius * locEGL_ScaleY, (Math.PI / 180) * this._startAngle, (Math.PI / 180) * this._endAngle, this._counterClockWise);
- context.lineTo(locOriginX, locOriginY);
- context.clip();
- context.closePath();
- }
-
- //draw sprite
- if (locSprite._texture && locRect.width > 0) {
- var image = locSprite._texture.getHtmlElementObj();
- if (this._colorized) {
- context.drawImage(image,
- 0, 0, locTextureCoord.width, locTextureCoord.height,
- flipXOffset, flipYOffset, locDrawSizeCanvas.width, locDrawSizeCanvas.height);
- } else {
- context.drawImage(image,
- locTextureCoord.x, locTextureCoord.y, locTextureCoord.width, locTextureCoord.height,
- flipXOffset, flipYOffset, locDrawSizeCanvas.width , locDrawSizeCanvas.height);
- }
- } else if (locContentSize.width !== 0) {
- var curColor = this.getColor();
- context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)";
- context.fillRect(flipXOffset, flipYOffset, locContentSize.width * locEGL_ScaleX, locContentSize.height * locEGL_ScaleY);
- }
-
- context.restore();
- cc.INCREMENT_GL_DRAWS(1);
- },
-
- _drawForWebGL:function (ctx) {
- var context = ctx || cc.renderContext;
- if (!this._vertexData || !this._sprite)
- return;
-
- cc.NODE_DRAW_SETUP(this);
-
- var blendFunc = this._sprite.getBlendFunc();
- cc.glBlendFunc(blendFunc.src, blendFunc.dst);
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX);
-
- if (this._sprite.getTexture())
- cc.glBindTexture2D(this._sprite.getTexture());
- else
- cc.glBindTexture2D(null);
-
- context.bindBuffer(context.ARRAY_BUFFER, this._vertexWebGLBuffer);
- if(this._vertexDataDirty){
- context.bufferData(context.ARRAY_BUFFER, this._vertexArrayBuffer, context.DYNAMIC_DRAW);
- this._vertexDataDirty = false;
- }
- var locVertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
- context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, context.FLOAT, false, locVertexDataLen, 0);
- context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.UNSIGNED_BYTE, true, locVertexDataLen, 8);
- context.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, context.FLOAT, false, locVertexDataLen, 12);
-
- if (this._type === cc.PROGRESS_TIMER_TYPE_RADIAL)
- context.drawArrays(context.TRIANGLE_FAN, 0, this._vertexDataCount);
- else if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) {
- if (!this._reverseDirection)
- context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount);
- else {
- context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount / 2);
- context.drawArrays(context.TRIANGLE_STRIP, 4, this._vertexDataCount / 2);
- // 2 draw calls
- cc.g_NumberOfDraws++;
- }
- }
- cc.g_NumberOfDraws++;
- },
-
- /**
- *
- * Update does the work of mapping the texture onto the triangles
- * It now doesn't occur the cost of free/alloc data every update cycle.
- * It also only changes the percentage point but no other points if they have not been modified.
- *
- * It now deals with flipped texture. If you run into this problem, just use the
- * sprite property and enable the methods flipX, flipY.
- *
- * @private
- */
- _updateRadial:function () {
- if (!this._sprite)
- return;
-
- var i, locMidPoint = this._midPoint;
- var alpha = this._percentage / 100;
- var angle = 2 * (cc.PI) * ( this._reverseDirection ? alpha : 1.0 - alpha);
-
- // We find the vector to do a hit detection based on the percentage
- // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate
- // from that by the progress angle around the m_tMidpoint pivot
- var topMid = cc.p(locMidPoint.x, 1);
- var percentagePt = cc.pRotateByAngle(topMid, locMidPoint, angle);
-
- var index = 0;
- var hit;
-
- if (alpha == 0) {
- // More efficient since we don't always need to check intersection
- // If the alpha is zero then the hit point is top mid and the index is 0.
- hit = topMid;
- index = 0;
- } else if (alpha == 1) {
- // More efficient since we don't always need to check intersection
- // If the alpha is one then the hit point is top mid and the index is 4.
- hit = topMid;
- index = 4;
- } else {
- // We run a for loop checking the edges of the texture to find the
- // intersection point
- // We loop through five points since the top is split in half
-
- var min_t = cc.FLT_MAX;
- var locProTextCoordsCount = cc.PROGRESS_TEXTURE_COORDS_COUNT;
- for (i = 0; i <= locProTextCoordsCount; ++i) {
- var pIndex = (i + (locProTextCoordsCount - 1)) % locProTextCoordsCount;
-
- var edgePtA = this._boundaryTexCoord(i % locProTextCoordsCount);
- var edgePtB = this._boundaryTexCoord(pIndex);
-
- // Remember that the top edge is split in half for the 12 o'clock position
- // Let's deal with that here by finding the correct endpoints
- if (i == 0)
- edgePtB = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x);
- else if (i == 4)
- edgePtA = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x);
-
- // retPoint are returned by ccpLineIntersect
- var retPoint = cc.p(0, 0);
- if (cc.pLineIntersect(edgePtA, edgePtB, locMidPoint, percentagePt, retPoint)) {
- // Since our hit test is on rays we have to deal with the top edge
- // being in split in half so we have to test as a segment
- if ((i == 0 || i == 4)) {
- // s represents the point between edgePtA--edgePtB
- if (!(0 <= retPoint.x && retPoint.x <= 1))
- continue;
- }
- // As long as our t isn't negative we are at least finding a
- // correct hitpoint from m_tMidpoint to percentagePt.
- if (retPoint.y >= 0) {
- // Because the percentage line and all the texture edges are
- // rays we should only account for the shortest intersection
- if (retPoint.y < min_t) {
- min_t = retPoint.y;
- index = i;
- }
- }
- }
- }
-
- // Now that we have the minimum magnitude we can use that to find our intersection
- hit = cc.pAdd(locMidPoint, cc.pMult(cc.pSub(percentagePt, locMidPoint), min_t));
- }
-
- // The size of the vertex data is the index from the hitpoint
- // the 3 is for the m_tMidpoint, 12 o'clock point and hitpoint position.
- var sameIndexCount = true;
- if (this._vertexDataCount != index + 3) {
- sameIndexCount = false;
- this._vertexData = null;
- this._vertexArrayBuffer = null;
- this._vertexDataCount = 0;
- }
-
- if (!this._vertexData) {
- this._vertexDataCount = index + 3;
- var locCount = this._vertexDataCount, vertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
- this._vertexArrayBuffer = new ArrayBuffer(locCount * vertexDataLen);
- var locData = [];
- for (i = 0; i < locCount; i++)
- locData[i] = new cc.V2F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * vertexDataLen);
-
- this._vertexData = locData;
- cc.Assert(this._vertexData, "cc.ProgressTimer. Not enough memory");
- }
-
- var locVertexData = this._vertexData;
- if (!sameIndexCount) {
- // First we populate the array with the m_tMidpoint, then all
- // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint
- locVertexData[0].texCoords = this._textureCoordFromAlphaPoint(locMidPoint);
- locVertexData[0].vertices = this._vertexFromAlphaPoint(locMidPoint);
-
- locVertexData[1].texCoords = this._textureCoordFromAlphaPoint(topMid);
- locVertexData[1].vertices = this._vertexFromAlphaPoint(topMid);
-
- for (i = 0; i < index; i++) {
- var alphaPoint = this._boundaryTexCoord(i);
- locVertexData[i + 2].texCoords = this._textureCoordFromAlphaPoint(alphaPoint);
- locVertexData[i + 2].vertices = this._vertexFromAlphaPoint(alphaPoint);
- }
- }
-
- // hitpoint will go last
- locVertexData[this._vertexDataCount - 1].texCoords = this._textureCoordFromAlphaPoint(hit);
- locVertexData[this._vertexDataCount - 1].vertices = this._vertexFromAlphaPoint(hit);
- },
-
- /**
- *
- * Update does the work of mapping the texture onto the triangles for the bar
- * It now doesn't occur the cost of free/alloc data every update cycle.
- * It also only changes the percentage point but no other points if they have not been modified.
- *
- * It now deals with flipped texture. If you run into this problem, just use the
- * sprite property and enable the methods flipX, flipY.
- *
- * @private
- */
- _updateBar:function () {
- if (!this._sprite)
- return;
-
- var i;
- var alpha = this._percentage / 100.0;
- var locBarChangeRate = this._barChangeRate;
- var alphaOffset = cc.pMult(cc.p((1.0 - locBarChangeRate.x) + alpha * locBarChangeRate.x,
- (1.0 - locBarChangeRate.y) + alpha * locBarChangeRate.y), 0.5);
- var min = cc.pSub(this._midPoint, alphaOffset);
- var max = cc.pAdd(this._midPoint, alphaOffset);
-
- if (min.x < 0) {
- max.x += -min.x;
- min.x = 0;
- }
-
- if (max.x > 1) {
- min.x -= max.x - 1;
- max.x = 1;
- }
-
- if (min.y < 0) {
- max.y += -min.y;
- min.y = 0;
- }
-
- if (max.y > 1) {
- min.y -= max.y - 1;
- max.y = 1;
- }
-
- var locVertexData;
- if (!this._reverseDirection) {
- if (!this._vertexData) {
- this._vertexDataCount = 4;
- var vertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT, locCount = 4;
- this._vertexArrayBuffer = new ArrayBuffer(locCount * vertexDataLen);
- this._vertexData = [];
- for (i = 0; i < locCount; i++) {
- this._vertexData[i] = new cc.V2F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * vertexDataLen);
- }
- cc.Assert(this._vertexData, "cc.ProgressTimer. Not enough memory");
- }
-
- locVertexData = this._vertexData;
- // TOPLEFT
- locVertexData[0].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, max.y));
- locVertexData[0].vertices = this._vertexFromAlphaPoint(cc.p(min.x, max.y));
-
- // BOTLEFT
- locVertexData[1].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, min.y));
- locVertexData[1].vertices = this._vertexFromAlphaPoint(cc.p(min.x, min.y));
-
- // TOPRIGHT
- locVertexData[2].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, max.y));
- locVertexData[2].vertices = this._vertexFromAlphaPoint(cc.p(max.x, max.y));
-
- // BOTRIGHT
- locVertexData[3].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, min.y));
- locVertexData[3].vertices = this._vertexFromAlphaPoint(cc.p(max.x, min.y));
- } else {
- if (!this._vertexData) {
- this._vertexDataCount = 8;
- var rVertexDataLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT, rLocCount = 8;
- this._vertexArrayBuffer = new ArrayBuffer(rLocCount * rVertexDataLen);
- var rTempData = [];
- for (i = 0; i < rLocCount; i++)
- rTempData[i] = new cc.V2F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * rVertexDataLen);
-
- cc.Assert(rTempData, "cc.ProgressTimer. Not enough memory");
- // TOPLEFT 1
- rTempData[0].texCoords = this._textureCoordFromAlphaPoint(cc.p(0, 1));
- rTempData[0].vertices = this._vertexFromAlphaPoint(cc.p(0, 1));
-
- // BOTLEFT 1
- rTempData[1].texCoords = this._textureCoordFromAlphaPoint(cc.p(0, 0));
- rTempData[1].vertices = this._vertexFromAlphaPoint(cc.p(0, 0));
-
- // TOPRIGHT 2
- rTempData[6].texCoords = this._textureCoordFromAlphaPoint(cc.p(1, 1));
- rTempData[6].vertices = this._vertexFromAlphaPoint(cc.p(1, 1));
-
- // BOTRIGHT 2
- rTempData[7].texCoords = this._textureCoordFromAlphaPoint(cc.p(1, 0));
- rTempData[7].vertices = this._vertexFromAlphaPoint(cc.p(1, 0));
-
- this._vertexData = rTempData;
- }
-
- locVertexData = this._vertexData;
- // TOPRIGHT 1
- locVertexData[2].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, max.y));
- locVertexData[2].vertices = this._vertexFromAlphaPoint(cc.p(min.x, max.y));
-
- // BOTRIGHT 1
- locVertexData[3].texCoords = this._textureCoordFromAlphaPoint(cc.p(min.x, min.y));
- locVertexData[3].vertices = this._vertexFromAlphaPoint(cc.p(min.x, min.y));
-
- // TOPLEFT 2
- locVertexData[4].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, max.y));
- locVertexData[4].vertices = this._vertexFromAlphaPoint(cc.p(max.x, max.y));
-
- // BOTLEFT 2
- locVertexData[5].texCoords = this._textureCoordFromAlphaPoint(cc.p(max.x, min.y));
- locVertexData[5].vertices = this._vertexFromAlphaPoint(cc.p(max.x, min.y));
- }
- },
-
- _updateColor:function () {
- if (!this._sprite || !this._vertexData)
- return;
-
- var sc = this._sprite.getQuad().tl.colors;
- var locVertexData = this._vertexData;
- for (var i = 0, len = this._vertexDataCount; i < len; ++i)
- locVertexData[i].colors = sc;
- this._vertexDataDirty = true;
- },
-
- _updateProgress:null,
-
- _updateProgressForCanvas:function () {
- var locSprite = this._sprite;
- var spriteSize = locSprite.getContentSize();
- var locMidPoint = this._midPoint;
-
- if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) {
- this._radius = Math.round(Math.sqrt(spriteSize.width * spriteSize.width + spriteSize.height * spriteSize.height));
- var locStartAngle = 270;
- var locEndAngle = 270;
- var locCounterClockWise = false;
- var locOrigin = this._origin;
-
- locOrigin.x = spriteSize.width * locMidPoint.x;
- locOrigin.y = -spriteSize.height * locMidPoint.y;
-
- if (this._reverseDirection) {
- locStartAngle = 270 - 3.6 * this._percentage;
- } else {
- locEndAngle = 270 + 3.6 * this._percentage;
- }
-
- if (locSprite._flippedX) {
- locOrigin.x -= spriteSize.width * (this._midPoint.x * 2);
- locStartAngle= -locStartAngle;
- locEndAngle= -locEndAngle;
- locStartAngle -= 180;
- locEndAngle -= 180;
- locCounterClockWise = !locCounterClockWise;
- }
- if (locSprite._flippedY) {
- locOrigin.y+=spriteSize.height*(this._midPoint.y*2);
- locCounterClockWise = !locCounterClockWise;
- locStartAngle= -locStartAngle;
- locEndAngle= -locEndAngle;
- }
-
- this._startAngle = locStartAngle;
- this._endAngle = locEndAngle;
- this._counterClockWise = locCounterClockWise;
- } else {
- var locBarChangeRate = this._barChangeRate;
- var percentageF = this._percentage / 100;
- var locBarRect = this._barRect;
-
- var drawedSize = cc.size((spriteSize.width * (1 - locBarChangeRate.x)), (spriteSize.height * (1 - locBarChangeRate.y)));
- var drawingSize = cc.size((spriteSize.width - drawedSize.width) * percentageF, (spriteSize.height - drawedSize.height) * percentageF);
- var currentDrawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height);
-
- var startPoint = cc.p(spriteSize.width * locMidPoint.x, spriteSize.height * locMidPoint.y);
-
- var needToLeft = startPoint.x - currentDrawSize.width / 2;
- if (locMidPoint.x > 0.5) {
- if (currentDrawSize.width / 2 >= spriteSize.width - startPoint.x) {
- needToLeft = spriteSize.width - currentDrawSize.width;
- }
- }
-
- var needToTop = startPoint.y - currentDrawSize.height / 2;
- if (locMidPoint.y > 0.5) {
- if (currentDrawSize.height / 2 >= spriteSize.height - startPoint.y) {
- needToTop = spriteSize.height - currentDrawSize.height;
- }
- }
-
- //left pos
- locBarRect.x = 0;
- var flipXNeed = 1;
- if (locSprite._flippedX) {
- locBarRect.x -= currentDrawSize.width;
- flipXNeed = -1;
- }
-
- if (needToLeft > 0)
- locBarRect.x += needToLeft * flipXNeed;
-
- //right pos
- locBarRect.y = 0;
- var flipYNeed = 1;
- if (locSprite._flippedY) {
- locBarRect.y += currentDrawSize.height;
- flipYNeed = -1;
- }
-
- if (needToTop > 0)
- locBarRect.y -= needToTop * flipYNeed;
-
- //clip width and clip height
- locBarRect.width = currentDrawSize.width;
- locBarRect.height = -currentDrawSize.height;
- }
- },
-
- _updateProgressForWebGL:function () {
- var locType = this._type;
- if(locType === cc.PROGRESS_TIMER_TYPE_RADIAL)
- this._updateRadial();
- else if(locType === cc.PROGRESS_TIMER_TYPE_BAR)
- this._updateBar();
- this._updateColor();
- this._vertexDataDirty = true;
- }
-});
-
-if(cc.Browser.supportWebGL) {
- cc.ProgressTimer.prototype.ctor = cc.ProgressTimer.prototype._ctorForWebGL;
- cc.ProgressTimer.prototype.setReverseProgress = cc.ProgressTimer.prototype._setReverseProgressForWebGL;
- cc.ProgressTimer.prototype.setSprite = cc.ProgressTimer.prototype._setSpriteForWebGL;
- cc.ProgressTimer.prototype.setType = cc.ProgressTimer.prototype._setTypeForWebGL;
- cc.ProgressTimer.prototype.setReverseDirection = cc.ProgressTimer.prototype._setReverseDirectionForWebGL;
- cc.ProgressTimer.prototype.initWithSprite = cc.ProgressTimer.prototype._initWithSpriteForWebGL;
- cc.ProgressTimer.prototype.draw = cc.ProgressTimer.prototype._drawForWebGL;
- cc.ProgressTimer.prototype._updateProgress = cc.ProgressTimer.prototype._updateProgressForWebGL;
-} else {
- cc.ProgressTimer.prototype.ctor = cc.ProgressTimer.prototype._ctorForCanvas;
- cc.ProgressTimer.prototype.setReverseProgress = cc.ProgressTimer.prototype._setReverseProgressForCanvas;
- cc.ProgressTimer.prototype.setSprite = cc.ProgressTimer.prototype._setSpriteForCanvas;
- cc.ProgressTimer.prototype.setType = cc.ProgressTimer.prototype._setTypeForCanvas;
- cc.ProgressTimer.prototype.setReverseDirection = cc.ProgressTimer.prototype._setReverseDirectionForCanvas;
- cc.ProgressTimer.prototype.initWithSprite = cc.ProgressTimer.prototype._initWithSpriteForCanvas;
- cc.ProgressTimer.prototype.draw = cc.ProgressTimer.prototype._drawForCanvas;
- cc.ProgressTimer.prototype._updateProgress = cc.ProgressTimer.prototype._updateProgressForCanvas;
-}
-
-/**
- * create a progress timer object with image file name that renders the inner sprite according to the percentage
- * @param {cc.Sprite} sprite
- * @return {cc.ProgressTimer}
- * @example
- * // Example
- * var progress = cc.ProgressTimer.create('progress.png')
- */
-cc.ProgressTimer.create = function (sprite) {
- var progressTimer = new cc.ProgressTimer();
- if (progressTimer.initWithSprite(sprite))
- return progressTimer;
- return null;
-};
-
-
diff --git a/cocos2d/misc_nodes/CCRenderTexture.js b/cocos2d/misc_nodes/CCRenderTexture.js
deleted file mode 100644
index ad64040ea0..0000000000
--- a/cocos2d/misc_nodes/CCRenderTexture.js
+++ /dev/null
@@ -1,866 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2009 Jason Booth
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * enum for jpg
- * @constant
- * @type Number
- */
-cc.IMAGE_FORMAT_JPEG = 0;
-/**
- * enum for png
- * @constant
- * @type Number
- */
-cc.IMAGE_FORMAT_PNG = 1;
-/**
- * enum for raw
- * @constant
- * @type Number
- */
-cc.IMAGE_FORMAT_RAWDATA = 2;
-
-/**
- * @param {Number} x
- * @return {Number}
- * Constructor
- */
-cc.NextPOT = function (x) {
- x = x - 1;
- x = x | (x >> 1);
- x = x | (x >> 2);
- x = x | (x >> 4);
- x = x | (x >> 8);
- x = x | (x >> 16);
- return x + 1;
-};
-
-/**
- * cc.RenderTexture is a generic rendering target. To render things into it,
- * simply construct a render target, call begin on it, call visit on any cocos
- * scenes or objects to render them, and call end. For convenience, render texture
- * adds a sprite as it's display child with the results, so you can simply add
- * the render texture to your scene and treat it like any other CocosNode.
- * There are also functions for saving the render texture to disk in PNG or JPG format.
- * @class
- * @extends cc.Node
- */
-cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{
- /**
- * the off-screen canvas for rendering and storing the texture
- * @type HTMLCanvasElement
- */
- _cacheCanvas:null,
- /**
- * stores a reference to the canvas context object
- * @type CanvasRenderingContext2D
- */
- _cacheContext:null,
-
- _fBO:0,
- _depthRenderBuffer:0,
- _oldFBO:0,
- _texture:null,
- _textureCopy:null,
- _uITextureImage:null,
-
- _pixelFormat:cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888,
- _sprite:null,
-
- //code for "auto" update
- _clearFlags:0,
- _clearColor:null,
- _clearDepth:0,
- _clearStencil:0,
- _autoDraw:false,
-
- _clearColorStr:null,
-
- /**
- * Constructor
- */
- ctor: null,
-
- _ctorForCanvas: function () {
- cc.Node.prototype.ctor.call(this);
- this._clearColor = cc.c4f(1, 1, 1, 1);
- this._clearColorStr = "rgba(255,255,255,1)";
-
- this._cacheCanvas = document.createElement('canvas');
- this._cacheContext = this._cacheCanvas.getContext('2d');
- this.setAnchorPoint(cc.p(0, 0));
- },
-
- _ctorForWebGL: function () {
- cc.Node.prototype.ctor.call(this);
- this._clearColor = cc.c4f(0, 0, 0, 0);
- },
-
- onExit:null,
-
- _onExitForCanvas:function () {
- cc.Node.prototype.onExit.call(this);
- this._cacheContext = null;
- this._cacheCanvas = null;
- },
-
- _onExitForWebGL: function () {
- cc.Node.prototype.onExit.call(this);
-
- this._sprite = null;
- this._textureCopy = null;
-
- var gl = cc.renderContext;
- gl.deleteFramebuffer(this._fBO);
- if (this._depthRenderBuffer)
- gl.deleteRenderbuffer(this._depthRenderBuffer);
- this._uITextureImage = null;
- if (this._texture)
- this._texture.releaseTexture();
- },
-
- /**
- * The sprite
- * @return {cc.Sprite}
- */
- getSprite:function () {
- return this._sprite;
- },
-
- /**
- * @param {cc.Sprite} sprite
- */
- setSprite:function (sprite) {
- this._sprite = sprite;
- },
-
- /**
- * @param {Number} width
- * @param {Number} height
- * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
- * @param {Number} depthStencilFormat
- * @return {Boolean}
- */
- initWithWidthAndHeight: null,
-
- _initWithWidthAndHeightForCanvas: function (width, height, format, depthStencilFormat) {
- var locCacheCanvas = this._cacheCanvas, locScaleFactor = cc.CONTENT_SCALE_FACTOR();
- locCacheCanvas.width = 0 | (width * locScaleFactor);
- locCacheCanvas.height = 0 | (height * locScaleFactor);
- this._cacheContext.translate(0, locCacheCanvas.height);
- var texture = new cc.Texture2D();
- texture.initWithElement(locCacheCanvas);
- texture.handleLoadedTexture();
- this._sprite = cc.Sprite.createWithTexture(texture);
- return true;
- },
-
- _initWithWidthAndHeightForWebGL: function (width, height, format, depthStencilFormat) {
- cc.Assert(format != cc.TEXTURE_2D_PIXEL_FORMAT_A8, "only RGB and RGBA formats are valid for a render texture");
-
- var gl = cc.renderContext, locScaleFactor = cc.CONTENT_SCALE_FACTOR();
-
- width = 0 | (width * locScaleFactor);
- height = 0 | (height * locScaleFactor);
-
- this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
-
- // textures must be power of two squared
- var powW , powH;
-
- if (cc.Configuration.getInstance().supportsNPOT()) {
- powW = width;
- powH = height;
- } else {
- powW = cc.NextPOT(width);
- powH = cc.NextPOT(height);
- }
-
- //void *data = malloc(powW * powH * 4);
- var dataLen = powW * powH * 4;
- var data = new Uint8Array(dataLen);
- //memset(data, 0, (int)(powW * powH * 4));
- for (var i = 0; i < powW * powH * 4; i++)
- data[i] = 0;
-
- this._pixelFormat = format;
-
- this._texture = new cc.Texture2D();
- if (!this._texture)
- return false;
-
- var locTexture = this._texture;
- locTexture.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height));
- //free( data );
-
- var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING);
-
- if (cc.Configuration.getInstance().checkForGLExtension("GL_QCOM")) {
- this._textureCopy = new cc.Texture2D();
- if (!this._textureCopy) {
- return false;
- }
- this._textureCopy.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height));
- }
-
- // generate FBO
- this._fBO = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);
-
- // associate texture with FBO
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, locTexture._webTextureObj, 0);
-
- if (depthStencilFormat != 0) {
- //create and attach depth buffer
- this._depthRenderBuffer = gl.createRenderbuffer();
- gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderBuffer);
- gl.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, powW, powH);
- gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
-
- // if depth format is the one with stencil part, bind same render buffer as stencil attachment
- //if (depthStencilFormat == gl.DEPTH24_STENCIL8)
- // gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
- }
-
- // check if it worked (probably worth doing :) )
- cc.Assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer");
-
- locTexture.setAliasTexParameters();
-
- this._sprite = cc.Sprite.createWithTexture(locTexture);
- var locSprite = this._sprite;
- locSprite.setScaleY(-1);
- locSprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
-
- gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO);
- gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
-
- // Disabled by default.
- this._autoDraw = false;
-
- // add sprite for backward compatibility
- this.addChild(locSprite);
- return true;
- },
-
- /**
- * starts grabbing
- */
- begin: null,
-
- _beginForCanvas: function () {
- cc.renderContext = this._cacheContext;
- cc.EGLView.getInstance()._setScaleXYForRenderTexture();
-
- /*// Save the current matrix
- cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
- cc.kmGLPushMatrix();
- cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
- cc.kmGLPushMatrix();*/
- },
-
- _beginForWebGL: function () {
- // Save the current matrix
- cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
- cc.kmGLPushMatrix();
- cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
- cc.kmGLPushMatrix();
-
- var director = cc.Director.getInstance();
- director.setProjection(director.getProjection());
-
- var texSize = this._texture.getContentSizeInPixels();
-
- // Calculate the adjustment ratios based on the old and new projections
- var size = cc.Director.getInstance().getWinSizeInPixels();
- var widthRatio = size.width / texSize.width;
- var heightRatio = size.height / texSize.height;
-
- var gl = cc.renderContext;
-
- // Adjust the orthographic projection and viewport
- gl.viewport(0, 0, texSize.width, texSize.height);
-
- var orthoMatrix = new cc.kmMat4();
- cc.kmMat4OrthographicProjection(orthoMatrix, -1.0 / widthRatio, 1.0 / widthRatio,
- -1.0 / heightRatio, 1.0 / heightRatio, -1, 1);
- cc.kmGLMultMatrix(orthoMatrix);
-
- this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
- gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);//Will direct drawing to the frame buffer created above
-
- /* Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture.
- * The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture.
- * Create a temporary texture to overcome this. At the end of CCRenderTexture::begin(), switch the attached texture to the second one, call glClear,
- * and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers.
- */
- if (cc.Configuration.getInstance().checkForGLExtension("GL_QCOM")) {
- // -- bind a temporary texture so we can clear the render buffer without losing our texture
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._textureCopy._webTextureObj, 0);
- //cc.CHECK_GL_ERROR_DEBUG();
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._texture._webTextureObj, 0);
- }
- },
-
- /**
- * starts rendering to the texture while clearing the texture first.
- * This is more efficient then calling -clear first and then -begin
- * @param {Number} r red 0-1
- * @param {Number} g green 0-1
- * @param {Number} b blue 0-1
- * @param {Number} a alpha 0-1 0 is transparent
- * @param {Number} [depthValue=]
- * @param {Number} [stencilValue=]
- */
- beginWithClear:function (r, g, b, a, depthValue, stencilValue) {
- var gl = cc.renderContext;
- depthValue = depthValue || gl.COLOR_BUFFER_BIT;
- stencilValue = stencilValue || (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
- this._beginWithClear(r, g, b, a, depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
- },
-
- _beginWithClear: null,
-
- _beginWithClearForCanvas: function (r, g, b, a, depthValue, stencilValue, flags) {
- this.begin();
-
- r = r || 0;
- g = g || 0;
- b = b || 0;
- a = a || 1;
-
- //var context = cc.renderContext;
- var context = this._cacheContext;
- var locCanvas = this._cacheCanvas;
- context.save();
- context.fillStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")";
- context.clearRect(0, 0, locCanvas.width, -locCanvas.height);
- context.fillRect(0, 0, locCanvas.width, -locCanvas.height);
- context.restore();
- },
-
- _beginWithClearForWebGL: function (r, g, b, a, depthValue, stencilValue, flags) {
- this.begin();
-
- var gl = cc.renderContext;
-
- // save clear color
- var clearColor = [0.0, 0.0, 0.0, 0.0];
- var depthClearValue = 0.0;
- var stencilClearValue = 0;
-
- if (flags & gl.COLOR_BUFFER_BIT) {
- clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
- gl.clearColor(r, g, b, a);
- }
-
- if (flags & gl.DEPTH_BUFFER_BIT) {
- depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
- gl.clearDepth(depthValue);
- }
-
- if (flags & gl.STENCIL_BUFFER_BIT) {
- stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
- gl.clearStencil(stencilValue);
- }
-
- gl.clear(flags);
-
- // restore
- if (flags & gl.COLOR_BUFFER_BIT)
- gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
-
- if (flags & gl.DEPTH_BUFFER_BIT)
- gl.clearDepth(depthClearValue);
-
- if (flags & gl.STENCIL_BUFFER_BIT)
- gl.clearStencil(stencilClearValue);
- },
-
- /**
- * ends grabbing
- */
- end: null,
-
- _endForCanvas: function () {
- cc.renderContext = cc.mainRenderContextBackup;
- cc.EGLView.getInstance()._resetScale();
-
- //TODO
- /*//restore viewport
- director.setViewport();
- cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
- cc.kmGLPopMatrix();
- cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
- cc.kmGLPopMatrix();*/
- },
-
- _endForWebGL: function () {
- var gl = cc.renderContext;
- var director = cc.Director.getInstance();
- gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
-
- //restore viewport
- director.setViewport();
- cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
- cc.kmGLPopMatrix();
- cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
- cc.kmGLPopMatrix();
-
- /* var size = director.getWinSizeInPixels();
-
- // restore viewport
- gl.viewport(0, 0, size.width * cc.CONTENT_SCALE_FACTOR(), size.height * cc.CONTENT_SCALE_FACTOR());
-
- // special viewport for 3d projection + retina display
- if (director.getProjection() == cc.DIRECTOR_PROJECTION_3D && cc.CONTENT_SCALE_FACTOR() != 1) {
- gl.viewport((-size.width / 2), (-size.height / 2), (size.width * cc.CONTENT_SCALE_FACTOR()), (size.height * cc.CONTENT_SCALE_FACTOR()));
- }
-
- director.setProjection(director.getProjection());*/
- },
-
- /**
- * clears the texture with a color
- * @param {Number|cc.Rect} r red 0-1
- * @param {Number} g green 0-1
- * @param {Number} b blue 0-1
- * @param {Number} a alpha 0-1
- */
- clear:function (r, g, b, a) {
- this.beginWithClear(r, g, b, a);
- this.end();
- },
-
- clearRect:null,
-
- _clearRectForCanvas:function(x, y, width, height){
- this._cacheContext.clearRect(x, y, width, -height);
- },
-
- _clearRectForWebGL:function(x, y, width, height){
- //TODO need to implement
- },
-
- /**
- * clears the texture with a specified depth value
- * @param {Number} depthValue
- */
- clearDepth:null,
-
- _clearDepthForCanvas:function (depthValue) {
- cc.log("clearDepth isn't supported on Cocos2d-Html5");
- },
-
- _clearDepthForWebGL:function (depthValue) {
- this.begin();
-
- var gl = cc.renderContext;
- //! save old depth value
- var depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
-
- gl.clearDepth(depthValue);
- gl.clear(gl.DEPTH_BUFFER_BIT);
-
- // restore clear color
- gl.clearDepth(depthClearValue);
- this.end();
- },
-
- /**
- * clears the texture with a specified stencil value
- * @param {Number} stencilValue
- */
- clearStencil:null,
-
- _clearStencilForCanvas:function (stencilValue) {
- cc.log("clearDepth isn't supported on Cocos2d-Html5");
- },
-
- _clearStencilForWebGL:function (stencilValue) {
- var gl = cc.renderContext;
- // save old stencil value
- var stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
-
- gl.clearStencil(stencilValue);
- gl.clear(gl.STENCIL_BUFFER_BIT);
-
- // restore clear color
- gl.clearStencil(stencilClearValue);
- },
-
- visit:null,
-
- _visitForCanvas:function (ctx) {
- // override visit.
- // Don't call visit on its children
- if (!this._visible)
- return;
-
- ctx = ctx || cc.renderContext;
- ctx.save();
-
- this.draw(ctx); // update children of RenderTexture before
- this.transform(ctx);
- this._sprite.visit(); // draw the RenderTexture
-
- ctx.restore();
-
- this._orderOfArrival = 0;
- },
-
- _visitForWebGL:function (ctx) {
- // override visit.
- // Don't call visit on its children
- if (!this._visible)
- return;
-
- cc.kmGLPushMatrix();
-
- var locGrid = this._grid;
- if (locGrid && locGrid.isActive()) {
- locGrid.beforeDraw();
- this.transformAncestors();
- }
-
- this.transform(ctx);
- this._sprite.visit();
- this.draw(ctx);
-
- if (locGrid && locGrid.isActive())
- locGrid.afterDraw(this);
-
- cc.kmGLPopMatrix();
-
- this._orderOfArrival = 0;
- },
-
- draw:null,
-
- _drawForCanvas: function (ctx) {
- ctx = ctx || cc.renderContext;
- if (this._autoDraw) {
- this.begin();
-
- if (this._clearFlags) {
- var locCanvas = this._cacheCanvas;
- ctx.save();
- ctx.fillStyle = this._clearColorStr;
- ctx.clearRect(0, 0, locCanvas.width, -locCanvas.height);
- ctx.fillRect(0, 0, locCanvas.width, -locCanvas.height);
- ctx.restore();
- }
-
- //! make sure all children are drawn
- this.sortAllChildren();
- var locChildren = this._children;
- var childrenLen = locChildren.length;
- var selfSprite = this._sprite;
- for (var i = 0; i < childrenLen; i++) {
- var getChild = locChildren[i];
- if (getChild != selfSprite)
- getChild.visit();
- }
-
- this.end();
- }
- },
-
- _drawForWebGL: function (ctx) {
- var gl = cc.renderContext;
- if (this._autoDraw) {
- this.begin();
-
- var locClearFlags = this._clearFlags;
- if (locClearFlags) {
- var oldClearColor = [0.0, 0.0, 0.0, 0.0];
- var oldDepthClearValue = 0.0;
- var oldStencilClearValue = 0;
-
- // backup and set
- if (locClearFlags & gl.COLOR_BUFFER_BIT) {
- oldClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
- gl.clearColor(this._clearColor.r, this._clearColor.g, this._clearColor.b, this._clearColor.a);
- }
-
- if (locClearFlags & gl.DEPTH_BUFFER_BIT) {
- oldDepthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
- gl.clearDepth(this._clearDepth);
- }
-
- if (locClearFlags & gl.STENCIL_BUFFER_BIT) {
- oldStencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
- gl.clearStencil(this._clearStencil);
- }
-
- // clear
- gl.clear(locClearFlags);
-
- // restore
- if (locClearFlags & gl.COLOR_BUFFER_BIT)
- gl.clearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]);
-
- if (locClearFlags & gl.DEPTH_BUFFER_BIT)
- gl.clearDepth(oldDepthClearValue);
-
- if (locClearFlags & gl.STENCIL_BUFFER_BIT)
- gl.clearStencil(oldStencilClearValue);
- }
-
- //! make sure all children are drawn
- this.sortAllChildren();
- var locChildren = this._children;
- for (var i = 0; i < locChildren.length; i++) {
- var getChild = locChildren[i];
- if (getChild != this._sprite)
- getChild.visit();
- }
-
- this.end();
- }
- },
-
- /**
- * creates a new CCImage from with the texture's data. Caller is responsible for releasing it by calling delete.
- * @return {cc.Image}
- */
- newCCImage:null,
-
- _newCCImageForCanvas:function (flipImage) {
- cc.log("saveToFile isn't supported on Cocos2d-Html5");
- return null;
- },
-
- _newCCImageForWebGL:function (flipImage) {
- if(flipImage === null)
- flipImage = true;
- cc.Assert(this._pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, "only RGBA8888 can be saved as image");
-
- if (!this._texture)
- return null;
-
- var size = this._texture.getContentSizeInPixels();
-
- // to get the image size to save
- // if the saving image domain exeeds the buffer texture domain,
- // it should be cut
- var nSavedBufferWidth = size.width;
- var nSavedBufferHeight = size.height;
-
- var pImage = new cc.Image();
- var gl = cc.renderContext;
-
- var pBuffer = new Uint8Array(nSavedBufferWidth * nSavedBufferHeight * 4);
- if (!(pBuffer))
- return pImage;
-
- var pTempData = new Uint8Array(nSavedBufferWidth * nSavedBufferHeight * 4);
- if (!(pTempData))
- return null;
-
- this.begin();
- gl.pixelStorei(gl.PACK_ALIGNMENT, 1);
- gl.readPixels(0, 0, nSavedBufferWidth, nSavedBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pTempData);
- this.end();
-
- // to get the actual texture data
- // #640 the image read from rendertexture is upseted
- for (var i = 0; i < nSavedBufferHeight; ++i) {
- this._memcpy(pBuffer, i * nSavedBufferWidth * 4,
- pTempData, (nSavedBufferHeight - i - 1) * nSavedBufferWidth * 4,
- nSavedBufferWidth * 4);
- }
- pImage.initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, cc.FMT_RAWDATA, nSavedBufferWidth, nSavedBufferHeight, 8);
-
- pBuffer = null;
- pTempData = null;
- return pImage;
- },
-
- _memcpy:function (destArr, destIndex, srcArr, srcIndex, size) {
- for (var i = 0; i < size; i++) {
- destArr[destIndex + i] = srcArr[srcIndex + i];
- }
- },
-
- /**
- * saves the texture into a file using JPEG format. The file will be saved in the Documents folder.
- * Returns YES if the operation is successful.
- * (doesn't support in HTML5)
- * @param {Number} filePath
- * @param {Number} format
- */
- saveToFile:function (filePath, format) {
- cc.log("saveToFile isn't supported on Cocos2d-Html5");
- },
-
- /**
- * Listen "come to background" message, and save render texture. It only has effect on Android.
- * @param {cc.Class} obj
- */
- listenToBackground:function (obj) {
- cc.log("listenToBackground isn't supported on Cocos2d-Html5");
- },
-
- /**
- * Listen "come to foreground" message and restore the frame buffer object. It only has effect on Android.
- * @param {cc.Class} obj
- */
- listenToForeground:function (obj) {
- cc.log("listenToForeground isn't supported on Cocos2d-Html5");
- },
-
- /**
- * Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES.
- * @return {Number}
- */
- getClearFlags:function () {
- return this._clearFlags;
- },
-
- setClearFlags:function (clearFlags) {
- this._clearFlags = clearFlags;
- },
-
- /**
- * Clear color value. Valid only when "autoDraw" is true.
- * @return {cc.Color4F}
- */
- getClearColor:function () {
- return this._clearColor;
- },
-
- setClearColor:null,
-
- _setClearColorForCanvas:function (clearColor) {
- var locClearColor = this._clearColor;
- locClearColor.r = clearColor.r;
- locClearColor.g = clearColor.g;
- locClearColor.b = clearColor.b;
- locClearColor.a = clearColor.a;
-
- this._clearColorStr = "rgba(" + (0 | (clearColor.r * 255)) + "," + (0 | (clearColor.g * 255)) + "," + (0 | (clearColor.b * 255)) + "," + clearColor.a + ")";
- },
-
- _setClearColorForWebGL:function (clearColor) {
- var locClearColor = this._clearColor;
- locClearColor.r = clearColor.r;
- locClearColor.g = clearColor.g;
- locClearColor.b = clearColor.b;
- locClearColor.a = clearColor.a;
- },
-
- /**
- * Value for clearDepth. Valid only when autoDraw is true.
- * @return {Number}
- */
- getClearDepth:function () {
- return this._clearDepth;
- },
-
- setClearDepth:function (clearDepth) {
- this._clearDepth = clearDepth;
- },
-
- /**
- * Value for clear Stencil. Valid only when autoDraw is true
- * @return {Number}
- */
- getClearStencil:function () {
- return this._clearStencil;
- },
-
- setClearStencil:function (clearStencil) {
- this._clearStencil = clearStencil;
- },
-
- /**
- * When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons.
- * Will be enabled in the future.
- * @return {Boolean}
- */
- isAutoDraw:function () {
- return this._autoDraw;
- },
-
- setAutoDraw:function (autoDraw) {
- this._autoDraw = autoDraw;
- }
-});
-
-if(cc.Browser.supportWebGL){
- cc.RenderTexture.prototype.ctor = cc.RenderTexture.prototype._ctorForWebGL;
- cc.RenderTexture.prototype.onExit = cc.RenderTexture.prototype._onExitForWebGL;
- cc.RenderTexture.prototype.initWithWidthAndHeight = cc.RenderTexture.prototype._initWithWidthAndHeightForWebGL;
- cc.RenderTexture.prototype.begin = cc.RenderTexture.prototype._beginForWebGL;
- cc.RenderTexture.prototype._beginWithClear = cc.RenderTexture.prototype._beginWithClearForWebGL;
- cc.RenderTexture.prototype.end = cc.RenderTexture.prototype._endForWebGL;
- cc.RenderTexture.prototype.clearRect = cc.RenderTexture.prototype._clearRectForWebGL;
- cc.RenderTexture.prototype.clearDepth = cc.RenderTexture.prototype._clearDepthForWebGL;
- cc.RenderTexture.prototype.clearStencil = cc.RenderTexture.prototype._clearStencilForWebGL;
- cc.RenderTexture.prototype.visit = cc.RenderTexture.prototype._visitForWebGL;
- cc.RenderTexture.prototype.draw = cc.RenderTexture.prototype._drawForWebGL;
- cc.RenderTexture.prototype.newCCImage = cc.RenderTexture.prototype._newCCImageForWebGL;
- cc.RenderTexture.prototype.setClearColor = cc.RenderTexture.prototype._setClearColorForWebGL;
-} else {
- cc.RenderTexture.prototype.ctor = cc.RenderTexture.prototype._ctorForCanvas;
- cc.RenderTexture.prototype.onExit = cc.RenderTexture.prototype._onExitForCanvas;
- cc.RenderTexture.prototype.initWithWidthAndHeight = cc.RenderTexture.prototype._initWithWidthAndHeightForCanvas;
- cc.RenderTexture.prototype.begin = cc.RenderTexture.prototype._beginForCanvas;
- cc.RenderTexture.prototype._beginWithClear = cc.RenderTexture.prototype._beginWithClearForCanvas;
- cc.RenderTexture.prototype.end = cc.RenderTexture.prototype._endForCanvas;
- cc.RenderTexture.prototype.clearRect = cc.RenderTexture.prototype._clearRectForCanvas;
- cc.RenderTexture.prototype.clearDepth = cc.RenderTexture.prototype._clearDepthForCanvas;
- cc.RenderTexture.prototype.clearStencil = cc.RenderTexture.prototype._clearStencilForCanvas;
- cc.RenderTexture.prototype.visit = cc.RenderTexture.prototype._visitForCanvas;
- cc.RenderTexture.prototype.draw = cc.RenderTexture.prototype._drawForCanvas;
- cc.RenderTexture.prototype.newCCImage = cc.RenderTexture.prototype._newCCImageForCanvas;
- cc.RenderTexture.prototype.setClearColor = cc.RenderTexture.prototype._setClearColorForCanvas;
-}
-
-/**
- * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid
- * @param {Number} width
- * @param {Number} height
- * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
- * @param {Number} depthStencilFormat
- * @return {cc.RenderTexture}
- * @example
- * // Example
- * var rt = cc.RenderTexture.create()
- */
-cc.RenderTexture.create = function (width, height, format, depthStencilFormat) {
- format = format || cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888;
- depthStencilFormat = depthStencilFormat || 0;
-
- var ret = new cc.RenderTexture();
- if (ret && ret.initWithWidthAndHeight(width, height, format, depthStencilFormat))
- return ret;
- return null;
-};
diff --git a/cocos2d/misc_nodes/CCMotionStreak.js b/cocos2d/motion-streak/CCMotionStreak.js
similarity index 57%
rename from cocos2d/misc_nodes/CCMotionStreak.js
rename to cocos2d/motion-streak/CCMotionStreak.js
index fc51bb9bda..158393454a 100644
--- a/cocos2d/misc_nodes/CCMotionStreak.js
+++ b/cocos2d/motion-streak/CCMotionStreak.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2008-2009 Jason Booth
http://www.cocos2d-x.org
@@ -34,51 +34,62 @@
* length is the how many pixels the texture is stretched across. The texture
* is vertically aligned along the streak segment.
* @class
- * @extends cc.NodeRGBA
+ * @extends cc.Node
+ *
+ * @property {cc.Texture2D} texture - Texture used for the motion streak.
+ * @property {Boolean} fastMode - Indicate whether use fast mode.
+ * @property {Boolean} startingPositionInitialized - Indicate whether starting position initialized.
+ * @example
+ * //example
+ * new cc.MotionStreak(2, 3, 32, cc.color.GREEN, s_streak);
*/
-cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
- _fastMode:false,
- _startingPositionInitialized:false,
+cc.MotionStreak = cc.Node.extend(/** @lends cc.MotionStreak# */{
+ texture: null,
+ fastMode: false,
+ startingPositionInitialized: false,
- /** texture used for the motion streak */
- _texture:null,
- _blendFunc:null,
- _positionR:null,
+ _blendFunc: null,
- _stroke:0,
- _fadeDelta:0,
- _minSeg:0,
+ _stroke: 0,
+ _fadeDelta: 0,
+ _minSeg: 0,
- _maxPoints:0,
- _nuPoints:0,
- _previousNuPoints:0,
+ _maxPoints: 0,
+ _nuPoints: 0,
+ _previousNuPoints: 0,
- /** Pointers */
- _pointVertexes:null,
- _pointState:null,
+ /* Pointers */
+ _pointVertexes: null,
+ _pointState: null,
// webgl
- _vertices:null,
- _colorPointer:null,
- _texCoords:null,
+ _vertices: null,
+ _colorPointer: null,
+ _texCoords: null,
- _verticesBuffer:null,
- _colorPointerBuffer:null,
- _texCoordsBuffer:null,
+ _verticesBuffer: null,
+ _colorPointerBuffer: null,
+ _texCoordsBuffer: null,
+ _className: "MotionStreak",
/**
- * Constructor
+ * creates and initializes a motion streak with fade in seconds, minimum segments, stroke's width, color, texture filename or texture
+ * Constructor of cc.MotionStreak
+ * @param {Number} fade time to fade
+ * @param {Number} minSeg minimum segment size
+ * @param {Number} stroke stroke's width
+ * @param {Number} color
+ * @param {string|cc.Texture2D} texture texture filename or texture
*/
- ctor: function () {
- cc.NodeRGBA.prototype.ctor.call(this);
- this._positionR = cc.PointZero();
- this._blendFunc = new cc.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
- this._vertexWebGLBuffer = cc.renderContext.createBuffer();
+ ctor: function (fade, minSeg, stroke, color, texture) {
+ cc.Node.prototype.ctor.call(this);
+ this._positionR = cc.p(0, 0);
+ this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
- this._fastMode = false;
- this._startingPositionInitialized = false;
+ this.fastMode = false;
+ this.startingPositionInitialized = false;
- this._texture = null;
+ this.texture = null;
this._stroke = 0;
this._fadeDelta = 0;
@@ -100,87 +111,131 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
this._verticesBuffer = null;
this._colorPointerBuffer = null;
this._texCoordsBuffer = null;
+
+ if (texture !== undefined)
+ this.initWithFade(fade, minSeg, stroke, color, texture);
},
/**
+ * Gets the texture.
* @return {cc.Texture2D}
*/
- getTexture:function () {
- return this._texture;
+ getTexture: function () {
+ return this.texture;
},
/**
+ * Set the texture.
* @param {cc.Texture2D} texture
*/
- setTexture:function (texture) {
- if (this._texture != texture)
- this._texture = texture;
+ setTexture: function (texture) {
+ if (this.texture !== texture)
+ this.texture = texture;
},
/**
+ * Gets the blend func.
* @return {cc.BlendFunc}
*/
- getBlendFunc:function () {
+ getBlendFunc: function () {
return this._blendFunc;
},
/**
+ * Set the blend func.
* @param {Number} src
* @param {Number} dst
*/
- setBlendFunc:function (src, dst) {
- if (arguments.length == 1) {
+ setBlendFunc: function (src, dst) {
+ if (dst === undefined) {
this._blendFunc = src;
- } else if (arguments.length == 2) {
+ } else {
this._blendFunc.src = src;
this._blendFunc.dst = dst;
}
},
- getOpacity:function () {
- cc.Assert(false, "Opacity no supported");
+ /**
+ * Gets opacity.
+ * @warning cc.MotionStreak.getOpacity has not been supported.
+ * @returns {number}
+ */
+ getOpacity: function () {
+ cc.log("cc.MotionStreak.getOpacity has not been supported.");
return 0;
},
- setOpacity:function (opacity) {
- cc.Assert(false, "Set opacity no supported");
+ /**
+ * Set opacity.
+ * @warning cc.MotionStreak.setOpacity has not been supported.
+ * @param opacity
+ */
+ setOpacity: function (opacity) {
+ cc.log("cc.MotionStreak.setOpacity has not been supported.");
},
- setOpacityModifyRGB:function (value) {
+ /**
+ * set opacity modify RGB.
+ * @warning cc.MotionStreak.setOpacityModifyRGB has not been supported.
+ * @param value
+ */
+ setOpacityModifyRGB: function (value) {
},
- isOpacityModifyRGB:function () {
+ /**
+ * Checking OpacityModifyRGB.
+ * @returns {boolean}
+ */
+ isOpacityModifyRGB: function () {
return false;
},
- onExit:function(){
- cc.Node.prototype.onExit.call(this);
- if(this._verticesBuffer)
- cc.renderContext.deleteBuffer(this._verticesBuffer);
- if(this._texCoordsBuffer)
- cc.renderContext.deleteBuffer(this._texCoordsBuffer);
- if(this._colorPointerBuffer)
- cc.renderContext.deleteBuffer(this._colorPointerBuffer);
- },
-
- isFastMode:function () {
- return this._fastMode;
+ /**
+ * Checking fast mode.
+ * @returns {boolean}
+ */
+ isFastMode: function () {
+ return this.fastMode;
},
/**
* set fast mode
* @param {Boolean} fastMode
*/
- setFastMode:function (fastMode) {
- this._fastMode = fastMode;
+ setFastMode: function (fastMode) {
+ this.fastMode = fastMode;
},
- isStartingPositionInitialized:function () {
- return this._startingPositionInitialized;
+ /**
+ * Checking starting position initialized.
+ * @returns {boolean}
+ */
+ isStartingPositionInitialized: function () {
+ return this.startingPositionInitialized;
},
- setStartingPositionInitialized:function (startingPositionInitialized) {
- this._startingPositionInitialized = startingPositionInitialized;
+ /**
+ * Set Starting Position Initialized.
+ * @param {Boolean} startingPositionInitialized
+ */
+ setStartingPositionInitialized: function (startingPositionInitialized) {
+ this.startingPositionInitialized = startingPositionInitialized;
+ },
+
+ /**
+ * Get stroke.
+ * @returns {Number} stroke
+ */
+ getStroke: function () {
+ return this._stroke;
+ },
+
+ /**
+ * Set stroke.
+ * @param {Number} stroke
+ */
+ setStroke: function (stroke) {
+ this._stroke = stroke;
},
/**
@@ -192,25 +247,28 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
* @param {string|cc.Texture2D} texture texture filename or texture
* @return {Boolean}
*/
- initWithFade:function (fade, minSeg, stroke, color, texture) {
- cc.Assert(texture != null, "Invalid filename or texture");
+ initWithFade: function (fade, minSeg, stroke, color, texture) {
+ if (!texture)
+ throw new Error("cc.MotionStreak.initWithFade(): Invalid filename or texture");
- if (typeof(texture) === "string")
- texture = cc.TextureCache.getInstance().addImage(texture);
+ if (cc.isString(texture))
+ texture = cc.textureCache.addImage(texture);
- cc.Node.prototype.setPosition.call(this, cc.PointZero());
- this.setAnchorPoint(cc.PointZero());
- this.ignoreAnchorPointForPosition(true);
- this._startingPositionInitialized = false;
+ cc.Node.prototype.setPosition.call(this, cc.p(0, 0));
+ this.anchorX = 0;
+ this.anchorY = 0;
+ this.ignoreAnchor = true;
+ this.startingPositionInitialized = false;
- this._fastMode = true;
- this._minSeg = (minSeg == -1.0) ? (stroke / 5.0) : minSeg;
+ this.fastMode = true;
+ this._minSeg = (minSeg === -1.0) ? (stroke / 5.0) : minSeg;
this._minSeg *= this._minSeg;
this._stroke = stroke;
this._fadeDelta = 1.0 / fade;
var locMaxPoints = (0 | (fade * 60)) + 2;
+ this._maxPoints = locMaxPoints;
this._nuPoints = 0;
this._pointState = new Float32Array(locMaxPoints);
this._pointVertexes = new Float32Array(locMaxPoints * 2);
@@ -218,9 +276,6 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
this._vertices = new Float32Array(locMaxPoints * 4);
this._texCoords = new Float32Array(locMaxPoints * 4);
this._colorPointer = new Uint8Array(locMaxPoints * 8);
- this._maxPoints = locMaxPoints;
-
- var gl = cc.renderContext;
this._verticesBuffer = gl.createBuffer();
this._texCoordsBuffer = gl.createBuffer();
@@ -230,11 +285,8 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
this._blendFunc.src = gl.SRC_ALPHA;
this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
- // shader program
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
-
- this.setTexture(texture);
- this.setColor(color);
+ this.texture = texture;
+ this.color = color;
this.scheduleUpdate();
//bind buffer
@@ -250,83 +302,97 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
/**
* color used for the tint
- * @param {cc.Color3B} colors
+ * @param {cc.Color} color
*/
- tintWithColor:function (colors) {
- this.setColor(colors);
+ tintWithColor: function (color) {
+ this.color = color;
// Fast assignation
var locColorPointer = this._colorPointer;
for (var i = 0, len = this._nuPoints * 2; i < len; i++) {
- locColorPointer[i * 4] = colors.r;
- locColorPointer[i * 4 + 1] = colors.g;
- locColorPointer[i * 4 + 2] = colors.b;
+ locColorPointer[i * 4] = color.r;
+ locColorPointer[i * 4 + 1] = color.g;
+ locColorPointer[i * 4 + 2] = color.b;
}
},
/**
* Remove all living segments of the ribbon
*/
- reset:function () {
+ reset: function () {
this._nuPoints = 0;
},
/**
- * @override
- * @param {cc.Point} position
+ * Set the position.
+ *
+ * @param {cc.Point|Number} position
+ * @param {Number} [yValue=undefined] If not exists, the first parameter must be cc.Point.
*/
- setPosition:function (position) {
- this._startingPositionInitialized = true;
- this._positionR = cc.p(position.x,position.y);
+ setPosition: function (position, yValue) {
+ this.startingPositionInitialized = true;
+ if (yValue === undefined) {
+ this._positionR.x = position.x;
+ this._positionR.y = position.y;
+ } else {
+ this._positionR.x = position;
+ this._positionR.y = yValue;
+ }
},
/**
- * @override
- * @param {WebGLRenderingContext} ctx
+ * Gets the position.x
+ * @return {Number}
*/
- draw:function (ctx) {
- if (this._nuPoints <= 1)
- return;
-
- if(this._texture && this._texture.isLoaded()){
- ctx = ctx || cc.renderContext;
- cc.NODE_DRAW_SETUP(this);
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX);
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
-
- cc.glBindTexture2D(this._texture);
-
- //position
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this._verticesBuffer);
- ctx.bufferData(ctx.ARRAY_BUFFER, this._vertices, ctx.DYNAMIC_DRAW);
- ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, ctx.FLOAT, false, 0, 0);
+ getPositionX: function () {
+ return this._positionR.x;
+ },
- //texcoords
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this._texCoordsBuffer);
- ctx.bufferData(ctx.ARRAY_BUFFER, this._texCoords, ctx.DYNAMIC_DRAW);
- ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, ctx.FLOAT, false, 0, 0);
+ /**
+ * Set the position.x
+ * @param {Number} x
+ */
+ setPositionX: function (x) {
+ this._positionR.x = x;
+ if (!this.startingPositionInitialized)
+ this.startingPositionInitialized = true;
+ },
- //colors
- ctx.bindBuffer(ctx.ARRAY_BUFFER, this._colorPointerBuffer);
- ctx.bufferData(ctx.ARRAY_BUFFER, this._colorPointer, ctx.DYNAMIC_DRAW);
- ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, ctx.UNSIGNED_BYTE, true, 0, 0);
+ /**
+ * Gets the position.y
+ * @return {Number}
+ */
+ getPositionY: function () {
+ return this._positionR.y;
+ },
- ctx.drawArrays(ctx.TRIANGLE_STRIP, 0, this._nuPoints * 2);
- cc.g_NumberOfDraws ++;
- }
+ /**
+ * Set the position.y
+ * @param {Number} y
+ */
+ setPositionY: function (y) {
+ this._positionR.y = y;
+ if (!this.startingPositionInitialized)
+ this.startingPositionInitialized = true;
},
/**
- * @override
+ * schedules the "update" method.
+ * It will use the order number 0. This method will be called every frame.
+ * Scheduled methods with a lower order value will be called before the ones that have a higher order value.
+ * Only one "update" method could be scheduled per node.
* @param {Number} delta
*/
- update:function (delta) {
- if (!this._startingPositionInitialized)
+ update: function (delta) {
+ if (!this.startingPositionInitialized)
return;
+ //TODO update the color (need move to render cmd)
+ this._renderCmd._updateDisplayColor();
+
delta *= this._fadeDelta;
- var newIdx, newIdx2, i, i2;
+ var i, newIdx, newIdx2, i2;
var mov = 0;
// Update current points
@@ -381,8 +447,8 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
appendNewPoint = false;
else if (locNuPoints > 0) {
var a1 = cc.pDistanceSQ(cc.p(locPointVertexes[(locNuPoints - 1) * 2], locPointVertexes[(locNuPoints - 1) * 2 + 1]),
- this._positionR) < this._minSeg;
- var a2 = (locNuPoints == 1) ? false : (cc.pDistanceSQ(
+ this._positionR) < this._minSeg;
+ var a2 = (locNuPoints === 1) ? false : (cc.pDistanceSQ(
cc.p(locPointVertexes[(locNuPoints - 2) * 2], locPointVertexes[(locNuPoints - 2) * 2 + 1]), this._positionR) < (this._minSeg * 2.0));
if (a1 || a2)
appendNewPoint = false;
@@ -396,7 +462,7 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
// Color assignment
var offset = locNuPoints * 8;
- var locDisplayedColor = this._displayedColor;
+ var locDisplayedColor = this.getDisplayedColor();
locColorPointer[offset] = locDisplayedColor.r;
locColorPointer[offset + 1] = locDisplayedColor.g;
locColorPointer[offset + 2] = locDisplayedColor.b;
@@ -410,7 +476,7 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
locColorPointer[offset + 7] = 255;
// Generate polygon
- if (locNuPoints > 0 && this._fastMode) {
+ if (locNuPoints > 0 && this.fastMode) {
if (locNuPoints > 1)
cc.vertexLineToPolygon(locPointVertexes, this._stroke, this._vertices, locNuPoints, 1);
else
@@ -419,11 +485,11 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
locNuPoints++;
}
- if (!this._fastMode)
+ if (!this.fastMode)
cc.vertexLineToPolygon(locPointVertexes, this._stroke, this._vertices, 0, locNuPoints);
// Updated Tex Coords only if they are different than previous step
- if (locNuPoints && this._previousNuPoints != locNuPoints) {
+ if (locNuPoints && this._previousNuPoints !== locNuPoints) {
var texDelta = 1.0 / locNuPoints;
var locTexCoords = this._texCoords;
for (i = 0; i < locNuPoints; i++) {
@@ -438,21 +504,30 @@ cc.MotionStreak = cc.NodeRGBA.extend(/** @lends cc.MotionStreak# */{
}
this._nuPoints = locNuPoints;
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new cc.MotionStreak.WebGLRenderCmd(this);
+ else
+ return null; //MotionStreak doesn't support Canvas mode
}
});
/**
- * creates and initializes a motion streak with fade in seconds, minimum segments, stroke's width, color, texture filename or texture
+ * Please use new cc.MotionStreak instead.
+ * Creates and initializes a motion streak with fade in seconds, minimum segments, stroke's width, color, texture filename or texture
+ * @deprecated since v3.0 please use new cc.MotionStreak instead.
* @param {Number} fade time to fade
* @param {Number} minSeg minimum segment size
* @param {Number} stroke stroke's width
* @param {Number} color
* @param {string|cc.Texture2D} texture texture filename or texture
* @return {cc.MotionStreak}
+ * @example
+ * //example
+ * new cc.MotionStreak(2, 3, 32, cc.color.GREEN, s_streak);
*/
cc.MotionStreak.create = function (fade, minSeg, stroke, color, texture) {
- var ret = new cc.MotionStreak();
- if (ret && ret.initWithFade(fade, minSeg, stroke, color, texture))
- return ret;
- return null;
+ return new cc.MotionStreak(fade, minSeg, stroke, color, texture);
};
diff --git a/cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js b/cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js
new file mode 100644
index 0000000000..a7d793a336
--- /dev/null
+++ b/cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js
@@ -0,0 +1,79 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc.MotionStreak.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
+};
+
+cc.MotionStreak.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+cc.MotionStreak.WebGLRenderCmd.prototype.constructor = cc.Sprite.WebGLRenderCmd;
+
+cc.MotionStreak.WebGLRenderCmd.prototype.rendering = function (ctx) {
+ var node = this._node;
+ if (node._nuPoints <= 1)
+ return;
+
+ if (node.texture && node.texture.isLoaded()) {
+ ctx = ctx || cc._renderContext;
+
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ this._glProgramState.apply(this._matrix);
+ cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
+
+ cc.glBindTexture2D(node.texture);
+
+ ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+ ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+
+ //position
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, node._verticesBuffer);
+ ctx.bufferData(ctx.ARRAY_BUFFER, node._vertices, ctx.DYNAMIC_DRAW);
+ ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, ctx.FLOAT, false, 0, 0);
+
+ //texcoords
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, node._texCoordsBuffer);
+ ctx.bufferData(ctx.ARRAY_BUFFER, node._texCoords, ctx.DYNAMIC_DRAW);
+ ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, ctx.FLOAT, false, 0, 0);
+
+ //colors
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, node._colorPointerBuffer);
+ ctx.bufferData(ctx.ARRAY_BUFFER, node._colorPointer, ctx.DYNAMIC_DRAW);
+ ctx.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, ctx.UNSIGNED_BYTE, true, 0, 0);
+
+ ctx.drawArrays(ctx.TRIANGLE_STRIP, 0, node._nuPoints * 2);
+ cc.g_NumberOfDraws++;
+ }
+};
diff --git a/cocos2d/node-grid/CCNodeGrid.js b/cocos2d/node-grid/CCNodeGrid.js
new file mode 100644
index 0000000000..684b3886b8
--- /dev/null
+++ b/cocos2d/node-grid/CCNodeGrid.js
@@ -0,0 +1,110 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * NodeGrid class is a class serves as a decorator of cc.Node,
+ * Grid node can run grid actions over all its children (WebGL only)
+ *
+ * @type {Class}
+ *
+ * @property {cc.GridBase} grid - Grid object that is used when applying effects
+ * @property {cc.Node} target - <@writeonly>Target
+ */
+cc.NodeGrid = cc.Node.extend(/** @lends cc.NodeGrid# */{
+ grid: null,
+ _target: null,
+ _gridRect:null,
+
+ ctor: function (rect) {
+ cc.Node.prototype.ctor.call(this);
+ if(rect === undefined) rect = cc.rect();
+ this._gridRect = rect;
+ },
+ /**
+ * Gets the grid object.
+ * @returns {cc.GridBase}
+ */
+ getGrid: function () {
+ return this.grid;
+ },
+
+ /**
+ * Set the grid object.
+ * @param {cc.GridBase} grid
+ */
+ setGrid: function (grid) {
+ this.grid = grid;
+ },
+
+ /**
+ * @brief Set the effect grid rect.
+ * @param {cc.Rect} rect
+ */
+ setGridRect: function (rect) {
+ this._gridRect = rect;
+ },
+ /**
+ * @brief Get the effect grid rect.
+ * @return {cc.Rect} rect.
+ */
+ getGridRect: function () {
+ return this._gridRect;
+ },
+
+ /**
+ * Set the target
+ * @param {cc.Node} target
+ */
+ setTarget: function (target) {
+ this._target = target;
+ },
+
+ _createRenderCmd: function(){
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new cc.NodeGrid.WebGLRenderCmd(this);
+ else
+ return new cc.Node.CanvasRenderCmd(this); // cc.NodeGrid doesn't support Canvas mode.
+ }
+});
+
+var _p = cc.NodeGrid.prototype;
+// Extended property
+/** @expose */
+_p.grid;
+/** @expose */
+_p.target;
+cc.defineGetterSetter(_p, "target", null, _p.setTarget);
+
+
+/**
+ * Creates a NodeGrid.
+ * Implementation cc.NodeGrid
+ * @deprecated since v3.0 please new cc.NodeGrid instead.
+ * @return {cc.NodeGrid}
+ */
+cc.NodeGrid.create = function () {
+ return new cc.NodeGrid();
+};
diff --git a/cocos2d/node-grid/CCNodeGridWebGLRenderCmd.js b/cocos2d/node-grid/CCNodeGridWebGLRenderCmd.js
new file mode 100644
index 0000000000..9288a0fd69
--- /dev/null
+++ b/cocos2d/node-grid/CCNodeGridWebGLRenderCmd.js
@@ -0,0 +1,98 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.NodeGrid.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = false;
+ this._gridBeginCommand = new cc.CustomRenderCmd(this, this.onGridBeginDraw);
+ this._gridEndCommand = new cc.CustomRenderCmd(this, this.onGridEndDraw);
+ };
+
+ var proto = cc.NodeGrid.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.NodeGrid.WebGLRenderCmd;
+
+ proto.visit = function (parentCmd) {
+ var node = this._node;
+ // quick return if not visible
+ if (!node._visible)
+ return;
+
+ parentCmd = parentCmd || this.getParentRenderCmd();
+ if (parentCmd)
+ this._curLevel = parentCmd._curLevel + 1;
+
+ var currentStack = cc.current_stack;
+ currentStack.stack.push(currentStack.top);
+ this._syncStatus(parentCmd);
+ currentStack.top = this._stackMatrix;
+
+ /*var beforeProjectionType = cc.director.PROJECTION_DEFAULT;
+ if (locGrid && locGrid._active) {
+ //var backMatrix = new cc.kmMat4();
+ //cc.kmMat4Assign(backMatrix, this._stackMatrix);
+
+ beforeProjectionType = cc.director.getProjection();
+ //locGrid.set2DProjection();
+
+ //reset this._stackMatrix to current_stack.top
+ //cc.kmMat4Assign(currentStack.top, backMatrix);
+ }*/
+ cc.renderer.pushRenderCommand(this._gridBeginCommand);
+
+ if (node._target)
+ node._target.visit();
+
+ var locChildren = node._children;
+ if (locChildren && locChildren.length > 0) {
+ var childLen = locChildren.length;
+ node.sortAllChildren();
+ // draw children
+ for (var i = 0; i < childLen; i++) {
+ var child = locChildren[i];
+ child && child.visit();
+ }
+ }
+
+ //if (locGrid && locGrid._active) {
+ //cc.director.setProjection(beforeProjectionType);
+ //}
+ cc.renderer.pushRenderCommand(this._gridEndCommand);
+
+ this._dirtyFlag = 0;
+ currentStack.top = currentStack.stack.pop();
+ };
+
+ proto.onGridBeginDraw = function () {
+ var locGrid = this._node.grid;
+ if (locGrid && locGrid._active)
+ locGrid.beforeDraw();
+ };
+
+ proto.onGridEndDraw = function () {
+ var locGrid = this._node.grid;
+ if (locGrid && locGrid._active)
+ locGrid.afterDraw(this._node);
+ };
+})();
diff --git a/cocos2d/tileMap_parallax_nodes/CCParallaxNode.js b/cocos2d/parallax/CCParallaxNode.js
similarity index 65%
rename from cocos2d/tileMap_parallax_nodes/CCParallaxNode.js
rename to cocos2d/parallax/CCParallaxNode.js
index 9d512e30b5..7efc9cf30e 100644
--- a/cocos2d/tileMap_parallax_nodes/CCParallaxNode.js
+++ b/cocos2d/parallax/CCParallaxNode.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -25,6 +25,8 @@
****************************************************************************/
/**
+ * Parallax Object.
+ * Parallax required attributes are stored.
* @class
* @extends cc.Class
*/
@@ -33,14 +35,20 @@ cc.PointObject = cc.Class.extend(/** @lends cc.PointObject# */{
_offset:null,
_child:null,
+ ctor: function(ratio, offset){
+ this.initWithCCPoint(ratio, offset);
+ },
+
/**
- * @return {cc.Point}
+ * Gets the ratio.
+ * @return {cc.Point} Not point, this is ratio.
*/
getRatio:function () {
return this._ratio;
},
/**
+ * Set the ratio.
* @param {cc.Point} value
*/
setRatio:function (value) {
@@ -48,6 +56,7 @@ cc.PointObject = cc.Class.extend(/** @lends cc.PointObject# */{
},
/**
+ * Gets the offset.
* @return {cc.Point}
*/
getOffset:function () {
@@ -55,6 +64,7 @@ cc.PointObject = cc.Class.extend(/** @lends cc.PointObject# */{
},
/**
+ * Set the offset.
* @param {cc.Point} value
*/
setOffset:function (value) {
@@ -62,6 +72,7 @@ cc.PointObject = cc.Class.extend(/** @lends cc.PointObject# */{
},
/**
+ * Gets the child.
* @return {cc.Node}
*/
getChild:function () {
@@ -69,6 +80,7 @@ cc.PointObject = cc.Class.extend(/** @lends cc.PointObject# */{
},
/**
+ * Set the child.
* @param {cc.Node} value
*/
setChild:function (value) {
@@ -76,7 +88,8 @@ cc.PointObject = cc.Class.extend(/** @lends cc.PointObject# */{
},
/**
- * @param {cc.Point} ratio
+ * initializes cc.PointObject
+ * @param {cc.Point} ratio Not point, this is a ratio.
* @param {cc.Point} offset
* @return {Boolean}
*/
@@ -89,14 +102,14 @@ cc.PointObject = cc.Class.extend(/** @lends cc.PointObject# */{
});
/**
+ * Create a object to stored parallax data.
* @param {cc.Point} ratio
* @param {cc.Point} offset
* @return {cc.PointObject}
+ * @deprecated since v3.0 please use new cc.PointObject() instead.
*/
cc.PointObject.create = function (ratio, offset) {
- var ret = new cc.PointObject();
- ret.initWithCCPoint(ratio, offset);
- return ret;
+ return new cc.PointObject(ratio, offset);
};
/**
@@ -104,32 +117,37 @@ cc.PointObject.create = function (ratio, offset) {
* The children will be moved faster / slower than the parent according the the parallax ratio.
* @class
* @extends cc.Node
+ *
+ * @property {Array} parallaxArray - Parallax nodes array
*/
cc.ParallaxNode = cc.Node.extend(/** @lends cc.ParallaxNode# */{
+ parallaxArray:null,
+
_lastPosition:null,
- _parallaxArray:null,
+ _className:"ParallaxNode",
/**
+ * Gets the parallax array.
* @return {Array}
*/
-
getParallaxArray:function () {
- return this._parallaxArray;
+ return this.parallaxArray;
},
/**
+ * Set parallax array.
* @param {Array} value
*/
setParallaxArray:function (value) {
- this._parallaxArray = value;
+ this.parallaxArray = value;
},
/**
- * Constructor
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
*/
ctor:function () {
cc.Node.prototype.ctor.call(this);
- this._parallaxArray = [];
+ this.parallaxArray = [];
this._lastPosition = cc.p(-100, -100);
},
@@ -142,24 +160,22 @@ cc.ParallaxNode = cc.Node.extend(/** @lends cc.ParallaxNode# */{
* @param {cc.Point} offset
* @example
* //example
- * voidNode.addChild(background, -1, cc.p(0.4, 0.5), cc.PointZero());
+ * voidNode.addChild(background, -1, cc.p(0.4, 0.5), cc.p(0,0));
*/
addChild:function (child, z, ratio, offset) {
if (arguments.length === 3) {
- cc.Assert(0, "ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead");
+ cc.log("ParallaxNode: use addChild(child, z, ratio, offset) instead");
return;
}
- cc.Assert(child != null, "Argument must be non-nil");
- var obj = cc.PointObject.create(ratio, offset);
+ if(!child)
+ throw new Error("cc.ParallaxNode.addChild(): child should be non-null");
+ var obj = new cc.PointObject(ratio, offset);
obj.setChild(child);
- this._parallaxArray.push(obj);
+ this.parallaxArray.push(obj);
- var pos = cc.p(this._position.x, this._position.y);
- pos.x = pos.x * ratio.x + offset.x;
- pos.y = pos.y * ratio.y + offset.y;
- child.setPosition(pos);
+ child.setPosition(this._position.x * ratio.x + offset.x, this._position.y * ratio.y + offset.y);
- cc.Node.prototype.addChild.call(this, child, z, child.getTag());
+ cc.Node.prototype.addChild.call(this, child, z, child.tag);
},
/**
@@ -171,10 +187,10 @@ cc.ParallaxNode = cc.Node.extend(/** @lends cc.ParallaxNode# */{
* voidNode.removeChild(background,true);
*/
removeChild:function (child, cleanup) {
- var locParallaxArray = this._parallaxArray;
+ var locParallaxArray = this.parallaxArray;
for (var i = 0; i < locParallaxArray.length; i++) {
var point = locParallaxArray[i];
- if (point.getChild() == child) {
+ if (point.getChild() === child) {
locParallaxArray.splice(i, 1);
break;
}
@@ -184,47 +200,52 @@ cc.ParallaxNode = cc.Node.extend(/** @lends cc.ParallaxNode# */{
/**
* Remove all children with cleanup
- * @param {Boolean} cleanup
+ * @param {Boolean} [cleanup=true]
*/
removeAllChildren:function (cleanup) {
- this._parallaxArray = [];
+ this.parallaxArray.length = 0;
cc.Node.prototype.removeAllChildren.call(this, cleanup);
},
- /**
- * Visit
- */
- visit:function () {
+ _updateParallaxPosition: function(){
var pos = this._absolutePosition();
if (!cc.pointEqualToPoint(pos, this._lastPosition)) {
- var locParallaxArray = this._parallaxArray;
+ var locParallaxArray = this.parallaxArray;
for (var i = 0, len = locParallaxArray.length; i < len; i++) {
var point = locParallaxArray[i];
- var x = -pos.x + pos.x * point.getRatio().x + point.getOffset().x;
- var y = -pos.y + pos.y * point.getRatio().y + point.getOffset().y;
- point.getChild().setPosition(x, y);
+ var child = point.getChild();
+ child.setPosition(-pos.x + pos.x * point.getRatio().x + point.getOffset().x,
+ -pos.y + pos.y * point.getRatio().y + point.getOffset().y);
}
this._lastPosition = pos;
}
- cc.Node.prototype.visit.call(this);
},
_absolutePosition:function () {
var ret = this._position;
var cn = this;
- while (cn.getParent() != null) {
- cn = cn.getParent();
+ while (cn.parent !== null) {
+ cn = cn.parent;
ret = cc.pAdd(ret, cn.getPosition());
}
return ret;
+ },
+
+ _createRenderCmd: function(){
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.ParallaxNode.CanvasRenderCmd(this);
+ else
+ return new cc.ParallaxNode.WebGLRenderCmd(this);
}
});
/**
+ * Create new parallax node.
+ * @deprecated since v3.0 please use new cc.ParallaxNode() instead.
* @return {cc.ParallaxNode}
* @example
* //example
- * var voidNode = cc.ParallaxNode.create();
+ * var voidNode = new cc.ParallaxNode();
*/
cc.ParallaxNode.create = function () {
return new cc.ParallaxNode();
diff --git a/cocos2d/parallax/CCParallaxNodeRenderCmd.js b/cocos2d/parallax/CCParallaxNodeRenderCmd.js
new file mode 100644
index 0000000000..2f5031c844
--- /dev/null
+++ b/cocos2d/parallax/CCParallaxNodeRenderCmd.js
@@ -0,0 +1,69 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//TODO find a way to simple these code.
+
+(function () {
+ cc.ParallaxNode.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = false;
+ };
+
+ var proto = cc.ParallaxNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.ParallaxNode.CanvasRenderCmd;
+
+ proto.updateStatus = function () {
+ this._node._updateParallaxPosition();
+ this.originUpdateStatus();
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ this._node._updateParallaxPosition();
+ this._originSyncStatus(parentCmd);
+ };
+})();
+
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+ if (cc._renderType !== cc.game.RENDER_TYPE_WEBGL)
+ return;
+
+ cc.ParallaxNode.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = false;
+ };
+
+ var proto = cc.ParallaxNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.ParallaxNode.WebGLRenderCmd;
+
+ proto.updateStatus = function () {
+ this._node._updateParallaxPosition();
+ this.originUpdateStatus();
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ this._node._updateParallaxPosition();
+ this._originSyncStatus(parentCmd);
+ };
+});
+
diff --git a/cocos2d/support/CCPNGReader.js b/cocos2d/particle/CCPNGReader.js
similarity index 98%
rename from cocos2d/support/CCPNGReader.js
rename to cocos2d/particle/CCPNGReader.js
index 99fb63c2cb..20667a2cbc 100644
--- a/cocos2d/support/CCPNGReader.js
+++ b/cocos2d/particle/CCPNGReader.js
@@ -1,7 +1,8 @@
/****************************************************************************
Copyright (c) 2011 Devon Govett
- Copyright (c) 2010-2012 cocos2d-x.org
-
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -25,6 +26,10 @@
THE SOFTWARE.
****************************************************************************/
+/**
+ * A png file reader
+ * @name cc.tiffReader
+ */
cc.PNGReader = cc.Class.extend({
ctor:function(data){
var chunkSize, colors, delayDen, delayNum, frame, i, index, key, section, ccshort, text, _i, _j, _ref;
diff --git a/cocos2d/particle_nodes/CCParticleBatchNode.js b/cocos2d/particle/CCParticleBatchNode.js
similarity index 54%
rename from cocos2d/particle_nodes/CCParticleBatchNode.js
rename to cocos2d/particle/CCParticleBatchNode.js
index 947e7ca78c..53c381fc30 100644
--- a/cocos2d/particle_nodes/CCParticleBatchNode.js
+++ b/cocos2d/particle/CCParticleBatchNode.js
@@ -1,8 +1,8 @@
/**
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
* Copyright (C) 2009 Matt Oswald
- * Copyright (c) 2009-2010 Ricardo Quesada
- * Copyright (c) 2011 Zynga Inc.
* Copyright (c) 2011 Marco Tillemans
*
* http://www.cocos2d-x.org
@@ -54,16 +54,58 @@ cc.PARTICLE_DEFAULT_CAPACITY = 500;
*
* @class
* @extends cc.ParticleSystem
+ * @param {String|cc.Texture2D} fileImage
+ * @param {Number} capacity
+ *
+ * @property {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture - The used texture
+ * @property {cc.TextureAtlas} textureAtlas - The texture atlas used for drawing the quads
+ *
+ * @example
+ * 1.
+ * //Create a cc.ParticleBatchNode with image path and capacity
+ * var particleBatchNode = new cc.ParticleBatchNode("res/grossini_dance.png",30);
+ *
+ * 2.
+ * //Create a cc.ParticleBatchNode with a texture and capacity
+ * var texture = cc.TextureCache.getInstance().addImage("res/grossini_dance.png");
+ * var particleBatchNode = new cc.ParticleBatchNode(texture, 30);
*/
cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
- TextureProtocol:true,
+ textureAtlas: null,
//the blend function used for drawing the quads
- _blendFunc:null,
- _textureAtlas:null,
+ _blendFunc: null,
+ _className: "ParticleBatchNode",
- ctor:function () {
+ /**
+ * initializes the particle system with the name of a file on disk (for a list of supported formats look at the cc.Texture2D class), a capacity of particles
+ * Constructor of cc.ParticleBatchNode
+ * @param {String|cc.Texture2D} fileImage
+ * @param {Number} capacity
+ * @example
+ * 1.
+ * //Create a cc.ParticleBatchNode with image path and capacity
+ * var particleBatchNode = new cc.ParticleBatchNode("res/grossini_dance.png",30);
+ *
+ * 2.
+ * //Create a cc.ParticleBatchNode with a texture and capacity
+ * var texture = cc.TextureCache.getInstance().addImage("res/grossini_dance.png");
+ * var particleBatchNode = new cc.ParticleBatchNode(texture, 30);
+ */
+ ctor: function (fileImage, capacity) {
cc.Node.prototype.ctor.call(this);
- this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST};
+ this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
+ if (cc.isString(fileImage)) {
+ this.init(fileImage, capacity);
+ } else if (fileImage instanceof cc.Texture2D) {
+ this.initWithTexture(fileImage, capacity);
+ }
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.ParticleBatchNode.CanvasRenderCmd(this);
+ else
+ return new cc.ParticleBatchNode.WebGLRenderCmd(this);
},
/**
@@ -72,15 +114,14 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
* @param {Number} capacity
* @return {Boolean}
*/
- initWithTexture:function (texture, capacity) {
- this._textureAtlas = new cc.TextureAtlas();
- this._textureAtlas.initWithTexture(texture, capacity);
+ initWithTexture: function (texture, capacity) {
+ this.textureAtlas = new cc.TextureAtlas();
+ this.textureAtlas.initWithTexture(texture, capacity);
// no lazy alloc in this node
- this._children = [];
+ this._children.length = 0;
- if (cc.renderContextType === cc.WEBGL)
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
+ this._renderCmd._initWithTexture();
return true;
},
@@ -90,8 +131,8 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
* @param {Number} capacity
* @return {Boolean}
*/
- initWithFile:function (fileImage, capacity) {
- var tex = cc.TextureCache.getInstance().addImage(fileImage);
+ initWithFile: function (fileImage, capacity) {
+ var tex = cc.textureCache.addImage(fileImage);
return this.initWithTexture(tex, capacity);
},
@@ -101,30 +142,52 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
* @param {Number} capacity
* @return {Boolean}
*/
- init:function (fileImage, capacity) {
- var tex = cc.TextureCache.getInstance().addImage(fileImage);
+ init: function (fileImage, capacity) {
+ var tex = cc.textureCache.addImage(fileImage);
return this.initWithTexture(tex, capacity);
},
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ cmd.visit(parentCmd);
+ cc.renderer.pushRenderCommand(cmd);
+ cmd._dirtyFlag = 0;
+ },
+
/**
* Add a child into the cc.ParticleBatchNode
* @param {cc.ParticleSystem} child
* @param {Number} zOrder
* @param {Number} tag
*/
- addChild:function (child, zOrder, tag) {
- cc.Assert(child != null, "Argument must be non-NULL");
- cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.ParticleSystem as children");
- zOrder = (zOrder == null) ? child.getZOrder() : zOrder;
- tag = (tag == null) ? child.getTag() : tag;
+ addChild: function (child, zOrder, tag) {
+ if (!child)
+ throw new Error("cc.ParticleBatchNode.addChild() : child should be non-null");
+ if (!(child instanceof cc.ParticleSystem))
+ throw new Error("cc.ParticleBatchNode.addChild() : only supports cc.ParticleSystem as children");
+ zOrder = (zOrder == null) ? child.zIndex : zOrder;
+ tag = (tag == null) ? child.tag : tag;
+
+ if (child.getTexture() !== this.textureAtlas.texture)
+ throw new Error("cc.ParticleSystem.addChild() : the child is not using the same texture id");
- cc.Assert(child.getTexture() == this._textureAtlas.getTexture(), "cc.ParticleSystem is not using the same texture id");
// If this is the 1st children, then copy blending function
+ var childBlendFunc = child.getBlendFunc();
if (this._children.length === 0)
- this.setBlendFunc(child.getBlendFunc());
-
- cc.Assert(this._blendFunc.src == child.getBlendFunc().src && this._blendFunc.dst == child.getBlendFunc().dst,
- "Can't add a ParticleSystem that uses a different blending function");
+ this.setBlendFunc(childBlendFunc);
+ else {
+ if ((childBlendFunc.src !== this._blendFunc.src) || (childBlendFunc.dst !== this._blendFunc.dst)) {
+ cc.log("cc.ParticleSystem.addChild() : Can't add a ParticleSystem that uses a different blending function");
+ return;
+ }
+ }
//no lazy sorting, so don't call super addChild, call helper instead
var pos = this._addChildHelper(child, zOrder, tag);
@@ -132,7 +195,7 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
//get new atlasIndex
var atlasIndex = 0;
- if (pos != 0) {
+ if (pos !== 0) {
var p = this._children[pos - 1];
atlasIndex = p.getAtlasIndex() + p.getTotalParticles();
} else
@@ -149,10 +212,10 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
* @param {cc.ParticleSystem} pSystem
* @param {Number} index
*/
- insertChild:function (pSystem, index) {
+ insertChild: function (pSystem, index) {
var totalParticles = pSystem.getTotalParticles();
- var locTextureAtlas = this._textureAtlas;
- var totalQuads = locTextureAtlas.getTotalQuads();
+ var locTextureAtlas = this.textureAtlas;
+ var totalQuads = locTextureAtlas.totalQuads;
pSystem.setAtlasIndex(index);
if (totalQuads + totalParticles > locTextureAtlas.getCapacity()) {
this._increaseAtlasCapacityTo(totalQuads + totalParticles);
@@ -161,7 +224,7 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
}
// make room for quads, not necessary for last child
- if (pSystem.getAtlasIndex() + totalParticles != totalQuads)
+ if (pSystem.getAtlasIndex() + totalParticles !== totalQuads)
locTextureAtlas.moveQuadsFromIndex(index, index + totalParticles);
// increase totalParticles here for new particles, update method of particlesystem will fill the quads
@@ -173,22 +236,26 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
* @param {cc.ParticleSystem} child
* @param {Boolean} cleanup
*/
- removeChild:function (child, cleanup) {
+ removeChild: function (child, cleanup) {
// explicit nil handling
if (child == null)
return;
- cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.ParticleSystem as children");
- cc.Assert(this._children.indexOf(child) > -1, "cc.ParticleBatchNode doesn't contain the sprite. Can't remove it");
+ if (!(child instanceof cc.ParticleSystem))
+ throw new Error("cc.ParticleBatchNode.removeChild(): only supports cc.ParticleSystem as children");
+ if (this._children.indexOf(child) === -1) {
+ cc.log("cc.ParticleBatchNode.removeChild(): doesn't contain the sprite. Can't remove it");
+ return;
+ }
cc.Node.prototype.removeChild.call(this, child, cleanup);
- var locTextureAtlas = this._textureAtlas;
+ var locTextureAtlas = this.textureAtlas;
// remove child helper
locTextureAtlas.removeQuadsAtIndex(child.getAtlasIndex(), child.getTotalParticles());
// after memmove of data, empty the quads at the end of array
- locTextureAtlas.fillWithEmptyQuadsFromIndex(locTextureAtlas.getTotalQuads(), child.getTotalParticles());
+ locTextureAtlas.fillWithEmptyQuadsFromIndex(locTextureAtlas.totalQuads, child.getTotalParticles());
// paticle could be reused for self rendering
child.setBatchNode(null);
@@ -201,22 +268,24 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
* @param {cc.ParticleSystem} child
* @param {Number} zOrder
*/
- reorderChild:function (child, zOrder) {
- cc.Assert(child != null, "Child must be non-NULL");
- cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.QuadParticleSystems as children");
- cc.Assert( this._children.indexOf(child) === -1, "Child doesn't belong to batch" );
-
- if (zOrder == child.getZOrder())
+ reorderChild: function (child, zOrder) {
+ if (!child)
+ throw new Error("cc.ParticleBatchNode.reorderChild(): child should be non-null");
+ if (!(child instanceof cc.ParticleSystem))
+ throw new Error("cc.ParticleBatchNode.reorderChild(): only supports cc.QuadParticleSystems as children");
+ if (this._children.indexOf(child) === -1) {
+ cc.log("cc.ParticleBatchNode.reorderChild(): Child doesn't belong to batch");
return;
+ }
// no reordering if only 1 child
if (this._children.length > 1) {
var getIndexes = this._getCurrentIndex(child, zOrder);
- if (getIndexes.oldIndex != getIndexes.newIndex) {
+ if (getIndexes.oldIndex !== getIndexes.newIndex) {
// reorder m_pChildren.array
- cc.ArrayRemoveObjectAtIndex(this._children, getIndexes.oldIndex);
- this._children = cc.ArrayAppendObjectToIndex(this._children, child, getIndexes.newIndex);
+ this._children.splice(getIndexes.oldIndex, 1)
+ this._children.splice(getIndexes.newIndex, 0, child);
// save old altasIndex
var oldAtlasIndex = child.getAtlasIndex();
@@ -229,146 +298,99 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
var locChildren = this._children;
for (var i = 0; i < locChildren.length; i++) {
var pNode = locChildren[i];
- if (pNode == child) {
+ if (pNode === child) {
newAtlasIndex = child.getAtlasIndex();
break;
}
}
// reorder textureAtlas quads
- this._textureAtlas.moveQuadsFromIndex(oldAtlasIndex, child.getTotalParticles(), newAtlasIndex);
+ this.textureAtlas.moveQuadsFromIndex(oldAtlasIndex, child.getTotalParticles(), newAtlasIndex);
child.updateWithNoTime();
}
}
- child._setZOrder(zOrder);
+ child._setLocalZOrder(zOrder);
},
/**
* @param {Number} index
* @param {Boolean} doCleanup
*/
- removeChildAtIndex:function (index, doCleanup) {
+ removeChildAtIndex: function (index, doCleanup) {
this.removeChild(this._children[i], doCleanup);
},
/**
- * @param {Boolean} doCleanup
+ * @param {Boolean} [doCleanup=true]
*/
- removeAllChildren:function (doCleanup) {
+ removeAllChildren: function (doCleanup) {
var locChildren = this._children;
for (var i = 0; i < locChildren.length; i++) {
locChildren[i].setBatchNode(null);
}
cc.Node.prototype.removeAllChildren.call(this, doCleanup);
- this._textureAtlas.removeAllQuads();
+ this.textureAtlas.removeAllQuads();
},
/**
* disables a particle by inserting a 0'd quad into the texture atlas
* @param {Number} particleIndex
*/
- disableParticle:function (particleIndex) {
- var quad = ((this._textureAtlas.getQuads())[particleIndex]);
+ disableParticle: function (particleIndex) {
+ var quad = this.textureAtlas.quads[particleIndex];
quad.br.vertices.x = quad.br.vertices.y = quad.tr.vertices.x = quad.tr.vertices.y =
quad.tl.vertices.x = quad.tl.vertices.y = quad.bl.vertices.x = quad.bl.vertices.y = 0.0;
- this._textureAtlas._setDirty(true);
- },
-
- /**
- * @override
- * @param {CanvasContext} ctx
- */
- draw:function (ctx) {
- //cc.PROFILER_STOP("CCParticleBatchNode - draw");
- if (cc.renderContextType === cc.CANVAS)
- return;
-
- if (this._textureAtlas.getTotalQuads() == 0)
- return;
-
- cc.NODE_DRAW_SETUP(this);
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
- this._textureAtlas.drawQuads();
-
- //cc.PROFILER_STOP("CCParticleBatchNode - draw");
+ this.textureAtlas._setDirty(true);
},
/**
* returns the used texture
- * @return {cc.Texture2D|HTMLImageElement|HTMLCanvasElement}
+ * @return {cc.Texture2D}
*/
- getTexture:function () {
- return this._textureAtlas.getTexture();
+ getTexture: function () {
+ return this.textureAtlas.texture;
},
/**
* sets a new texture. it will be retained
- * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture
+ * @param {cc.Texture2D} texture
*/
- setTexture:function (texture) {
- this._textureAtlas.setTexture(texture);
+ setTexture: function (texture) {
+ this.textureAtlas.texture = texture;
// If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it
var locBlendFunc = this._blendFunc;
- if (texture && !texture.hasPremultipliedAlpha() && ( locBlendFunc.src == gl.BLEND_SRC && locBlendFunc.dst == gl.BLEND_DST )) {
- locBlendFunc.src = gl.SRC_ALPHA;
- locBlendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
+ if (texture && !texture.hasPremultipliedAlpha() && ( locBlendFunc.src === cc.BLEND_SRC && locBlendFunc.dst === cc.BLEND_DST )) {
+ locBlendFunc.src = cc.SRC_ALPHA;
+ locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
}
},
/**
* set the blending function used for the texture
- * @param {Number} src
+ * @param {Number|Object} src
* @param {Number} dst
*/
- setBlendFunc:function (src, dst) {
- if (arguments.length == 1)
- this._blendFunc = src;
- else
- this._blendFunc = {src:src, dst:dst};
+ setBlendFunc: function (src, dst) {
+ if (dst === undefined) {
+ this._blendFunc.src = src.src;
+ this._blendFunc.dst = src.dst;
+ } else {
+ this._blendFunc.src = src;
+ this._blendFunc.src = dst;
+ }
},
/**
* returns the blending function used for the texture
* @return {cc.BlendFunc}
*/
- getBlendFunc:function () {
- return this._blendFunc;
+ getBlendFunc: function () {
+ return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
},
- // override visit.
- // Don't call visit on it's children
- visit:function (ctx) {
- if (cc.renderContextType === cc.CANVAS)
- return;
-
- // CAREFUL:
- // This visit is almost identical to cc.Node#visit
- // with the exception that it doesn't call visit on it's children
- //
- // The alternative is to have a void cc.Sprite#visit, but
- // although this is less mantainable, is faster
- //
- if (!this._visible)
- return;
-
- cc.kmGLPushMatrix();
- if (this._grid && this._grid.isActive()) {
- this._grid.beforeDraw();
- this.transformAncestors();
- }
-
- this.transform(ctx);
- this.draw(ctx);
-
- if (this._grid && this._grid.isActive())
- this._grid.afterDraw(this);
-
- cc.kmGLPopMatrix();
- },
-
- _updateAllAtlasIndexes:function () {
+ _updateAllAtlasIndexes: function () {
var index = 0;
var locChildren = this._children;
for (var i = 0; i < locChildren.length; i++) {
@@ -378,28 +400,27 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
}
},
- _increaseAtlasCapacityTo:function (quantity) {
- cc.log("cocos2d: cc.ParticleBatchNode: resizing TextureAtlas capacity from [" + this._textureAtlas.getCapacity()
+ _increaseAtlasCapacityTo: function (quantity) {
+ cc.log("cocos2d: cc.ParticleBatchNode: resizing TextureAtlas capacity from [" + this.textureAtlas.getCapacity()
+ "] to [" + quantity + "].");
- if (!this._textureAtlas.resizeCapacity(quantity)) {
+ if (!this.textureAtlas.resizeCapacity(quantity)) {
// serious problems
- cc.log("cocos2d: WARNING: Not enough memory to resize the atlas");
- cc.Assert(false, "XXX: cc.ParticleBatchNode #increaseAtlasCapacity SHALL handle this assert");
+ cc.log("cc.ParticleBatchNode._increaseAtlasCapacityTo() : WARNING: Not enough memory to resize the atlas");
}
},
- _searchNewPositionInChildrenForZ:function (z) {
+ _searchNewPositionInChildrenForZ: function (z) {
var locChildren = this._children;
var count = locChildren.length;
for (var i = 0; i < count; i++) {
- if (locChildren[i].getZOrder() > z)
+ if (locChildren[i].zIndex > z)
return i;
}
return count;
},
- _getCurrentIndex:function (child, z) {
+ _getCurrentIndex: function (child, z) {
var foundCurrentIdx = false;
var foundNewIdx = false;
@@ -411,7 +432,7 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
for (var i = 0; i < count; i++) {
var pNode = locChildren[i];
// new index
- if (pNode.getZOrder() > z && !foundNewIdx) {
+ if (pNode.zIndex > z && !foundNewIdx) {
newIndex = i;
foundNewIdx = true;
@@ -419,7 +440,7 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
break;
}
// current index
- if (child == pNode) {
+ if (child === pNode) {
oldIndex = i;
foundCurrentIdx = true;
if (!foundNewIdx)
@@ -431,25 +452,30 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
if (!foundNewIdx)
newIndex = count;
newIndex += minusOne;
- return {newIndex:newIndex, oldIndex:oldIndex};
+ return {newIndex: newIndex, oldIndex: oldIndex};
},
- /**
- *
- * don't use lazy sorting, reordering the particle systems quads afterwards would be too complex
- * XXX research whether lazy sorting + freeing current quads and calloc a new block with size of capacity would be faster
- * XXX or possibly using vertexZ for reordering, that would be fastest
- * this helper is almost equivalent to CCNode's addChild, but doesn't make use of the lazy sorting
- *
- * @param {cc.ParticleSystem} child
- * @param {Number} z
- * @param {Number} aTag
- * @return {Number}
- * @private
- */
- _addChildHelper:function (child, z, aTag) {
- cc.Assert(child != null, "Argument must be non-nil");
- cc.Assert(child.getParent() == null, "child already added. It can't be added again");
+ //
+ //
+ // don't use lazy sorting, reordering the particle systems quads afterwards would be too complex
+ // XXX research whether lazy sorting + freeing current quads and calloc a new block with size of capacity would be faster
+ // XXX or possibly using vertexZ for reordering, that would be fastest
+ // this helper is almost equivalent to CCNode's addChild, but doesn't make use of the lazy sorting
+ //
+ // @param {cc.ParticleSystem} child
+ // @param {Number} z
+ // @param {Number} aTag
+ // @return {Number}
+ // @private
+ //
+ _addChildHelper: function (child, z, aTag) {
+ if (!child)
+ throw new Error("cc.ParticleBatchNode._addChildHelper(): child should be non-null");
+ if (child.parent) {
+ cc.log("cc.ParticleBatchNode._addChildHelper(): child already added. It can't be added again");
+ return null;
+ }
+
if (!this._children)
this._children = [];
@@ -457,21 +483,21 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
//don't use a lazy insert
var pos = this._searchNewPositionInChildrenForZ(z);
- this._children = cc.ArrayAppendObjectToIndex(this._children, child, pos);
- child.setTag(aTag);
- child._setZOrder(z);
- child.setParent(this);
+ this._children.splice(pos, 0, child);
+ child.tag = aTag;
+ child._setLocalZOrder(z);
+ child.parent = this;
if (this._running) {
- child.onEnter();
- child.onEnterTransitionDidFinish();
+ child._performRecursive(cc.Node._stateCallbackType.onEnter);
+ child._performRecursive(cc.Node._stateCallbackType.onEnterTransitionDidFinish);
}
return pos;
},
- _updateBlendFunc:function () {
- if (!this._textureAtlas.getTexture().hasPremultipliedAlpha()) {
- this._blendFunc.src = gl.SRC_ALPHA;
- this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
+ _updateBlendFunc: function () {
+ if (!this.textureAtlas.texture.hasPremultipliedAlpha()) {
+ this._blendFunc.src = cc.SRC_ALPHA;
+ this._blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
}
},
@@ -479,41 +505,34 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{
* return the texture atlas used for drawing the quads
* @return {cc.TextureAtlas}
*/
- getTextureAtlas:function () {
- return this._textureAtlas;
+ getTextureAtlas: function () {
+ return this.textureAtlas;
},
/**
* set the texture atlas used for drawing the quads
* @param {cc.TextureAtlas} textureAtlas
*/
- setTextureAtlas:function (textureAtlas) {
- this._textureAtlas = textureAtlas;
+ setTextureAtlas: function (textureAtlas) {
+ this.textureAtlas = textureAtlas;
}
});
-/**
- * initializes the particle system with cc.Texture2D, a capacity of particles, which particle system to use
- * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture
- * @param {Number} capacity
- * @return {cc.ParticleBatchNode}
- */
-cc.ParticleBatchNode.createWithTexture = function (texture, capacity) {
- var ret = new cc.ParticleBatchNode();
- if (ret && ret.initWithTexture(texture, capacity))
- return ret;
- return null;
-};
+var _p = cc.ParticleBatchNode.prototype;
+
+// Extended properties
+/** @expose */
+_p.texture;
+cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
+
/**
* initializes the particle system with the name of a file on disk (for a list of supported formats look at the cc.Texture2D class), a capacity of particles
- * @param {String} fileImage
- * @param capacity
+ * @deprecated since v3.0 please use new cc.ParticleBatchNode(filename, capacity) instead.
+ * @param {String|cc.Texture2D} fileImage
+ * @param {Number} capacity
* @return {cc.ParticleBatchNode}
*/
cc.ParticleBatchNode.create = function (fileImage, capacity) {
- var ret = new cc.ParticleBatchNode();
- if (ret && ret.init(fileImage, capacity))
- return ret;
- return null;
+ return new cc.ParticleBatchNode(fileImage, capacity);
};
diff --git a/extensions/CocoStudio/Armature/utils/CCArmatureDefine.js b/cocos2d/particle/CCParticleBatchNodeCanvasRenderCmd.js
similarity index 70%
rename from extensions/CocoStudio/Armature/utils/CCArmatureDefine.js
rename to cocos2d/particle/CCParticleBatchNodeCanvasRenderCmd.js
index 96778148cc..6e0990d140 100644
--- a/extensions/CocoStudio/Armature/utils/CCArmatureDefine.js
+++ b/cocos2d/particle/CCParticleBatchNodeCanvasRenderCmd.js
@@ -1,5 +1,5 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,15 +22,18 @@
THE SOFTWARE.
****************************************************************************/
-cc.MAX_VERTEXZ_VALUE = 5000000.0;
-cc.ARMATURE_MAX_CHILD = 50.0;
-cc.ARMATURE_MAX_ZORDER = 100;
-cc.ARMATURE_MAX_COUNT = ((cc.MAX_VERTEXZ_VALUE) / (cc.ARMATURE_MAX_CHILD) / cc.ARMATURE_MAX_ZORDER);
-cc.AUTO_ADD_SPRITE_FRAME_NAME_PREFIX = false;
-cc.ENABLE_PHYSICS_CHIPMUNK_DETECT = true;
+(function () {
+ /**
+ * cc.ParticleBatchNode's rendering objects of Canvas
+ */
+ cc.ParticleBatchNode.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = false;
+ };
-cc.armatureVersion = function(){
- return "v1.0.0.0";
-};
+ var proto = cc.ParticleBatchNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.ParticleBatchNode.CanvasRenderCmd;
-cc.RESOURCE_TYPE["TEXT"].push("ExportJson");
\ No newline at end of file
+ proto._initWithTexture = function () {
+ };
+})();
diff --git a/cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js b/cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js
new file mode 100644
index 0000000000..765e7553ad
--- /dev/null
+++ b/cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js
@@ -0,0 +1,60 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ /**
+ * cc.ParticleBatchNode's rendering objects of WebGL
+ */
+ cc.ParticleBatchNode.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = true;
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ };
+
+ var proto = cc.ParticleBatchNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.ParticleBatchNode.WebGLRenderCmd;
+
+ proto.rendering = function (ctx) {
+ var _t = this._node;
+ if (_t.textureAtlas.totalQuads === 0)
+ return;
+
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ this._glProgramState.apply(this._matrix);
+ cc.glBlendFuncForParticle(_t._blendFunc.src, _t._blendFunc.dst);
+ _t.textureAtlas.drawQuads();
+ };
+
+ proto._initWithTexture = function () {
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
+ };
+})();
diff --git a/cocos2d/particle_nodes/CCParticleExamples.js b/cocos2d/particle/CCParticleExamples.js
similarity index 62%
rename from cocos2d/particle_nodes/CCParticleExamples.js
rename to cocos2d/particle/CCParticleExamples.js
index f8b0a05cf5..7c89bb37fc 100644
--- a/cocos2d/particle_nodes/CCParticleExamples.js
+++ b/cocos2d/particle/CCParticleExamples.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -30,15 +30,16 @@
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleFire.create();
+ * var emitter = new cc.ParticleFire();
*/
cc.ParticleFire = cc.ParticleSystem.extend(/** @lends cc.ParticleFire# */{
/**
- * initialize a fire particle system
- * @return {Boolean}
+ * The cc.ParticleFire's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleFire()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 300 : 150);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 300 : 150);
},
/**
@@ -49,10 +50,10 @@ cc.ParticleFire = cc.ParticleSystem.extend(/** @lends cc.ParticleFire# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
@@ -71,7 +72,7 @@ cc.ParticleFire = cc.ParticleSystem.extend(/** @lends cc.ParticleFire# */{
this.setAngleVar(10);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, 60);
this.setPosVar(cc.p(40, 20));
@@ -83,16 +84,16 @@ cc.ParticleFire = cc.ParticleSystem.extend(/** @lends cc.ParticleFire# */{
// size, in pixels
this.setStartSize(54.0);
this.setStartSizeVar(10.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per frame
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.76,0.25,0.12,1.0));
- this.setStartColorVar(cc.c4f(0,0,0,0));
- this.setEndColor(cc.c4f(0,0,0,1));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(194,64,31,255));
+ this.setStartColorVar(cc.color(0,0,0,0));
+ this.setEndColor(cc.color(0,0,0,255));
+ this.setEndColorVar(cc.color(0,0,0,0));
// additive
this.setBlendAdditive(true);
@@ -104,17 +105,11 @@ cc.ParticleFire = cc.ParticleSystem.extend(/** @lends cc.ParticleFire# */{
/**
* Create a fire particle system
+ * @deprecated since v3.0 please use new cc.ParticleFire() instead
* @return {cc.ParticleFire}
- *
- * @example
- * var emitter = cc.ParticleFire.create();
*/
cc.ParticleFire.create = function () {
- var ret = new cc.ParticleFire();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleFire();
};
/**
@@ -123,15 +118,16 @@ cc.ParticleFire.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleFireworks.create();
+ * var emitter = new cc.ParticleFireworks();
*/
cc.ParticleFireworks = cc.ParticleSystem.extend(/** @lends cc.ParticleFireworks# */{
/**
- * initialize a fireworks particle system
- * @return {Boolean}
+ * The cc.ParticleFireworks's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleFireworks()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 1500 : 150);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 1500 : 150);
},
/**
@@ -142,10 +138,10 @@ cc.ParticleFireworks = cc.ParticleSystem.extend(/** @lends cc.ParticleFireworks#
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, -90));
@@ -159,7 +155,7 @@ cc.ParticleFireworks = cc.ParticleSystem.extend(/** @lends cc.ParticleFireworks#
this.setSpeedVar(50);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height / 2);
// angle
@@ -174,15 +170,15 @@ cc.ParticleFireworks = cc.ParticleSystem.extend(/** @lends cc.ParticleFireworks#
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.5,0.5,0.5,1.0));
- this.setStartColorVar(cc.c4f(0.5,0.5,0.5,1.0));
- this.setEndColor(cc.c4f(0.1,0.1,0.1,0.2));
- this.setEndColorVar(cc.c4f(0.1,0.1,0.1,0.2));
+ this.setStartColor(cc.color(128,128,128,255));
+ this.setStartColorVar(cc.color(128,128,128,255));
+ this.setEndColor(cc.color(26,26,26,51));
+ this.setEndColorVar(cc.color(26,26,26,51));
// size, in pixels
this.setStartSize(8.0);
this.setStartSizeVar(2.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// additive
this.setBlendAdditive(false);
@@ -194,17 +190,11 @@ cc.ParticleFireworks = cc.ParticleSystem.extend(/** @lends cc.ParticleFireworks#
/**
* Create a fireworks particle system
+ * @deprecated since v3.0 please use new cc.ParticleFireworks() instead.
* @return {cc.ParticleFireworks}
- *
- * @example
- * var emitter = cc.ParticleFireworks.create();
*/
cc.ParticleFireworks.create = function () {
- var ret = new cc.ParticleFireworks();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleFireworks();
};
/**
@@ -213,15 +203,16 @@ cc.ParticleFireworks.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleSun.create();
+ * var emitter = new cc.ParticleSun();
*/
cc.ParticleSun = cc.ParticleSystem.extend(/** @lends cc.ParticleSun# */{
/**
- * initialize a sun particle system
- * @return {Boolean}
+ * The cc.ParticleSun's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleSun()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 350 : 150);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 350 : 150);
},
/**
@@ -235,10 +226,10 @@ cc.ParticleSun = cc.ParticleSystem.extend(/** @lends cc.ParticleSun# */{
this.setBlendAdditive(true);
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, 0));
@@ -256,9 +247,9 @@ cc.ParticleSun = cc.ParticleSystem.extend(/** @lends cc.ParticleSun# */{
this.setAngleVar(360);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height / 2);
- this.setPosVar(cc.PointZero());
+ this.setPosVar(cc.p(0,0));
// life of particles
this.setLife(1);
@@ -267,16 +258,16 @@ cc.ParticleSun = cc.ParticleSystem.extend(/** @lends cc.ParticleSun# */{
// size, in pixels
this.setStartSize(30.0);
this.setStartSizeVar(10.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per seconds
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.76,0.25,0.12,1));
- this.setStartColorVar(cc.c4f(0,0,0,0));
- this.setEndColor(cc.c4f(0,0,0,1));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(194, 64, 31, 255));
+ this.setStartColorVar(cc.color(0, 0, 0, 0));
+ this.setEndColor(cc.color(0, 0, 0, 255));
+ this.setEndColorVar(cc.color(0, 0, 0, 0));
return true;
}
@@ -286,17 +277,11 @@ cc.ParticleSun = cc.ParticleSystem.extend(/** @lends cc.ParticleSun# */{
/**
* Create a sun particle system
+ * @deprecated since v3.0 please use new cc.ParticleSun() instead.
* @return {cc.ParticleSun}
- *
- * @example
- * var emitter = cc.ParticleSun.create();
*/
cc.ParticleSun.create = function () {
- var ret = new cc.ParticleSun();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleSun();
};
//! @brief A particle system
@@ -306,16 +291,16 @@ cc.ParticleSun.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleGalaxy.create();
+ * var emitter = new cc.ParticleGalaxy();
*/
cc.ParticleGalaxy = cc.ParticleSystem.extend(/** @lends cc.ParticleGalaxy# */{
/**
- * initialize a galaxy particle system
- * @return {Boolean}
+ * The cc.ParticleGalaxy's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleGalaxy()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- //return this.initWithTotalParticles(200);
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 200 : 100);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 200 : 100);
},
/**
@@ -326,10 +311,10 @@ cc.ParticleGalaxy = cc.ParticleSystem.extend(/** @lends cc.ParticleGalaxy# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, 0));
@@ -351,9 +336,9 @@ cc.ParticleGalaxy = cc.ParticleSystem.extend(/** @lends cc.ParticleGalaxy# */{
this.setAngleVar(360);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height / 2);
- this.setPosVar(cc.PointZero());
+ this.setPosVar(cc.p(0,0));
// life of particles
this.setLife(4);
@@ -362,16 +347,16 @@ cc.ParticleGalaxy = cc.ParticleSystem.extend(/** @lends cc.ParticleGalaxy# */{
// size, in pixels
this.setStartSize(37.0);
this.setStartSizeVar(10.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per second
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.12,0.25,0.76,1));
- this.setStartColorVar(cc.c4f(0,0,0,0));
- this.setEndColor(cc.c4f(0,0,0,1));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(31, 64, 194, 255));
+ this.setStartColorVar(cc.color(0, 0, 0, 0));
+ this.setEndColor(cc.color(0, 0, 0, 255));
+ this.setEndColorVar(cc.color(0, 0, 0, 0));
// additive
this.setBlendAdditive(true);
@@ -382,17 +367,11 @@ cc.ParticleGalaxy = cc.ParticleSystem.extend(/** @lends cc.ParticleGalaxy# */{
});
/**
* Create a galaxy particle system
+ * @deprecated since v3.0 please use new cc.OarticleGalaxy() instead.
* @return {cc.ParticleGalaxy}
- *
- * @example
- * var emitter = cc.ParticleGalaxy.create();
*/
cc.ParticleGalaxy.create = function () {
- var ret = new cc.ParticleGalaxy();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleGalaxy();
};
/**
@@ -401,15 +380,16 @@ cc.ParticleGalaxy.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleFlower.create();
+ * var emitter = new cc.ParticleFlower();
*/
cc.ParticleFlower = cc.ParticleSystem.extend(/** @lends cc.ParticleFlower# */{
/**
- * initialize a flower particle system
- * @return {Boolean}
+ * The cc.ParticleFlower's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleFlower()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 250 : 100);
+ ctor : function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 250 : 100);
},
/**
@@ -420,10 +400,10 @@ cc.ParticleFlower = cc.ParticleSystem.extend(/** @lends cc.ParticleFlower# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, 0));
@@ -445,9 +425,9 @@ cc.ParticleFlower = cc.ParticleSystem.extend(/** @lends cc.ParticleFlower# */{
this.setAngleVar(360);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height / 2);
- this.setPosVar(cc.PointZero());
+ this.setPosVar(cc.p(0,0));
// life of particles
this.setLife(4);
@@ -456,16 +436,16 @@ cc.ParticleFlower = cc.ParticleSystem.extend(/** @lends cc.ParticleFlower# */{
// size, in pixels
this.setStartSize(30.0);
this.setStartSizeVar(10.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per second
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.5,0.5,0.5,1));
- this.setStartColorVar(cc.c4f(0.5,0.5,0.5,0.5));
- this.setEndColor(cc.c4f(0,0,0,1));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(128, 128, 128, 255));
+ this.setStartColorVar(cc.color(128, 128, 128, 128));
+ this.setEndColor(cc.color(0, 0, 0, 255));
+ this.setEndColorVar(cc.color(0, 0, 0, 0));
// additive
this.setBlendAdditive(true);
@@ -477,17 +457,11 @@ cc.ParticleFlower = cc.ParticleSystem.extend(/** @lends cc.ParticleFlower# */{
/**
* Create a flower particle system
+ * @deprecated since v3.0 please use new cc.ParticleFlower() instead.
* @return {cc.ParticleFlower}
- *
- * @example
- * var emitter = cc.ParticleFlower.create();
*/
cc.ParticleFlower.create = function () {
- var ret = new cc.ParticleFlower();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleFlower();
};
//! @brief A meteor particle system
@@ -497,15 +471,16 @@ cc.ParticleFlower.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleMeteor.create();
+ * var emitter = new cc.ParticleMeteor();
*/
cc.ParticleMeteor = cc.ParticleSystem.extend(/** @lends cc.ParticleMeteor# */{
/**
- * initialize a meteor particle system
- * @return {Boolean}
+ * The cc.ParticleMeteor's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleMeteor()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 150 : 100);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 150 : 100);
},
/**
@@ -516,10 +491,10 @@ cc.ParticleMeteor = cc.ParticleSystem.extend(/** @lends cc.ParticleMeteor# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(-200, 200));
@@ -541,9 +516,9 @@ cc.ParticleMeteor = cc.ParticleSystem.extend(/** @lends cc.ParticleMeteor# */{
this.setAngleVar(360);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height / 2);
- this.setPosVar(cc.PointZero());
+ this.setPosVar(cc.p(0,0));
// life of particles
this.setLife(2);
@@ -552,16 +527,16 @@ cc.ParticleMeteor = cc.ParticleSystem.extend(/** @lends cc.ParticleMeteor# */{
// size, in pixels
this.setStartSize(60.0);
this.setStartSizeVar(10.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per second
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.2,0.4,0.7,1));
- this.setStartColorVar(cc.c4f(0,0,0.2,0.1));
- this.setEndColor(cc.c4f(0,0,0,1));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(51, 102, 179));
+ this.setStartColorVar(cc.color(0, 0, 51, 26));
+ this.setEndColor(cc.color(0, 0, 0, 255));
+ this.setEndColorVar(cc.color(0, 0, 0, 0));
// additive
this.setBlendAdditive(true);
@@ -573,17 +548,11 @@ cc.ParticleMeteor = cc.ParticleSystem.extend(/** @lends cc.ParticleMeteor# */{
/**
* Create a meteor particle system
+ * @deprecated since v3.0 please use new cc.ParticleMeteor() instead.
* @return {cc.ParticleMeteor}
- *
- * @example
- * var emitter = cc.ParticleMeteor.create();
*/
cc.ParticleMeteor.create = function () {
- var ret = new cc.ParticleMeteor();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleMeteor();
};
/**
@@ -592,15 +561,17 @@ cc.ParticleMeteor.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleSpiral.create();
+ * var emitter = new cc.ParticleSpiral();
*/
cc.ParticleSpiral = cc.ParticleSystem.extend(/** @lends cc.ParticleSpiral# */{
+
/**
- * initialize a spiral particle system
- * @return {Boolean}
+ * The cc.ParticleSpiral's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleSpiral()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 500 : 100);
+ ctor:function() {
+ cc.ParticleSystem.prototype.ctor.call(this,(cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 500 : 100);
},
/**
@@ -611,10 +582,10 @@ cc.ParticleSpiral = cc.ParticleSystem.extend(/** @lends cc.ParticleSpiral# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, 0));
@@ -636,9 +607,9 @@ cc.ParticleSpiral = cc.ParticleSystem.extend(/** @lends cc.ParticleSpiral# */{
this.setAngleVar(0);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height / 2);
- this.setPosVar(cc.PointZero());
+ this.setPosVar(cc.p(0,0));
// life of particles
this.setLife(12);
@@ -647,16 +618,16 @@ cc.ParticleSpiral = cc.ParticleSystem.extend(/** @lends cc.ParticleSpiral# */{
// size, in pixels
this.setStartSize(20.0);
this.setStartSizeVar(0.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per second
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.5,0.5,0.5,1));
- this.setStartColorVar(cc.c4f(0.5,0.5,0.5,0));
- this.setEndColor(cc.c4f(0.5,0.5,0.5,1));
- this.setEndColorVar(cc.c4f(0.5,0.5,0.5,0));
+ this.setStartColor(cc.color(128,128,128,255));
+ this.setStartColorVar(cc.color(128,128,128,0));
+ this.setEndColor(cc.color(128,128,128,255));
+ this.setEndColorVar(cc.color(128,128,128,0));
// additive
this.setBlendAdditive(false);
@@ -668,17 +639,11 @@ cc.ParticleSpiral = cc.ParticleSystem.extend(/** @lends cc.ParticleSpiral# */{
/**
* Create a spiral particle system
+ * @deprecated since v3.0 please use new cc.ParticleSpiral() instead.
* @return {cc.ParticleSpiral}
- *
- * @example
- * var emitter = cc.ParticleSpiral.create();
*/
cc.ParticleSpiral.create = function () {
- var ret = new cc.ParticleSpiral();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleSpiral();
};
/**
@@ -687,16 +652,16 @@ cc.ParticleSpiral.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleExplosion.create();
+ * var emitter = new cc.ParticleExplosion();
*/
cc.ParticleExplosion = cc.ParticleSystem.extend(/** @lends cc.ParticleExplosion# */{
/**
- * initialize an explosion particle system
- * @return {Boolean}
+ * The cc.ParticleExplosion's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleExplosion()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- //return this.initWithTotalParticles(700);
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 700 : 300);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 700 : 300);
},
/**
@@ -709,7 +674,7 @@ cc.ParticleExplosion = cc.ParticleSystem.extend(/** @lends cc.ParticleExplosion#
// duration
this.setDuration(0.1);
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, 0));
@@ -731,9 +696,9 @@ cc.ParticleExplosion = cc.ParticleSystem.extend(/** @lends cc.ParticleExplosion#
this.setAngleVar(360);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height / 2);
- this.setPosVar(cc.PointZero());
+ this.setPosVar(cc.p(0,0));
// life of particles
this.setLife(5.0);
@@ -742,16 +707,16 @@ cc.ParticleExplosion = cc.ParticleSystem.extend(/** @lends cc.ParticleExplosion#
// size, in pixels
this.setStartSize(15.0);
this.setStartSizeVar(10.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per second
this.setEmissionRate(this.getTotalParticles() / this.getDuration());
// color of particles
- this.setStartColor(cc.c4f(0.7,0.1,0.2,1));
- this.setStartColorVar(cc.c4f(0.5,0.5,0.5,0));
- this.setEndColor(cc.c4f(0.5,0.5,0.5,0));
- this.setEndColorVar(cc.c4f(0.5,0.5,0.5,0));
+ this.setStartColor(cc.color(179, 26, 51, 255));
+ this.setStartColorVar(cc.color(128, 128, 128, 0));
+ this.setEndColor(cc.color(128, 128, 128, 0));
+ this.setEndColorVar(cc.color(128, 128, 128, 0));
// additive
this.setBlendAdditive(false);
@@ -763,17 +728,11 @@ cc.ParticleExplosion = cc.ParticleSystem.extend(/** @lends cc.ParticleExplosion#
/**
* Create an explosion particle system
+ * @deprecated since v3.0 please use new cc.ParticleExplosion() instead.
* @return {cc.ParticleExplosion}
- *
- * @example
- * var emitter = cc.ParticleExplosion.create();
*/
cc.ParticleExplosion.create = function () {
- var ret = new cc.ParticleExplosion();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleExplosion();
};
/**
@@ -782,16 +741,17 @@ cc.ParticleExplosion.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleSmoke.create();
+ * var emitter = new cc.ParticleSmoke();
*/
cc.ParticleSmoke = cc.ParticleSystem.extend(/** @lends cc.ParticleSmoke# */{
+
/**
- * initialize a smoke particle system
- * @return {Boolean}
+ * The cc.ParticleSmoke's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleSmoke()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- //return this.initWithTotalParticles(200);
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 200 : 100);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 200 : 100);
},
/**
@@ -802,10 +762,10 @@ cc.ParticleSmoke = cc.ParticleSystem.extend(/** @lends cc.ParticleSmoke# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// Emitter mode: Gravity Mode
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, 0));
@@ -823,7 +783,7 @@ cc.ParticleSmoke = cc.ParticleSystem.extend(/** @lends cc.ParticleSmoke# */{
this.setAngleVar(5);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, 0);
this.setPosVar(cc.p(20, 0));
@@ -834,16 +794,16 @@ cc.ParticleSmoke = cc.ParticleSystem.extend(/** @lends cc.ParticleSmoke# */{
// size, in pixels
this.setStartSize(60.0);
this.setStartSizeVar(10.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per frame
this.setEmissionRate(this.getTotalParticles() / this.getLife());
// color of particles
- this.setStartColor(cc.c4f(0.8,0.8,0.8,1));
- this.setStartColorVar(cc.c4f(0.02,0.02,0.02,0));
- this.setEndColor(cc.c4f(0,0,0,1));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(204, 204, 204, 255));
+ this.setStartColorVar(cc.color(5, 5, 5, 0));
+ this.setEndColor(cc.color(0, 0, 0, 255));
+ this.setEndColorVar(cc.color(0, 0, 0, 0));
// additive
this.setBlendAdditive(false);
@@ -855,17 +815,11 @@ cc.ParticleSmoke = cc.ParticleSystem.extend(/** @lends cc.ParticleSmoke# */{
/**
* Create a smoke particle system
+ * @deprecated since v3.0 please use new cc.ParticleSmoke() instead.
* @return {cc.ParticleSmoke}
- *
- * @example
- * var emitter = cc.ParticleFireworks.create();
*/
cc.ParticleSmoke.create = function () {
- var ret = new cc.ParticleSmoke();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleSmoke();
};
/**
@@ -874,15 +828,17 @@ cc.ParticleSmoke.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleSnow.create();
+ * var emitter = new cc.ParticleSnow();
*/
cc.ParticleSnow = cc.ParticleSystem.extend(/** @lends cc.ParticleSnow# */{
+
/**
- * initialize a snow particle system
- * @return {Boolean}
+ * The cc.ParticleSnow's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleSnow()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 700 : 250);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 700 : 250);
},
/**
@@ -893,10 +849,10 @@ cc.ParticleSnow = cc.ParticleSystem.extend(/** @lends cc.ParticleSnow# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
// set gravity mode.
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(0, -1));
@@ -914,7 +870,7 @@ cc.ParticleSnow = cc.ParticleSystem.extend(/** @lends cc.ParticleSnow# */{
this.setTangentialAccelVar(1);
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height + 10);
this.setPosVar(cc.p(winSize.width / 2, 0));
@@ -929,16 +885,16 @@ cc.ParticleSnow = cc.ParticleSystem.extend(/** @lends cc.ParticleSnow# */{
// size, in pixels
this.setStartSize(10.0);
this.setStartSizeVar(5.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per second
this.setEmissionRate(10);
// color of particles
- this.setStartColor(cc.c4f(1,1,1,1));
- this.setStartColorVar(cc.c4f(0,0,0,0));
- this.setEndColor(cc.c4f(1,1,1,0));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(255, 255, 255, 255));
+ this.setStartColorVar(cc.color(0, 0, 0, 0));
+ this.setEndColor(cc.color(255, 255, 255, 0));
+ this.setEndColorVar(cc.color(0, 0, 0, 0));
// additive
this.setBlendAdditive(false);
@@ -950,17 +906,11 @@ cc.ParticleSnow = cc.ParticleSystem.extend(/** @lends cc.ParticleSnow# */{
/**
* Create a snow particle system
+ * @deprecated since v3.0 please use new cc.ParticleSnow() instead.
* @return {cc.ParticleSnow}
- *
- * @example
- * var emitter = cc.ParticleSnow.create();
*/
cc.ParticleSnow.create = function () {
- var ret = new cc.ParticleSnow();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleSnow();
};
//! @brief A rain particle system
@@ -970,15 +920,17 @@ cc.ParticleSnow.create = function () {
* @extends cc.ParticleSystem
*
* @example
- * var emitter = cc.ParticleRain.create();
+ * var emitter = new cc.ParticleRain();
*/
cc.ParticleRain = cc.ParticleSystem.extend(/** @lends cc.ParticleRain# */{
+
/**
- * initialize a rain particle system
- * @return {Boolean}
+ * The cc.ParticleRain's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.ParticleRain()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- init:function () {
- return this.initWithTotalParticles((cc.renderContextType === cc.WEBGL) ? 1000 : 300);
+ ctor:function () {
+ cc.ParticleSystem.prototype.ctor.call(this, (cc._renderType === cc.game.RENDER_TYPE_WEBGL) ? 1000 : 300);
},
/**
@@ -989,9 +941,9 @@ cc.ParticleRain = cc.ParticleSystem.extend(/** @lends cc.ParticleRain# */{
initWithTotalParticles:function (numberOfParticles) {
if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) {
// duration
- this.setDuration(cc.PARTICLE_DURATION_INFINITY);
+ this.setDuration(cc.ParticleSystem.DURATION_INFINITY);
- this.setEmitterMode(cc.PARTICLE_MODE_GRAVITY);
+ this.setEmitterMode(cc.ParticleSystem.MODE_GRAVITY);
// Gravity Mode: gravity
this.setGravity(cc.p(10, -10));
@@ -1014,7 +966,7 @@ cc.ParticleRain = cc.ParticleSystem.extend(/** @lends cc.ParticleRain# */{
// emitter position
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
this.setPosition(winSize.width / 2, winSize.height);
this.setPosVar(cc.p(winSize.width / 2, 0));
@@ -1025,16 +977,16 @@ cc.ParticleRain = cc.ParticleSystem.extend(/** @lends cc.ParticleRain# */{
// size, in pixels
this.setStartSize(4.0);
this.setStartSizeVar(2.0);
- this.setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE);
+ this.setEndSize(cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE);
// emits per second
this.setEmissionRate(20);
// color of particles
- this.setStartColor(cc.c4f(0.7,0.8,1,1));
- this.setStartColorVar(cc.c4f(0,0,0,0));
- this.setEndColor(cc.c4f(0.7,0.8,1,0.5));
- this.setEndColorVar(cc.c4f(0,0,0,0));
+ this.setStartColor(cc.color(179, 204, 255, 255));
+ this.setStartColorVar(cc.color(0, 0, 0, 0));
+ this.setEndColor(cc.color(179, 204, 255, 128));
+ this.setEndColorVar(cc.color(0, 0, 0, 0));
// additive
this.setBlendAdditive(false);
@@ -1046,15 +998,9 @@ cc.ParticleRain = cc.ParticleSystem.extend(/** @lends cc.ParticleRain# */{
/**
* Create a rain particle system
+ * @deprecated since v3.0 please use cc.ParticleRain() instead.
* @return {cc.ParticleRain}
- *
- * @example
- * var emitter = cc.ParticleRain.create();
*/
cc.ParticleRain.create = function () {
- var ret = new cc.ParticleRain();
- if (ret.init()) {
- return ret;
- }
- return null;
+ return new cc.ParticleRain();
};
diff --git a/cocos2d/particle/CCParticleSystem.js b/cocos2d/particle/CCParticleSystem.js
new file mode 100644
index 0000000000..7a18fa4f32
--- /dev/null
+++ b/cocos2d/particle/CCParticleSystem.js
@@ -0,0 +1,2318 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+// ideas taken from:
+// . The ocean spray in your face [Jeff Lander]
+// http://www.double.co.nz/dust/col0798.pdf
+// . Building an Advanced Particle System [John van der Burg]
+// http://www.gamasutra.com/features/20000623/vanderburg_01.htm
+// . LOVE game engine
+// http://love2d.org/
+//
+//
+// Radius mode support, from 71 squared
+// http://particledesigner.71squared.com/
+//
+// IMPORTANT: Particle Designer is supported by cocos2d, but
+// 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
+// cocos2d uses a another approach, but the results are almost identical.
+//
+
+
+// tCCPositionType
+// possible types of particle positions
+
+
+/**
+ * Structure that contains the values of each particle
+ * @Class
+ * @Construct
+ * @param {cc.Point} [pos=cc.p(0,0)] Position of particle
+ * @param {cc.Point} [startPos=cc.p(0,0)]
+ * @param {cc.Color} [color= cc.color(0, 0, 0, 255)]
+ * @param {cc.Color} [deltaColor=cc.color(0, 0, 0, 255)]
+ * @param {cc.Size} [size=0]
+ * @param {cc.Size} [deltaSize=0]
+ * @param {Number} [rotation=0]
+ * @param {Number} [deltaRotation=0]
+ * @param {Number} [timeToLive=0]
+ * @param {Number} [atlasIndex=0]
+ * @param {cc.Particle.ModeA} [modeA=]
+ * @param {cc.Particle.ModeA} [modeB=]
+ */
+cc.Particle = function (pos, startPos, color, deltaColor, size, deltaSize, rotation, deltaRotation, timeToLive, atlasIndex, modeA, modeB) {
+ this.pos = pos ? pos : cc.p(0, 0);
+ this.startPos = startPos ? startPos : cc.p(0, 0);
+ this.color = color ? color : {r: 0, g: 0, b: 0, a: 255};
+ this.deltaColor = deltaColor ? deltaColor : {r: 0, g: 0, b: 0, a: 255};
+ this.size = size || 0;
+ this.deltaSize = deltaSize || 0;
+ this.rotation = rotation || 0;
+ this.deltaRotation = deltaRotation || 0;
+ this.timeToLive = timeToLive || 0;
+ this.atlasIndex = atlasIndex || 0;
+ this.modeA = modeA ? modeA : new cc.Particle.ModeA();
+ this.modeB = modeB ? modeB : new cc.Particle.ModeB();
+ this.isChangeColor = false;
+ this.drawPos = cc.p(0, 0);
+};
+
+/**
+ * Mode A: gravity, direction, radial accel, tangential accel
+ * @Class
+ * @Construct
+ * @param {cc.Point} dir direction of particle
+ * @param {Number} radialAccel
+ * @param {Number} tangentialAccel
+ */
+cc.Particle.ModeA = function (dir, radialAccel, tangentialAccel) {
+ this.dir = dir ? dir : cc.p(0, 0);
+ this.radialAccel = radialAccel || 0;
+ this.tangentialAccel = tangentialAccel || 0;
+};
+
+/**
+ * Mode B: radius mode
+ * @Class
+ * @Construct
+ * @param {Number} angle
+ * @param {Number} degreesPerSecond
+ * @param {Number} radius
+ * @param {Number} deltaRadius
+ */
+cc.Particle.ModeB = function (angle, degreesPerSecond, radius, deltaRadius) {
+ this.angle = angle || 0;
+ this.degreesPerSecond = degreesPerSecond || 0;
+ this.radius = radius || 0;
+ this.deltaRadius = deltaRadius || 0;
+};
+
+/**
+ * Array of Point instances used to optimize particle updates
+ */
+cc.Particle.TemporaryPoints = [
+ cc.p(),
+ cc.p(),
+ cc.p(),
+ cc.p()
+];
+
+/**
+ *
+ * Particle System base class.
+ * Attributes of a Particle System:
+ * - emission rate of the particles
+ * - Gravity Mode (Mode A):
+ * - gravity
+ * - direction
+ * - speed +- variance
+ * - tangential acceleration +- variance
+ * - radial acceleration +- variance
+ * - Radius Mode (Mode B):
+ * - startRadius +- variance
+ * - endRadius +- variance
+ * - rotate +- variance
+ * - Properties common to all modes:
+ * - life +- life variance
+ * - start spin +- variance
+ * - end spin +- variance
+ * - start size +- variance
+ * - end size +- variance
+ * - start color +- variance
+ * - end color +- variance
+ * - life +- variance
+ * - blending function
+ * - texture
+ *
+ * cocos2d also supports particles generated by Particle Designer (http://particledesigner.71squared.com/).
+ * 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
+ * cocos2d uses a another approach, but the results are almost identical.
+ * cocos2d supports all the variables used by Particle Designer plus a bit more:
+ * - spinning particles (supported when using ParticleSystem)
+ * - tangential acceleration (Gravity mode)
+ * - radial acceleration (Gravity mode)
+ * - radius direction (Radius mode) (Particle Designer supports outwards to inwards direction only)
+ * It is possible to customize any of the above mentioned properties in runtime. Example:
+ *
+ * @class
+ * @extends cc.Node
+ *
+ * @property {Boolean} opacityModifyRGB - Indicate whether the alpha value modify color.
+ * @property {cc.SpriteBatchNode} batchNode - Weak reference to the sprite batch node.
+ * @property {Boolean} active - <@readonly> Indicate whether the particle system is activated.
+ * @property {Number} shapeType - ShapeType of ParticleSystem : cc.ParticleSystem.BALL_SHAPE | cc.ParticleSystem.STAR_SHAPE.
+ * @property {Number} atlasIndex - Index of system in batch node array.
+ * @property {Number} particleCount - Current quantity of particles that are being simulated.
+ * @property {Number} duration - How many seconds the emitter wil run. -1 means 'forever'
+ * @property {cc.Point} sourcePos - Source position of the emitter.
+ * @property {cc.Point} posVar - Variation of source position.
+ * @property {Number} life - Life of each particle setter.
+ * @property {Number} lifeVar - Variation of life.
+ * @property {Number} angle - Angle of each particle setter.
+ * @property {Number} angleVar - Variation of angle of each particle setter.
+ * @property {Number} startSize - Start size in pixels of each particle.
+ * @property {Number} startSizeVar - Variation of start size in pixels.
+ * @property {Number} endSize - End size in pixels of each particle.
+ * @property {Number} endSizeVar - Variation of end size in pixels.
+ * @property {Number} startSpin - Start angle of each particle.
+ * @property {Number} startSpinVar - Variation of start angle.
+ * @property {Number} endSpin - End angle of each particle.
+ * @property {Number} endSpinVar - Variation of end angle.
+ * @property {cc.Point} gravity - Gravity of the emitter.
+ * @property {cc.Point} speed - Speed of the emitter.
+ * @property {cc.Point} speedVar - Variation of the speed.
+ * @property {Number} tangentialAccel - Tangential acceleration of each particle. Only available in 'Gravity' mode.
+ * @property {Number} tangentialAccelVar - Variation of the tangential acceleration.
+ * @property {Number} tangentialAccel - Radial acceleration of each particle. Only available in 'Gravity' mode.
+ * @property {Number} tangentialAccelVar - Variation of the radial acceleration.
+ * @property {Boolean} rotationIsDir - Indicate whether the rotation of each particle equals to its direction. Only available in 'Gravity' mode.
+ * @property {Number} startRadius - Starting radius of the particles. Only available in 'Radius' mode.
+ * @property {Number} startRadiusVar - Variation of the starting radius.
+ * @property {Number} endRadius - Ending radius of the particles. Only available in 'Radius' mode.
+ * @property {Number} endRadiusVar - Variation of the ending radius.
+ * @property {Number} rotatePerS - Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
+ * @property {Number} rotatePerSVar - Variation of the degress to rotate a particle around the source pos per second.
+ * @property {cc.Color} startColor - Start color of each particle.
+ * @property {cc.Color} startColorVar - Variation of the start color.
+ * @property {cc.Color} endColor - Ending color of each particle.
+ * @property {cc.Color} endColorVar - Variation of the end color.
+ * @property {Number} emissionRate - Emission rate of the particles.
+ * @property {Number} emitterMode - Emitter modes: CCParticleSystem.MODE_GRAVITY: uses gravity, speed, radial and tangential acceleration; CCParticleSystem.MODE_RADIUS: uses radius movement + rotation.
+ * @property {Number} positionType - Particles movement type: cc.ParticleSystem.TYPE_FREE | cc.ParticleSystem.TYPE_GROUPED.
+ * @property {Number} totalParticles - Maximum particles of the system.
+ * @property {Boolean} autoRemoveOnFinish - Indicate whether the node will be auto-removed when it has no particles left.
+ * @property {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture - Texture of Particle System.
+ *
+ * @example
+ * emitter.radialAccel = 15;
+ * emitter.startSpin = 0;
+ */
+cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{
+ _className: "ParticleSystem",
+ //***********variables*************
+ _plistFile: "",
+ //! time elapsed since the start of the system (in seconds)
+ _elapsed: 0,
+ _dontTint: false,
+
+ // Different modes
+ //! Mode A:Gravity + Tangential Accel + Radial Accel
+ modeA: null,
+ //! Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
+ modeB: null,
+
+ //private POINTZERO for ParticleSystem
+ _pointZeroForParticle: cc.p(0, 0),
+
+ //! Array of particles
+ _particles: null,
+
+ // color modulate
+ // BOOL colorModulate;
+
+ //! How many particles can be emitted per second
+ _emitCounter: 0,
+ //! particle idx
+ _particleIdx: 0,
+
+ _batchNode: null,
+ atlasIndex: 0,
+
+ //true if scaled or rotated
+ _transformSystemDirty: false,
+ _allocatedParticles: 0,
+
+ _isActive: false,
+ particleCount: 0,
+ duration: 0,
+ _sourcePosition: null,
+ _posVar: null,
+ life: 0,
+ lifeVar: 0,
+ angle: 0,
+ angleVar: 0,
+ startSize: 0,
+ startSizeVar: 0,
+ endSize: 0,
+ endSizeVar: 0,
+ _startColor: null,
+ _startColorVar: null,
+ _endColor: null,
+ _endColorVar: null,
+ startSpin: 0,
+ startSpinVar: 0,
+ endSpin: 0,
+ endSpinVar: 0,
+ emissionRate: 0,
+ _totalParticles: 0,
+ _texture: null,
+ _blendFunc: null,
+ _opacityModifyRGB: false,
+ positionType: null,
+ autoRemoveOnFinish: false,
+ emitterMode: 0,
+
+ _textureLoaded: null,
+
+ /**
+ * return the string found by key in dict.
+ * This plist files can be create manually or with Particle Designer:
+ * http://particledesigner.71squared.com/
+ *
+ * Constructor of cc.ParticleSystem
+ * @param {String|Number} plistFile
+ */
+ ctor: function (plistFile) {
+ cc.Node.prototype.ctor.call(this);
+ this.emitterMode = cc.ParticleSystem.MODE_GRAVITY;
+ this.modeA = new cc.ParticleSystem.ModeA();
+ this.modeB = new cc.ParticleSystem.ModeB();
+ this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
+
+ this._particles = [];
+ this._sourcePosition = cc.p(0, 0);
+ this._posVar = cc.p(0, 0);
+
+ this._startColor = cc.color(255, 255, 255, 255);
+ this._startColorVar = cc.color(255, 255, 255, 255);
+ this._endColor = cc.color(255, 255, 255, 255);
+ this._endColorVar = cc.color(255, 255, 255, 255);
+
+ this._plistFile = "";
+ this._elapsed = 0;
+ this._dontTint = false;
+ this._pointZeroForParticle = cc.p(0, 0);
+ this._emitCounter = 0;
+ this._particleIdx = 0;
+ this._batchNode = null;
+ this.atlasIndex = 0;
+
+ this._transformSystemDirty = false;
+ this._allocatedParticles = 0;
+ this._isActive = false;
+ this.particleCount = 0;
+ this.duration = 0;
+ this.life = 0;
+ this.lifeVar = 0;
+ this.angle = 0;
+ this.angleVar = 0;
+ this.startSize = 0;
+ this.startSizeVar = 0;
+ this.endSize = 0;
+ this.endSizeVar = 0;
+
+ this.startSpin = 0;
+ this.startSpinVar = 0;
+ this.endSpin = 0;
+ this.endSpinVar = 0;
+ this.emissionRate = 0;
+ this._totalParticles = 0;
+ this._texture = null;
+ this._opacityModifyRGB = false;
+ this.positionType = cc.ParticleSystem.TYPE_FREE;
+ this.autoRemoveOnFinish = false;
+
+ this._textureLoaded = true;
+
+ if (!plistFile || cc.isNumber(plistFile)) {
+ var ton = plistFile || 100;
+ this.setDrawMode(cc.ParticleSystem.TEXTURE_MODE);
+ this.initWithTotalParticles(ton);
+ } else if (cc.isString(plistFile)) {
+ this.initWithFile(plistFile);
+ } else if (cc.isObject(plistFile)) {
+ this.initWithDictionary(plistFile, "");
+ }
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.ParticleSystem.CanvasRenderCmd(this);
+ else
+ return new cc.ParticleSystem.WebGLRenderCmd(this);
+ },
+
+ /**
+ * This is a hack function for performance, it's only available on Canvas mode.
+ * It's very expensive to change color on Canvas mode, so if set it to true, particle system will ignore the changing color operation.
+ * @param {boolean} ignore
+ */
+ ignoreColor: function (ignore) {
+ this._dontTint = ignore;
+ },
+
+ /**
+ * initializes the texture with a rectangle measured Points
+ * pointRect should be in Texture coordinates, not pixel coordinates
+ *
+ * @param {cc.Rect} pointRect
+ */
+ initTexCoordsWithRect: function (pointRect) {
+ this._renderCmd.initTexCoordsWithRect(pointRect);
+ },
+
+ /**
+ * return weak reference to the cc.SpriteBatchNode that renders the cc.Sprite
+ * @return {cc.ParticleBatchNode}
+ */
+ getBatchNode: function () {
+ return this._batchNode;
+ },
+
+ /**
+ * set weak reference to the cc.SpriteBatchNode that renders the cc.Sprite
+ * @param {cc.ParticleBatchNode} batchNode
+ */
+ setBatchNode: function (batchNode) {
+ this._renderCmd.setBatchNode(batchNode);
+ },
+
+ /**
+ * return index of system in batch node array
+ * @return {Number}
+ */
+ getAtlasIndex: function () {
+ return this.atlasIndex;
+ },
+
+ /**
+ * set index of system in batch node array
+ * @param {Number} atlasIndex
+ */
+ setAtlasIndex: function (atlasIndex) {
+ this.atlasIndex = atlasIndex;
+ },
+
+ /**
+ * Return DrawMode of ParticleSystem (Canvas Mode only)
+ * @return {Number}
+ */
+ getDrawMode: function () {
+ return this._renderCmd.getDrawMode();
+ },
+
+ /**
+ * DrawMode of ParticleSystem setter (Canvas Mode only)
+ * @param {Number} drawMode
+ */
+ setDrawMode: function (drawMode) {
+ this._renderCmd.setDrawMode(drawMode);
+ },
+
+ /**
+ * Return ShapeType of ParticleSystem (Canvas Mode only)
+ * @return {Number}
+ */
+ getShapeType: function () {
+ return this._renderCmd.getShapeType();
+ },
+
+ /**
+ * ShapeType of ParticleSystem setter (Canvas Mode only)
+ * @param {Number} shapeType
+ */
+ setShapeType: function (shapeType) {
+ this._renderCmd.setShapeType(shapeType);
+ },
+
+ /**
+ * Return ParticleSystem is active
+ * @return {Boolean}
+ */
+ isActive: function () {
+ return this._isActive;
+ },
+
+ /**
+ * Quantity of particles that are being simulated at the moment
+ * @return {Number}
+ */
+ getParticleCount: function () {
+ return this.particleCount;
+ },
+
+ /**
+ * Quantity of particles setter
+ * @param {Number} particleCount
+ */
+ setParticleCount: function (particleCount) {
+ this.particleCount = particleCount;
+ },
+
+ /**
+ * How many seconds the emitter wil run. -1 means 'forever'
+ * @return {Number}
+ */
+ getDuration: function () {
+ return this.duration;
+ },
+
+ /**
+ * set run seconds of the emitter
+ * @param {Number} duration
+ */
+ setDuration: function (duration) {
+ this.duration = duration;
+ },
+
+ /**
+ * Return sourcePosition of the emitter
+ * @return {cc.Point | Object}
+ */
+ getSourcePosition: function () {
+ return {x: this._sourcePosition.x, y: this._sourcePosition.y};
+ },
+
+ /**
+ * sourcePosition of the emitter setter
+ * @param sourcePosition
+ */
+ setSourcePosition: function (sourcePosition) {
+ this._sourcePosition.x = sourcePosition.x;
+ this._sourcePosition.y = sourcePosition.y;
+ },
+
+ /**
+ * Return Position variance of the emitter
+ * @return {cc.Point | Object}
+ */
+ getPosVar: function () {
+ return {x: this._posVar.x, y: this._posVar.y};
+ },
+
+ /**
+ * Position variance of the emitter setter
+ * @param {cc.Point} posVar
+ */
+ setPosVar: function (posVar) {
+ this._posVar.x = posVar.x;
+ this._posVar.y = posVar.y;
+ },
+
+ /**
+ * Return life of each particle
+ * @return {Number}
+ */
+ getLife: function () {
+ return this.life;
+ },
+
+ /**
+ * life of each particle setter
+ * @param {Number} life
+ */
+ setLife: function (life) {
+ this.life = life;
+ },
+
+ /**
+ * Return life variance of each particle
+ * @return {Number}
+ */
+ getLifeVar: function () {
+ return this.lifeVar;
+ },
+
+ /**
+ * life variance of each particle setter
+ * @param {Number} lifeVar
+ */
+ setLifeVar: function (lifeVar) {
+ this.lifeVar = lifeVar;
+ },
+
+ /**
+ * Return angle of each particle
+ * @return {Number}
+ */
+ getAngle: function () {
+ return this.angle;
+ },
+
+ /**
+ * angle of each particle setter
+ * @param {Number} angle
+ */
+ setAngle: function (angle) {
+ this.angle = angle;
+ },
+
+ /**
+ * Return angle variance of each particle
+ * @return {Number}
+ */
+ getAngleVar: function () {
+ return this.angleVar;
+ },
+
+ /**
+ * angle variance of each particle setter
+ * @param angleVar
+ */
+ setAngleVar: function (angleVar) {
+ this.angleVar = angleVar;
+ },
+
+ // mode A
+ /**
+ * Return Gravity of emitter
+ * @return {cc.Point}
+ */
+ getGravity: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getGravity() : Particle Mode should be Gravity");
+ var locGravity = this.modeA.gravity;
+ return cc.p(locGravity.x, locGravity.y);
+ },
+
+ /**
+ * Gravity of emitter setter
+ * @param {cc.Point} gravity
+ */
+ setGravity: function (gravity) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setGravity() : Particle Mode should be Gravity");
+ this.modeA.gravity = gravity;
+ },
+
+ /**
+ * Return Speed of each particle
+ * @return {Number}
+ */
+ getSpeed: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getSpeed() : Particle Mode should be Gravity");
+ return this.modeA.speed;
+ },
+
+ /**
+ * Speed of each particle setter
+ * @param {Number} speed
+ */
+ setSpeed: function (speed) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setSpeed() : Particle Mode should be Gravity");
+ this.modeA.speed = speed;
+ },
+
+ /**
+ * return speed variance of each particle. Only available in 'Gravity' mode.
+ * @return {Number}
+ */
+ getSpeedVar: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getSpeedVar() : Particle Mode should be Gravity");
+ return this.modeA.speedVar;
+ },
+
+ /**
+ * speed variance of each particle setter. Only available in 'Gravity' mode.
+ * @param {Number} speedVar
+ */
+ setSpeedVar: function (speedVar) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setSpeedVar() : Particle Mode should be Gravity");
+ this.modeA.speedVar = speedVar;
+ },
+
+ /**
+ * Return tangential acceleration of each particle. Only available in 'Gravity' mode.
+ * @return {Number}
+ */
+ getTangentialAccel: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getTangentialAccel() : Particle Mode should be Gravity");
+ return this.modeA.tangentialAccel;
+ },
+
+ /**
+ * Tangential acceleration of each particle setter. Only available in 'Gravity' mode.
+ * @param {Number} tangentialAccel
+ */
+ setTangentialAccel: function (tangentialAccel) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setTangentialAccel() : Particle Mode should be Gravity");
+ this.modeA.tangentialAccel = tangentialAccel;
+ },
+
+ /**
+ * Return tangential acceleration variance of each particle. Only available in 'Gravity' mode.
+ * @return {Number}
+ */
+ getTangentialAccelVar: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getTangentialAccelVar() : Particle Mode should be Gravity");
+ return this.modeA.tangentialAccelVar;
+ },
+
+ /**
+ * tangential acceleration variance of each particle setter. Only available in 'Gravity' mode.
+ * @param {Number} tangentialAccelVar
+ */
+ setTangentialAccelVar: function (tangentialAccelVar) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setTangentialAccelVar() : Particle Mode should be Gravity");
+ this.modeA.tangentialAccelVar = tangentialAccelVar;
+ },
+
+ /**
+ * Return radial acceleration of each particle. Only available in 'Gravity' mode.
+ * @return {Number}
+ */
+ getRadialAccel: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getRadialAccel() : Particle Mode should be Gravity");
+ return this.modeA.radialAccel;
+ },
+
+ /**
+ * radial acceleration of each particle setter. Only available in 'Gravity' mode.
+ * @param {Number} radialAccel
+ */
+ setRadialAccel: function (radialAccel) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setRadialAccel() : Particle Mode should be Gravity");
+ this.modeA.radialAccel = radialAccel;
+ },
+
+ /**
+ * Return radial acceleration variance of each particle. Only available in 'Gravity' mode.
+ * @return {Number}
+ */
+ getRadialAccelVar: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getRadialAccelVar() : Particle Mode should be Gravity");
+ return this.modeA.radialAccelVar;
+ },
+
+ /**
+ * radial acceleration variance of each particle setter. Only available in 'Gravity' mode.
+ * @param {Number} radialAccelVar
+ */
+ setRadialAccelVar: function (radialAccelVar) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setRadialAccelVar() : Particle Mode should be Gravity");
+ this.modeA.radialAccelVar = radialAccelVar;
+ },
+
+ /**
+ * get the rotation of each particle to its direction Only available in 'Gravity' mode.
+ * @returns {boolean}
+ */
+ getRotationIsDir: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.getRotationIsDir() : Particle Mode should be Gravity");
+ return this.modeA.rotationIsDir;
+ },
+
+ /**
+ * set the rotation of each particle to its direction Only available in 'Gravity' mode.
+ * @param {boolean} t
+ */
+ setRotationIsDir: function (t) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_GRAVITY)
+ cc.log("cc.ParticleBatchNode.setRotationIsDir() : Particle Mode should be Gravity");
+ this.modeA.rotationIsDir = t;
+ },
+
+ // mode B
+ /**
+ * Return starting radius of the particles. Only available in 'Radius' mode.
+ * @return {Number}
+ */
+ getStartRadius: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.getStartRadius() : Particle Mode should be Radius");
+ return this.modeB.startRadius;
+ },
+
+ /**
+ * starting radius of the particles setter. Only available in 'Radius' mode.
+ * @param {Number} startRadius
+ */
+ setStartRadius: function (startRadius) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.setStartRadius() : Particle Mode should be Radius");
+ this.modeB.startRadius = startRadius;
+ },
+
+ /**
+ * Return starting radius variance of the particles. Only available in 'Radius' mode.
+ * @return {Number}
+ */
+ getStartRadiusVar: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.getStartRadiusVar() : Particle Mode should be Radius");
+ return this.modeB.startRadiusVar;
+ },
+
+ /**
+ * starting radius variance of the particles setter. Only available in 'Radius' mode.
+ * @param {Number} startRadiusVar
+ */
+ setStartRadiusVar: function (startRadiusVar) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.setStartRadiusVar() : Particle Mode should be Radius");
+ this.modeB.startRadiusVar = startRadiusVar;
+ },
+
+ /**
+ * Return ending radius of the particles. Only available in 'Radius' mode.
+ * @return {Number}
+ */
+ getEndRadius: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.getEndRadius() : Particle Mode should be Radius");
+ return this.modeB.endRadius;
+ },
+
+ /**
+ * ending radius of the particles setter. Only available in 'Radius' mode.
+ * @param {Number} endRadius
+ */
+ setEndRadius: function (endRadius) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.setEndRadius() : Particle Mode should be Radius");
+ this.modeB.endRadius = endRadius;
+ },
+
+ /**
+ * Return ending radius variance of the particles. Only available in 'Radius' mode.
+ * @return {Number}
+ */
+ getEndRadiusVar: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.getEndRadiusVar() : Particle Mode should be Radius");
+ return this.modeB.endRadiusVar;
+ },
+
+ /**
+ * ending radius variance of the particles setter. Only available in 'Radius' mode.
+ * @param endRadiusVar
+ */
+ setEndRadiusVar: function (endRadiusVar) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.setEndRadiusVar() : Particle Mode should be Radius");
+ this.modeB.endRadiusVar = endRadiusVar;
+ },
+
+ /**
+ * get Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
+ * @return {Number}
+ */
+ getRotatePerSecond: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.getRotatePerSecond() : Particle Mode should be Radius");
+ return this.modeB.rotatePerSecond;
+ },
+
+ /**
+ * set Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
+ * @param {Number} degrees
+ */
+ setRotatePerSecond: function (degrees) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.setRotatePerSecond() : Particle Mode should be Radius");
+ this.modeB.rotatePerSecond = degrees;
+ },
+
+ /**
+ * Return Variance in degrees for rotatePerSecond. Only available in 'Radius' mode.
+ * @return {Number}
+ */
+ getRotatePerSecondVar: function () {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.getRotatePerSecondVar() : Particle Mode should be Radius");
+ return this.modeB.rotatePerSecondVar;
+ },
+
+ /**
+ * Variance in degrees for rotatePerSecond setter. Only available in 'Radius' mode.
+ * @param degrees
+ */
+ setRotatePerSecondVar: function (degrees) {
+ if (this.emitterMode !== cc.ParticleSystem.MODE_RADIUS)
+ cc.log("cc.ParticleBatchNode.setRotatePerSecondVar() : Particle Mode should be Radius");
+ this.modeB.rotatePerSecondVar = degrees;
+ },
+ //////////////////////////////////////////////////////////////////////////
+
+ //don't use a transform matrix, this is faster
+ setScale: function (scale, scaleY) {
+ this._transformSystemDirty = true;
+ cc.Node.prototype.setScale.call(this, scale, scaleY);
+ },
+
+ setRotation: function (newRotation) {
+ this._transformSystemDirty = true;
+ cc.Node.prototype.setRotation.call(this, newRotation);
+ },
+
+ setScaleX: function (newScaleX) {
+ this._transformSystemDirty = true;
+ cc.Node.prototype.setScaleX.call(this, newScaleX);
+ },
+
+ setScaleY: function (newScaleY) {
+ this._transformSystemDirty = true;
+ cc.Node.prototype.setScaleY.call(this, newScaleY);
+ },
+
+ /**
+ * get start size in pixels of each particle
+ * @return {Number}
+ */
+ getStartSize: function () {
+ return this.startSize;
+ },
+
+ /**
+ * set start size in pixels of each particle
+ * @param {Number} startSize
+ */
+ setStartSize: function (startSize) {
+ this.startSize = startSize;
+ },
+
+ /**
+ * get size variance in pixels of each particle
+ * @return {Number}
+ */
+ getStartSizeVar: function () {
+ return this.startSizeVar;
+ },
+
+ /**
+ * set size variance in pixels of each particle
+ * @param {Number} startSizeVar
+ */
+ setStartSizeVar: function (startSizeVar) {
+ this.startSizeVar = startSizeVar;
+ },
+
+ /**
+ * get end size in pixels of each particle
+ * @return {Number}
+ */
+ getEndSize: function () {
+ return this.endSize;
+ },
+
+ /**
+ * set end size in pixels of each particle
+ * @param endSize
+ */
+ setEndSize: function (endSize) {
+ this.endSize = endSize;
+ },
+
+ /**
+ * get end size variance in pixels of each particle
+ * @return {Number}
+ */
+ getEndSizeVar: function () {
+ return this.endSizeVar;
+ },
+
+ /**
+ * set end size variance in pixels of each particle
+ * @param {Number} endSizeVar
+ */
+ setEndSizeVar: function (endSizeVar) {
+ this.endSizeVar = endSizeVar;
+ },
+
+ /**
+ * set start color of each particle
+ * @return {cc.Color}
+ */
+ getStartColor: function () {
+ return cc.color(this._startColor.r, this._startColor.g, this._startColor.b, this._startColor.a);
+ },
+
+ /**
+ * get start color of each particle
+ * @param {cc.Color} startColor
+ */
+ setStartColor: function (startColor) {
+ this._startColor.r = startColor.r;
+ this._startColor.g = startColor.g;
+ this._startColor.b = startColor.b;
+ this._startColor.a = startColor.a;
+ },
+
+ /**
+ * get start color variance of each particle
+ * @return {cc.Color}
+ */
+ getStartColorVar: function () {
+ return cc.color(this._startColorVar.r, this._startColorVar.g, this._startColorVar.b, this._startColorVar.a);
+ },
+
+ /**
+ * set start color variance of each particle
+ * @param {cc.Color} startColorVar
+ */
+ setStartColorVar: function (startColorVar) {
+ this._startColorVar.r = startColorVar.r;
+ this._startColorVar.g = startColorVar.g;
+ this._startColorVar.b = startColorVar.b;
+ this._startColorVar.a = startColorVar.a;
+ },
+
+ /**
+ * get end color and end color variation of each particle
+ * @return {cc.Color}
+ */
+ getEndColor: function () {
+ return cc.color(this._endColor.r, this._endColor.g, this._endColor.b, this._endColor.a);
+ },
+
+ /**
+ * set end color and end color variation of each particle
+ * @param {cc.Color} endColor
+ */
+ setEndColor: function (endColor) {
+ this._endColor.r = endColor.r;
+ this._endColor.g = endColor.g;
+ this._endColor.b = endColor.b;
+ this._endColor.a = endColor.a;
+ },
+
+ /**
+ * get end color variance of each particle
+ * @return {cc.Color}
+ */
+ getEndColorVar: function () {
+ return cc.color(this._endColorVar.r, this._endColorVar.g, this._endColorVar.b, this._endColorVar.a);
+ },
+
+ /**
+ * set end color variance of each particle
+ * @param {cc.Color} endColorVar
+ */
+ setEndColorVar: function (endColorVar) {
+ this._endColorVar.r = endColorVar.r;
+ this._endColorVar.g = endColorVar.g;
+ this._endColorVar.b = endColorVar.b;
+ this._endColorVar.a = endColorVar.a;
+ },
+
+ /**
+ * get initial angle of each particle
+ * @return {Number}
+ */
+ getStartSpin: function () {
+ return this.startSpin;
+ },
+
+ /**
+ * set initial angle of each particle
+ * @param {Number} startSpin
+ */
+ setStartSpin: function (startSpin) {
+ this.startSpin = startSpin;
+ },
+
+ /**
+ * get initial angle variance of each particle
+ * @return {Number}
+ */
+ getStartSpinVar: function () {
+ return this.startSpinVar;
+ },
+
+ /**
+ * set initial angle variance of each particle
+ * @param {Number} startSpinVar
+ */
+ setStartSpinVar: function (startSpinVar) {
+ this.startSpinVar = startSpinVar;
+ },
+
+ /**
+ * get end angle of each particle
+ * @return {Number}
+ */
+ getEndSpin: function () {
+ return this.endSpin;
+ },
+
+ /**
+ * set end angle of each particle
+ * @param {Number} endSpin
+ */
+ setEndSpin: function (endSpin) {
+ this.endSpin = endSpin;
+ },
+
+ /**
+ * get end angle variance of each particle
+ * @return {Number}
+ */
+ getEndSpinVar: function () {
+ return this.endSpinVar;
+ },
+
+ /**
+ * set end angle variance of each particle
+ * @param {Number} endSpinVar
+ */
+ setEndSpinVar: function (endSpinVar) {
+ this.endSpinVar = endSpinVar;
+ },
+
+ /**
+ * get emission rate of the particles
+ * @return {Number}
+ */
+ getEmissionRate: function () {
+ return this.emissionRate;
+ },
+
+ /**
+ * set emission rate of the particles
+ * @param {Number} emissionRate
+ */
+ setEmissionRate: function (emissionRate) {
+ this.emissionRate = emissionRate;
+ },
+
+ /**
+ * get maximum particles of the system
+ * @return {Number}
+ */
+ getTotalParticles: function () {
+ return this._totalParticles;
+ },
+
+ /**
+ * set maximum particles of the system
+ * @param {Number} tp totalParticles
+ */
+ setTotalParticles: function (tp) {
+ this._renderCmd.setTotalParticles(tp);
+ },
+
+ /**
+ * get Texture of Particle System
+ * @return {cc.Texture2D}
+ */
+ getTexture: function () {
+ return this._texture;
+ },
+
+ /**
+ * set Texture of Particle System
+ * @param {cc.Texture2D } texture
+ */
+ setTexture: function (texture) {
+ if (!texture)
+ return;
+
+ if (texture.isLoaded()) {
+ this.setTextureWithRect(texture, cc.rect(0, 0, texture.width, texture.height));
+ } else {
+ this._textureLoaded = false;
+ texture.addEventListener("load", function (sender) {
+ this._textureLoaded = true;
+ this.setTextureWithRect(sender, cc.rect(0, 0, sender.width, sender.height));
+ }, this);
+ }
+ },
+
+ /** conforms to CocosNodeTexture protocol */
+ /**
+ * get BlendFunc of Particle System
+ * @return {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ return this._blendFunc;
+ },
+
+ /**
+ * set BlendFunc of Particle System
+ * @param {Number} src
+ * @param {Number} dst
+ */
+ setBlendFunc: function (src, dst) {
+ if (dst === undefined) {
+ if (this._blendFunc !== src) {
+ this._blendFunc = src;
+ this._updateBlendFunc();
+ }
+ } else {
+ if (this._blendFunc.src !== src || this._blendFunc.dst !== dst) {
+ this._blendFunc = {src: src, dst: dst};
+ this._updateBlendFunc();
+ }
+ }
+ },
+
+ /**
+ * does the alpha value modify color getter
+ * @return {Boolean}
+ */
+ isOpacityModifyRGB: function () {
+ return this._opacityModifyRGB;
+ },
+
+ /**
+ * does the alpha value modify color setter
+ * @param newValue
+ */
+ setOpacityModifyRGB: function (newValue) {
+ this._opacityModifyRGB = newValue;
+ },
+
+ /**
+ * whether or not the particles are using blend additive.
+ * If enabled, the following blending function will be used.
+ *
+ * @return {Boolean}
+ * @example
+ * source blend function = GL_SRC_ALPHA;
+ * dest blend function = GL_ONE;
+ */
+ isBlendAdditive: function () {
+ return (( this._blendFunc.src === cc.SRC_ALPHA && this._blendFunc.dst === cc.ONE) || (this._blendFunc.src === cc.ONE && this._blendFunc.dst === cc.ONE));
+ },
+
+ /**
+ * whether or not the particles are using blend additive.
+ * If enabled, the following blending function will be used.
+ *
+ * @param {Boolean} isBlendAdditive
+ */
+ setBlendAdditive: function (isBlendAdditive) {
+ var locBlendFunc = this._blendFunc;
+ if (isBlendAdditive) {
+ locBlendFunc.src = cc.SRC_ALPHA;
+ locBlendFunc.dst = cc.ONE;
+ } else {
+ this._renderCmd._setBlendAdditive();
+ }
+ },
+
+ /**
+ * get particles movement type: Free or Grouped
+ * @return {Number}
+ */
+ getPositionType: function () {
+ return this.positionType;
+ },
+
+ /**
+ * set particles movement type: Free or Grouped
+ * @param {Number} positionType
+ */
+ setPositionType: function (positionType) {
+ this.positionType = positionType;
+ },
+
+ /**
+ * return whether or not the node will be auto-removed when it has no particles left.
+ * By default it is false.
+ *
+ * @return {Boolean}
+ */
+ isAutoRemoveOnFinish: function () {
+ return this.autoRemoveOnFinish;
+ },
+
+ /**
+ * set whether or not the node will be auto-removed when it has no particles left.
+ * By default it is false.
+ *
+ * @param {Boolean} isAutoRemoveOnFinish
+ */
+ setAutoRemoveOnFinish: function (isAutoRemoveOnFinish) {
+ this.autoRemoveOnFinish = isAutoRemoveOnFinish;
+ },
+
+ /**
+ * return kind of emitter modes
+ * @return {Number}
+ */
+ getEmitterMode: function () {
+ return this.emitterMode;
+ },
+
+ /**
+ * Switch between different kind of emitter modes:
+ * - CCParticleSystem.MODE_GRAVITY: uses gravity, speed, radial and tangential acceleration
+ * - CCParticleSystem.MODE_RADIUS: uses radius movement + rotation
+ *
+ * @param {Number} emitterMode
+ */
+ setEmitterMode: function (emitterMode) {
+ this.emitterMode = emitterMode;
+ },
+
+ /**
+ * initializes a cc.ParticleSystem
+ */
+ init: function () {
+ return this.initWithTotalParticles(150);
+ },
+
+ /**
+ *
+ * initializes a CCParticleSystem from a plist file.
+ * This plist files can be creted manually or with Particle Designer:
+ * http://particledesigner.71squared.com/
+ *
+ * @param {String} plistFile
+ * @return {boolean}
+ */
+ initWithFile: function (plistFile) {
+ this._plistFile = plistFile;
+ var dict = cc.loader.getRes(plistFile);
+ if (!dict) {
+ cc.log("cc.ParticleSystem.initWithFile(): Particles: file not found");
+ return false;
+ }
+
+ // XXX compute path from a path, should define a function somewhere to do it
+ return this.initWithDictionary(dict, "");
+ },
+
+ /**
+ * return bounding box of particle system in world space
+ * @return {cc.Rect}
+ */
+ getBoundingBoxToWorld: function () {
+ return cc.rect(0, 0, cc._canvas.width, cc._canvas.height);
+ },
+
+ /**
+ * initializes a particle system from a NSDictionary and the path from where to load the png
+ * @param {object} dictionary
+ * @param {String} dirname
+ * @return {Boolean}
+ */
+ initWithDictionary: function (dictionary, dirname) {
+ var ret = false;
+ var buffer = null;
+ var image = null;
+ var locValueForKey = this._valueForKey;
+
+ var maxParticles = parseInt(locValueForKey("maxParticles", dictionary));
+ // self, not super
+ if (this.initWithTotalParticles(maxParticles)) {
+ // angle
+ this.angle = parseFloat(locValueForKey("angle", dictionary));
+ this.angleVar = parseFloat(locValueForKey("angleVariance", dictionary));
+
+ // duration
+ this.duration = parseFloat(locValueForKey("duration", dictionary));
+
+ // blend function
+ this._blendFunc.src = parseInt(locValueForKey("blendFuncSource", dictionary));
+ this._blendFunc.dst = parseInt(locValueForKey("blendFuncDestination", dictionary));
+
+ // color
+ var locStartColor = this._startColor;
+ locStartColor.r = parseFloat(locValueForKey("startColorRed", dictionary)) * 255;
+ locStartColor.g = parseFloat(locValueForKey("startColorGreen", dictionary)) * 255;
+ locStartColor.b = parseFloat(locValueForKey("startColorBlue", dictionary)) * 255;
+ locStartColor.a = parseFloat(locValueForKey("startColorAlpha", dictionary)) * 255;
+
+ var locStartColorVar = this._startColorVar;
+ locStartColorVar.r = parseFloat(locValueForKey("startColorVarianceRed", dictionary)) * 255;
+ locStartColorVar.g = parseFloat(locValueForKey("startColorVarianceGreen", dictionary)) * 255;
+ locStartColorVar.b = parseFloat(locValueForKey("startColorVarianceBlue", dictionary)) * 255;
+ locStartColorVar.a = parseFloat(locValueForKey("startColorVarianceAlpha", dictionary)) * 255;
+
+ var locEndColor = this._endColor;
+ locEndColor.r = parseFloat(locValueForKey("finishColorRed", dictionary)) * 255;
+ locEndColor.g = parseFloat(locValueForKey("finishColorGreen", dictionary)) * 255;
+ locEndColor.b = parseFloat(locValueForKey("finishColorBlue", dictionary)) * 255;
+ locEndColor.a = parseFloat(locValueForKey("finishColorAlpha", dictionary)) * 255;
+
+ var locEndColorVar = this._endColorVar;
+ locEndColorVar.r = parseFloat(locValueForKey("finishColorVarianceRed", dictionary)) * 255;
+ locEndColorVar.g = parseFloat(locValueForKey("finishColorVarianceGreen", dictionary)) * 255;
+ locEndColorVar.b = parseFloat(locValueForKey("finishColorVarianceBlue", dictionary)) * 255;
+ locEndColorVar.a = parseFloat(locValueForKey("finishColorVarianceAlpha", dictionary)) * 255;
+
+ // particle size
+ this.startSize = parseFloat(locValueForKey("startParticleSize", dictionary));
+ this.startSizeVar = parseFloat(locValueForKey("startParticleSizeVariance", dictionary));
+ this.endSize = parseFloat(locValueForKey("finishParticleSize", dictionary));
+ this.endSizeVar = parseFloat(locValueForKey("finishParticleSizeVariance", dictionary));
+
+ // position
+ this.setPosition(parseFloat(locValueForKey("sourcePositionx", dictionary)),
+ parseFloat(locValueForKey("sourcePositiony", dictionary)));
+ this._posVar.x = parseFloat(locValueForKey("sourcePositionVariancex", dictionary));
+ this._posVar.y = parseFloat(locValueForKey("sourcePositionVariancey", dictionary));
+
+ // Spinning
+ this.startSpin = parseFloat(locValueForKey("rotationStart", dictionary));
+ this.startSpinVar = parseFloat(locValueForKey("rotationStartVariance", dictionary));
+ this.endSpin = parseFloat(locValueForKey("rotationEnd", dictionary));
+ this.endSpinVar = parseFloat(locValueForKey("rotationEndVariance", dictionary));
+
+ this.emitterMode = parseInt(locValueForKey("emitterType", dictionary));
+
+ // Mode A: Gravity + tangential accel + radial accel
+ if (this.emitterMode === cc.ParticleSystem.MODE_GRAVITY) {
+ var locModeA = this.modeA;
+ // gravity
+ locModeA.gravity.x = parseFloat(locValueForKey("gravityx", dictionary));
+ locModeA.gravity.y = parseFloat(locValueForKey("gravityy", dictionary));
+
+ // speed
+ locModeA.speed = parseFloat(locValueForKey("speed", dictionary));
+ locModeA.speedVar = parseFloat(locValueForKey("speedVariance", dictionary));
+
+ // radial acceleration
+ var pszTmp = locValueForKey("radialAcceleration", dictionary);
+ locModeA.radialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
+
+ pszTmp = locValueForKey("radialAccelVariance", dictionary);
+ locModeA.radialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
+
+ // tangential acceleration
+ pszTmp = locValueForKey("tangentialAcceleration", dictionary);
+ locModeA.tangentialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
+
+ pszTmp = locValueForKey("tangentialAccelVariance", dictionary);
+ locModeA.tangentialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
+
+ // rotation is dir
+ var locRotationIsDir = locValueForKey("rotationIsDir", dictionary);
+ if (locRotationIsDir !== null) {
+ locRotationIsDir = locRotationIsDir.toString().toLowerCase();
+ locModeA.rotationIsDir = (locRotationIsDir === "true" || locRotationIsDir === "1");
+ }
+ else {
+ locModeA.rotationIsDir = false;
+ }
+ } else if (this.emitterMode === cc.ParticleSystem.MODE_RADIUS) {
+ // or Mode B: radius movement
+ var locModeB = this.modeB;
+ locModeB.startRadius = parseFloat(locValueForKey("maxRadius", dictionary));
+ locModeB.startRadiusVar = parseFloat(locValueForKey("maxRadiusVariance", dictionary));
+ locModeB.endRadius = parseFloat(locValueForKey("minRadius", dictionary));
+ locModeB.endRadiusVar = 0;
+ locModeB.rotatePerSecond = parseFloat(locValueForKey("rotatePerSecond", dictionary));
+ locModeB.rotatePerSecondVar = parseFloat(locValueForKey("rotatePerSecondVariance", dictionary));
+ } else {
+ cc.log("cc.ParticleSystem.initWithDictionary(): Invalid emitterType in config file");
+ return false;
+ }
+
+ // life span
+ this.life = parseFloat(locValueForKey("particleLifespan", dictionary));
+ this.lifeVar = parseFloat(locValueForKey("particleLifespanVariance", dictionary));
+
+ // emission Rate
+ this.emissionRate = this._totalParticles / this.life;
+
+ //don't get the internal texture if a batchNode is used
+ if (!this._batchNode) {
+ // Set a compatible default for the alpha transfer
+ this._opacityModifyRGB = false;
+
+ // texture
+ // Try to get the texture from the cache
+ var textureName = locValueForKey("textureFileName", dictionary);
+ var imgPath = cc.path.changeBasename(this._plistFile, textureName);
+ var tex = cc.textureCache.getTextureForKey(imgPath);
+
+ if (tex) {
+ this.setTexture(tex);
+ } else {
+ var textureData = locValueForKey("textureImageData", dictionary);
+
+ if (!textureData || textureData.length === 0) {
+ tex = cc.textureCache.addImage(imgPath);
+ if (!tex)
+ return false;
+ this.setTexture(tex);
+ } else {
+ buffer = cc.unzipBase64AsArray(textureData, 1);
+ if (!buffer) {
+ cc.log("cc.ParticleSystem: error decoding or ungzipping textureImageData");
+ return false;
+ }
+
+ var imageFormat = cc.getImageFormatByData(buffer);
+
+ if (imageFormat !== cc.FMT_TIFF && imageFormat !== cc.FMT_PNG) {
+ cc.log("cc.ParticleSystem: unknown image format with Data");
+ return false;
+ }
+
+ var canvasObj = document.createElement("canvas");
+ if (imageFormat === cc.FMT_PNG) {
+ var myPngObj = new cc.PNGReader(buffer);
+ myPngObj.render(canvasObj);
+ } else {
+ var myTIFFObj = cc.tiffReader;
+ myTIFFObj.parseTIFF(buffer, canvasObj);
+ }
+
+ cc.textureCache.cacheImage(imgPath, canvasObj);
+
+ var addTexture = cc.textureCache.getTextureForKey(imgPath);
+ if (!addTexture)
+ cc.log("cc.ParticleSystem.initWithDictionary() : error loading the texture");
+ this.setTexture(addTexture);
+ }
+ }
+ }
+ ret = true;
+ }
+ return ret;
+ },
+
+ /**
+ * Initializes a system with a fixed number of particles
+ * @param {Number} numberOfParticles
+ * @return {Boolean}
+ */
+ initWithTotalParticles: function (numberOfParticles) {
+ this._totalParticles = numberOfParticles;
+
+ var i, locParticles = this._particles;
+ locParticles.length = 0;
+ for (i = 0; i < numberOfParticles; i++) {
+ locParticles[i] = new cc.Particle();
+ }
+
+ if (!locParticles) {
+ cc.log("Particle system: not enough memory");
+ return false;
+ }
+ this._allocatedParticles = numberOfParticles;
+
+ if (this._batchNode)
+ for (i = 0; i < this._totalParticles; i++)
+ locParticles[i].atlasIndex = i;
+
+ // default, active
+ this._isActive = true;
+
+ // default blend function
+ this._blendFunc.src = cc.BLEND_SRC;
+ this._blendFunc.dst = cc.BLEND_DST;
+
+ // default movement type;
+ this.positionType = cc.ParticleSystem.TYPE_FREE;
+
+ // by default be in mode A:
+ this.emitterMode = cc.ParticleSystem.MODE_GRAVITY;
+
+ // default: modulate
+ // XXX: not used
+ // colorModulate = YES;
+ this.autoRemoveOnFinish = false;
+
+ //for batchNode
+ this._transformSystemDirty = false;
+
+ // udpate after action in run!
+ this.scheduleUpdateWithPriority(1);
+ this._renderCmd._initWithTotalParticles(numberOfParticles);
+ return true;
+ },
+
+ /**
+ * Unschedules the "update" method.
+ * @function
+ * @see scheduleUpdate();
+ */
+ destroyParticleSystem: function () {
+ this.unscheduleUpdate();
+ },
+
+ /**
+ * Add a particle to the emitter
+ * @return {Boolean}
+ */
+ addParticle: function () {
+ if (this.isFull())
+ return false;
+
+ var particle = this._renderCmd.addParticle();
+ this.initParticle(particle);
+ ++this.particleCount;
+ return true;
+ },
+
+ /**
+ * Initializes a particle
+ * @param {cc.Particle} particle
+ */
+ initParticle: function (particle) {
+ var locRandomMinus11 = cc.randomMinus1To1;
+ // timeToLive
+ // no negative life. prevent division by 0
+ particle.timeToLive = this.life + this.lifeVar * locRandomMinus11();
+ particle.timeToLive = Math.max(0, particle.timeToLive);
+
+ // position
+ particle.pos.x = this._sourcePosition.x + this._posVar.x * locRandomMinus11();
+ particle.pos.y = this._sourcePosition.y + this._posVar.y * locRandomMinus11();
+
+ // Color
+ var start, end;
+ var locStartColor = this._startColor, locStartColorVar = this._startColorVar;
+ var locEndColor = this._endColor, locEndColorVar = this._endColorVar;
+ start = {
+ r: cc.clampf(locStartColor.r + locStartColorVar.r * locRandomMinus11(), 0, 255),
+ g: cc.clampf(locStartColor.g + locStartColorVar.g * locRandomMinus11(), 0, 255),
+ b: cc.clampf(locStartColor.b + locStartColorVar.b * locRandomMinus11(), 0, 255),
+ a: cc.clampf(locStartColor.a + locStartColorVar.a * locRandomMinus11(), 0, 255)
+ };
+ end = {
+ r: cc.clampf(locEndColor.r + locEndColorVar.r * locRandomMinus11(), 0, 255),
+ g: cc.clampf(locEndColor.g + locEndColorVar.g * locRandomMinus11(), 0, 255),
+ b: cc.clampf(locEndColor.b + locEndColorVar.b * locRandomMinus11(), 0, 255),
+ a: cc.clampf(locEndColor.a + locEndColorVar.a * locRandomMinus11(), 0, 255)
+ };
+
+ particle.color = start;
+ var locParticleDeltaColor = particle.deltaColor, locParticleTimeToLive = particle.timeToLive;
+ locParticleDeltaColor.r = (end.r - start.r) / locParticleTimeToLive;
+ locParticleDeltaColor.g = (end.g - start.g) / locParticleTimeToLive;
+ locParticleDeltaColor.b = (end.b - start.b) / locParticleTimeToLive;
+ locParticleDeltaColor.a = (end.a - start.a) / locParticleTimeToLive;
+
+ // size
+ var startS = this.startSize + this.startSizeVar * locRandomMinus11();
+ startS = Math.max(0, startS); // No negative value
+
+ particle.size = startS;
+ if (this.endSize === cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE) {
+ particle.deltaSize = 0;
+ } else {
+ var endS = this.endSize + this.endSizeVar * locRandomMinus11();
+ endS = Math.max(0, endS); // No negative values
+ particle.deltaSize = (endS - startS) / locParticleTimeToLive;
+ }
+
+ // rotation
+ var startA = this.startSpin + this.startSpinVar * locRandomMinus11();
+ var endA = this.endSpin + this.endSpinVar * locRandomMinus11();
+ particle.rotation = startA;
+ particle.deltaRotation = (endA - startA) / locParticleTimeToLive;
+
+ // position
+ if (this.positionType === cc.ParticleSystem.TYPE_FREE)
+ particle.startPos = this.convertToWorldSpace(this._pointZeroForParticle);
+ else if (this.positionType === cc.ParticleSystem.TYPE_RELATIVE) {
+ particle.startPos.x = this._position.x;
+ particle.startPos.y = this._position.y;
+ }
+
+ // direction
+ var a = cc.degreesToRadians(this.angle + this.angleVar * locRandomMinus11());
+
+ // Mode Gravity: A
+ if (this.emitterMode === cc.ParticleSystem.MODE_GRAVITY) {
+ var locModeA = this.modeA, locParticleModeA = particle.modeA;
+ var s = locModeA.speed + locModeA.speedVar * locRandomMinus11();
+
+ // direction
+ locParticleModeA.dir.x = Math.cos(a);
+ locParticleModeA.dir.y = Math.sin(a);
+ cc.pMultIn(locParticleModeA.dir, s);
+
+ // radial accel
+ locParticleModeA.radialAccel = locModeA.radialAccel + locModeA.radialAccelVar * locRandomMinus11();
+
+ // tangential accel
+ locParticleModeA.tangentialAccel = locModeA.tangentialAccel + locModeA.tangentialAccelVar * locRandomMinus11();
+
+ // rotation is dir
+ if (locModeA.rotationIsDir)
+ particle.rotation = -cc.radiansToDegrees(cc.pToAngle(locParticleModeA.dir));
+ } else {
+ // Mode Radius: B
+ var locModeB = this.modeB, locParitlceModeB = particle.modeB;
+
+ // Set the default diameter of the particle from the source position
+ var startRadius = locModeB.startRadius + locModeB.startRadiusVar * locRandomMinus11();
+ var endRadius = locModeB.endRadius + locModeB.endRadiusVar * locRandomMinus11();
+
+ locParitlceModeB.radius = startRadius;
+ locParitlceModeB.deltaRadius = (locModeB.endRadius === cc.ParticleSystem.START_RADIUS_EQUAL_TO_END_RADIUS) ? 0 : (endRadius - startRadius) / locParticleTimeToLive;
+
+ locParitlceModeB.angle = a;
+ locParitlceModeB.degreesPerSecond = cc.degreesToRadians(locModeB.rotatePerSecond + locModeB.rotatePerSecondVar * locRandomMinus11());
+ }
+ },
+
+ /**
+ * stop emitting particles. Running particles will continue to run until they die
+ */
+ stopSystem: function () {
+ this._isActive = false;
+ this._elapsed = this.duration;
+ this._emitCounter = 0;
+ },
+
+ /**
+ * Kill all living particles.
+ */
+ resetSystem: function () {
+ this._isActive = true;
+ this._elapsed = 0;
+ var locParticles = this._particles;
+ for (this._particleIdx = 0; this._particleIdx < this.particleCount; ++this._particleIdx)
+ locParticles[this._particleIdx].timeToLive = 0;
+ },
+
+ /**
+ * whether or not the system is full
+ * @return {Boolean}
+ */
+ isFull: function () {
+ return (this.particleCount >= this._totalParticles);
+ },
+
+ /**
+ * should be overridden by subclasses
+ * @param {cc.Particle} particle
+ * @param {cc.Point} newPosition
+ */
+ updateQuadWithParticle: function (particle, newPosition) {
+ this._renderCmd.updateQuadWithParticle(particle, newPosition);
+ },
+
+ /**
+ * should be overridden by subclasses
+ */
+ postStep: function () {
+ this._renderCmd.postStep();
+ },
+
+ /**
+ * update emitter's status
+ * @override
+ * @param {Number} dt delta time
+ */
+ update:function (dt) {
+ if (this._isActive && this.emissionRate) {
+ var rate = 1.0 / this.emissionRate;
+ //issue #1201, prevent bursts of particles, due to too high emitCounter
+ if (this.particleCount < this._totalParticles)
+ this._emitCounter += dt;
+
+ while ((this.particleCount < this._totalParticles) && (this._emitCounter > rate)) {
+ this.addParticle();
+ this._emitCounter -= rate;
+ }
+
+ this._elapsed += dt;
+ if (this.duration !== -1 && this.duration < this._elapsed)
+ this.stopSystem();
+ }
+ this._particleIdx = 0;
+
+ var currentPosition = cc.Particle.TemporaryPoints[0];
+ if (this.positionType === cc.ParticleSystem.TYPE_FREE) {
+ cc.pIn(currentPosition, this.convertToWorldSpace(this._pointZeroForParticle));
+ } else if (this.positionType === cc.ParticleSystem.TYPE_RELATIVE) {
+ currentPosition.x = this._position.x;
+ currentPosition.y = this._position.y;
+ }
+
+ if (this._visible) {
+ // Used to reduce memory allocation / creation within the loop
+ var tpa = cc.Particle.TemporaryPoints[1],
+ tpb = cc.Particle.TemporaryPoints[2],
+ tpc = cc.Particle.TemporaryPoints[3];
+
+ var locParticles = this._particles;
+ while (this._particleIdx < this.particleCount) {
+
+ // Reset the working particles
+ cc.pZeroIn(tpa);
+ cc.pZeroIn(tpb);
+ cc.pZeroIn(tpc);
+
+ var selParticle = locParticles[this._particleIdx];
+
+ // life
+ selParticle.timeToLive -= dt;
+
+ if (selParticle.timeToLive > 0) {
+ // Mode A: gravity, direction, tangential accel & radial accel
+ if (this.emitterMode === cc.ParticleSystem.MODE_GRAVITY) {
+
+ var tmp = tpc, radial = tpa, tangential = tpb;
+
+ // radial acceleration
+ if (selParticle.pos.x || selParticle.pos.y) {
+ cc.pIn(radial, selParticle.pos);
+ cc.pNormalizeIn(radial);
+ } else {
+ cc.pZeroIn(radial);
+ }
+
+ cc.pIn(tangential, radial);
+ cc.pMultIn(radial, selParticle.modeA.radialAccel);
+
+ // tangential acceleration
+ var newy = tangential.x;
+ tangential.x = -tangential.y;
+ tangential.y = newy;
+
+ cc.pMultIn(tangential, selParticle.modeA.tangentialAccel);
+
+ cc.pIn(tmp, radial);
+ cc.pAddIn(tmp, tangential);
+ cc.pAddIn(tmp, this.modeA.gravity);
+ cc.pMultIn(tmp, dt);
+ cc.pAddIn(selParticle.modeA.dir, tmp);
+
+
+ cc.pIn(tmp, selParticle.modeA.dir);
+ cc.pMultIn(tmp, dt);
+ cc.pAddIn(selParticle.pos, tmp);
+ } else {
+ // Mode B: radius movement
+ var selModeB = selParticle.modeB;
+ // Update the angle and radius of the particle.
+ selModeB.angle += selModeB.degreesPerSecond * dt;
+ selModeB.radius += selModeB.deltaRadius * dt;
+
+ selParticle.pos.x = -Math.cos(selModeB.angle) * selModeB.radius;
+ selParticle.pos.y = -Math.sin(selModeB.angle) * selModeB.radius;
+ }
+
+ // color
+ this._renderCmd._updateDeltaColor(selParticle, dt);
+
+ // size
+ selParticle.size += (selParticle.deltaSize * dt);
+ selParticle.size = Math.max(0, selParticle.size);
+
+ // angle
+ selParticle.rotation += (selParticle.deltaRotation * dt);
+
+ //
+ // update values in quad
+ //
+ var newPos = tpa;
+ if (this.positionType === cc.ParticleSystem.TYPE_FREE || this.positionType === cc.ParticleSystem.TYPE_RELATIVE) {
+ var diff = tpb;
+ cc.pIn(diff, currentPosition);
+ cc.pSubIn(diff, selParticle.startPos);
+
+ cc.pIn(newPos, selParticle.pos);
+ cc.pSubIn(newPos, diff);
+ } else {
+ cc.pIn(newPos, selParticle.pos);
+ }
+
+ // translate newPos to correct position, since matrix transform isn't performed in batchnode
+ // don't update the particle with the new position information, it will interfere with the radius and tangential calculations
+ if (this._batchNode) {
+ newPos.x += this._position.x;
+ newPos.y += this._position.y;
+ }
+ this._renderCmd.updateParticlePosition(selParticle, newPos);
+
+ // update particle counter
+ ++this._particleIdx;
+ } else {
+ // life < 0
+ var currentIndex = selParticle.atlasIndex;
+ if (this._particleIdx !== this.particleCount - 1) {
+ var deadParticle = locParticles[this._particleIdx];
+ locParticles[this._particleIdx] = locParticles[this.particleCount - 1];
+ locParticles[this.particleCount - 1] = deadParticle;
+ }
+ if (this._batchNode) {
+ //disable the switched particle
+ this._batchNode.disableParticle(this.atlasIndex + currentIndex);
+ //switch indexes
+ locParticles[this.particleCount - 1].atlasIndex = currentIndex;
+ }
+
+ --this.particleCount;
+ if (this.particleCount === 0 && this.autoRemoveOnFinish) {
+ this.unscheduleUpdate();
+ this._parent.removeChild(this, true);
+ return;
+ }
+ }
+ }
+ this._transformSystemDirty = false;
+ }
+
+ if (!this._batchNode)
+ this.postStep();
+ },
+
+ /**
+ * update emitter's status (dt = 0)
+ */
+ updateWithNoTime: function () {
+ this.update(0);
+ },
+
+ //
+ // return the string found by key in dict.
+ // @param {string} key
+ // @param {object} dict
+ // @return {String} "" if not found; return the string if found.
+ // @private
+ //
+ _valueForKey: function (key, dict) {
+ if (dict) {
+ var pString = dict[key];
+ return pString != null ? pString : "";
+ }
+ return "";
+ },
+
+ _updateBlendFunc: function () {
+ if (this._batchNode) {
+ cc.log("Can't change blending functions when the particle is being batched");
+ return;
+ }
+
+ var locTexture = this._texture;
+ if (locTexture && locTexture instanceof cc.Texture2D) {
+ this._opacityModifyRGB = false;
+ var locBlendFunc = this._blendFunc;
+ if (locBlendFunc.src === cc.BLEND_SRC && locBlendFunc.dst === cc.BLEND_DST) {
+ if (locTexture.hasPremultipliedAlpha()) {
+ this._opacityModifyRGB = true;
+ } else {
+ locBlendFunc.src = cc.SRC_ALPHA;
+ locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
+ }
+ }
+ }
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ *
+ * @return {cc.ParticleSystem}
+ */
+ clone: function () {
+ var retParticle = new cc.ParticleSystem();
+
+ // self, not super
+ if (retParticle.initWithTotalParticles(this.getTotalParticles())) {
+ // angle
+ retParticle.setAngle(this.getAngle());
+ retParticle.setAngleVar(this.getAngleVar());
+
+ // duration
+ retParticle.setDuration(this.getDuration());
+
+ // blend function
+ var blend = this.getBlendFunc();
+ retParticle.setBlendFunc(blend.src, blend.dst);
+
+ // color
+ retParticle.setStartColor(this.getStartColor());
+
+ retParticle.setStartColorVar(this.getStartColorVar());
+
+ retParticle.setEndColor(this.getEndColor());
+
+ retParticle.setEndColorVar(this.getEndColorVar());
+
+ // this size
+ retParticle.setStartSize(this.getStartSize());
+ retParticle.setStartSizeVar(this.getStartSizeVar());
+ retParticle.setEndSize(this.getEndSize());
+ retParticle.setEndSizeVar(this.getEndSizeVar());
+
+ // position
+ retParticle.setPosition(cc.p(this.x, this.y));
+ retParticle.setPosVar(cc.p(this.getPosVar().x, this.getPosVar().y));
+
+ retParticle.setPositionType(this.getPositionType());
+
+ // Spinning
+ retParticle.setStartSpin(this.getStartSpin() || 0);
+ retParticle.setStartSpinVar(this.getStartSpinVar() || 0);
+ retParticle.setEndSpin(this.getEndSpin() || 0);
+ retParticle.setEndSpinVar(this.getEndSpinVar() || 0);
+
+ retParticle.setEmitterMode(this.getEmitterMode());
+
+ // Mode A: Gravity + tangential accel + radial accel
+ if (this.getEmitterMode() === cc.ParticleSystem.MODE_GRAVITY) {
+ // gravity
+ var gra = this.getGravity();
+ retParticle.setGravity(cc.p(gra.x, gra.y));
+
+ // speed
+ retParticle.setSpeed(this.getSpeed());
+ retParticle.setSpeedVar(this.getSpeedVar());
+
+ // radial acceleration
+ retParticle.setRadialAccel(this.getRadialAccel());
+ retParticle.setRadialAccelVar(this.getRadialAccelVar());
+
+ // tangential acceleration
+ retParticle.setTangentialAccel(this.getTangentialAccel());
+ retParticle.setTangentialAccelVar(this.getTangentialAccelVar());
+
+ } else if (this.getEmitterMode() === cc.ParticleSystem.MODE_RADIUS) {
+ // or Mode B: radius movement
+ retParticle.setStartRadius(this.getStartRadius());
+ retParticle.setStartRadiusVar(this.getStartRadiusVar());
+ retParticle.setEndRadius(this.getEndRadius());
+ retParticle.setEndRadiusVar(this.getEndRadiusVar());
+
+ retParticle.setRotatePerSecond(this.getRotatePerSecond());
+ retParticle.setRotatePerSecondVar(this.getRotatePerSecondVar());
+ }
+
+ // life span
+ retParticle.setLife(this.getLife());
+ retParticle.setLifeVar(this.getLifeVar());
+
+ // emission Rate
+ retParticle.setEmissionRate(this.getEmissionRate());
+
+ //don't get the internal texture if a batchNode is used
+ if (!this.getBatchNode()) {
+ // Set a compatible default for the alpha transfer
+ retParticle.setOpacityModifyRGB(this.isOpacityModifyRGB());
+ // texture
+ var texture = this.getTexture();
+ if (texture) {
+ var size = texture.getContentSize();
+ retParticle.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height));
+ }
+ }
+ }
+ return retParticle;
+ },
+
+ /**
+ * Sets a new CCSpriteFrame as particle.
+ * WARNING: this method is experimental. Use setTextureWithRect instead.
+ *
+ * @param {cc.SpriteFrame} spriteFrame
+ */
+ setDisplayFrame: function (spriteFrame) {
+ if (!spriteFrame)
+ return;
+
+ var locOffset = spriteFrame.getOffsetInPixels();
+ if (locOffset.x !== 0 || locOffset.y !== 0)
+ cc.log("cc.ParticleSystem.setDisplayFrame(): QuadParticle only supports SpriteFrames with no offsets");
+
+ // update texture before updating texture rect
+ var texture = spriteFrame.getTexture(), locTexture = this._texture;
+ if (locTexture !== texture)
+ this.setTexture(texture);
+ },
+
+ /**
+ * Sets a new texture with a rect. The rect is in Points.
+ * @param {cc.Texture2D} texture
+ * @param {cc.Rect} rect
+ */
+ setTextureWithRect: function (texture, rect) {
+ var locTexture = this._texture;
+ if (locTexture !== texture) {
+ this._texture = texture;
+ this._updateBlendFunc();
+ }
+ this.initTexCoordsWithRect(rect);
+ },
+
+ /**
+ * listen the event that coming to foreground on Android (An empty function for native)
+ * @param {cc.Class} obj
+ */
+ listenBackToForeground: function (obj) {
+ //do nothing
+ }
+});
+
+var _p = cc.ParticleSystem.prototype;
+
+// Extended properties
+/** @expose */
+_p.opacityModifyRGB;
+cc.defineGetterSetter(_p, "opacityModifyRGB", _p.isOpacityModifyRGB, _p.setOpacityModifyRGB);
+/** @expose */
+_p.batchNode;
+cc.defineGetterSetter(_p, "batchNode", _p.getBatchNode, _p.setBatchNode);
+/** @expose */
+_p.drawMode;
+cc.defineGetterSetter(_p, "drawMode", _p.getDrawMode, _p.setDrawMode);
+/** @expose */
+_p.shapeType;
+cc.defineGetterSetter(_p, "shapeType", _p.getShapeType, _p.setShapeType);
+/** @expose */
+_p.active;
+cc.defineGetterSetter(_p, "active", _p.isActive);
+/** @expose */
+_p.sourcePos;
+cc.defineGetterSetter(_p, "sourcePos", _p.getSourcePosition, _p.setSourcePosition);
+/** @expose */
+_p.posVar;
+cc.defineGetterSetter(_p, "posVar", _p.getPosVar, _p.setPosVar);
+/** @expose */
+_p.gravity;
+cc.defineGetterSetter(_p, "gravity", _p.getGravity, _p.setGravity);
+/** @expose */
+_p.speed;
+cc.defineGetterSetter(_p, "speed", _p.getSpeed, _p.setSpeed);
+/** @expose */
+_p.speedVar;
+cc.defineGetterSetter(_p, "speedVar", _p.getSpeedVar, _p.setSpeedVar);
+/** @expose */
+_p.tangentialAccel;
+cc.defineGetterSetter(_p, "tangentialAccel", _p.getTangentialAccel, _p.setTangentialAccel);
+/** @expose */
+_p.tangentialAccelVar;
+cc.defineGetterSetter(_p, "tangentialAccelVar", _p.getTangentialAccelVar, _p.setTangentialAccelVar);
+/** @expose */
+_p.radialAccel;
+cc.defineGetterSetter(_p, "radialAccel", _p.getRadialAccel, _p.setRadialAccel);
+/** @expose */
+_p.radialAccelVar;
+cc.defineGetterSetter(_p, "radialAccelVar", _p.getRadialAccelVar, _p.setRadialAccelVar);
+/** @expose */
+_p.rotationIsDir;
+cc.defineGetterSetter(_p, "rotationIsDir", _p.getRotationIsDir, _p.setRotationIsDir);
+/** @expose */
+_p.startRadius;
+cc.defineGetterSetter(_p, "startRadius", _p.getStartRadius, _p.setStartRadius);
+/** @expose */
+_p.startRadiusVar;
+cc.defineGetterSetter(_p, "startRadiusVar", _p.getStartRadiusVar, _p.setStartRadiusVar);
+/** @expose */
+_p.endRadius;
+cc.defineGetterSetter(_p, "endRadius", _p.getEndRadius, _p.setEndRadius);
+/** @expose */
+_p.endRadiusVar;
+cc.defineGetterSetter(_p, "endRadiusVar", _p.getEndRadiusVar, _p.setEndRadiusVar);
+/** @expose */
+_p.rotatePerS;
+cc.defineGetterSetter(_p, "rotatePerS", _p.getRotatePerSecond, _p.setRotatePerSecond);
+/** @expose */
+_p.rotatePerSVar;
+cc.defineGetterSetter(_p, "rotatePerSVar", _p.getRotatePerSecondVar, _p.setRotatePerSecondVar);
+/** @expose */
+_p.startColor;
+cc.defineGetterSetter(_p, "startColor", _p.getStartColor, _p.setStartColor);
+/** @expose */
+_p.startColorVar;
+cc.defineGetterSetter(_p, "startColorVar", _p.getStartColorVar, _p.setStartColorVar);
+/** @expose */
+_p.endColor;
+cc.defineGetterSetter(_p, "endColor", _p.getEndColor, _p.setEndColor);
+/** @expose */
+_p.endColorVar;
+cc.defineGetterSetter(_p, "endColorVar", _p.getEndColorVar, _p.setEndColorVar);
+/** @expose */
+_p.totalParticles;
+cc.defineGetterSetter(_p, "totalParticles", _p.getTotalParticles, _p.setTotalParticles);
+/** @expose */
+_p.texture;
+cc.defineGetterSetter(_p, "texture", _p.getTexture, _p.setTexture);
+
+
+/**
+ * return the string found by key in dict.
+ * This plist files can be create manually or with Particle Designer:
+ * http://particledesigner.71squared.com/
+ *
+ * @deprecated since v3.0 please use new cc.ParticleSysytem(plistFile) instead.
+ * @param {String|Number} plistFile
+ * @return {cc.ParticleSystem}
+ */
+cc.ParticleSystem.create = function (plistFile) {
+ return new cc.ParticleSystem(plistFile);
+};
+
+/**
+ * return the string found by key in dict.
+ * This plist files can be create manually or with Particle Designer:
+ * http://particledesigner.71squared.com/
+ *
+ * @deprecated since v3.0 please use new cc.ParticleSysytem(plistFile) instead.
+ * @function
+ * @param {String|Number} plistFile
+ * @return {cc.ParticleSystem}
+ */
+cc.ParticleSystem.createWithTotalParticles = cc.ParticleSystem.create;
+
+// Different modes
+/**
+ * Mode A:Gravity + Tangential Accel + Radial Accel
+ * @Class
+ * @Construct
+ * @param {cc.Point} [gravity=] Gravity value.
+ * @param {Number} [speed=0] speed of each particle.
+ * @param {Number} [speedVar=0] speed variance of each particle.
+ * @param {Number} [tangentialAccel=0] tangential acceleration of each particle.
+ * @param {Number} [tangentialAccelVar=0] tangential acceleration variance of each particle.
+ * @param {Number} [radialAccel=0] radial acceleration of each particle.
+ * @param {Number} [radialAccelVar=0] radial acceleration variance of each particle.
+ * @param {boolean} [rotationIsDir=false]
+ */
+cc.ParticleSystem.ModeA = function (gravity, speed, speedVar, tangentialAccel, tangentialAccelVar, radialAccel, radialAccelVar, rotationIsDir) {
+ /** Gravity value. Only available in 'Gravity' mode. */
+ this.gravity = gravity ? gravity : cc.p(0, 0);
+ /** speed of each particle. Only available in 'Gravity' mode. */
+ this.speed = speed || 0;
+ /** speed variance of each particle. Only available in 'Gravity' mode. */
+ this.speedVar = speedVar || 0;
+ /** tangential acceleration of each particle. Only available in 'Gravity' mode. */
+ this.tangentialAccel = tangentialAccel || 0;
+ /** tangential acceleration variance of each particle. Only available in 'Gravity' mode. */
+ this.tangentialAccelVar = tangentialAccelVar || 0;
+ /** radial acceleration of each particle. Only available in 'Gravity' mode. */
+ this.radialAccel = radialAccel || 0;
+ /** radial acceleration variance of each particle. Only available in 'Gravity' mode. */
+ this.radialAccelVar = radialAccelVar || 0;
+ /** set the rotation of each particle to its direction Only available in 'Gravity' mode. */
+ this.rotationIsDir = rotationIsDir || false;
+};
+
+/**
+ * Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
+ * @Class
+ * @Construct
+ * @param {Number} [startRadius=0] The starting radius of the particles.
+ * @param {Number} [startRadiusVar=0] The starting radius variance of the particles.
+ * @param {Number} [endRadius=0] The ending radius of the particles.
+ * @param {Number} [endRadiusVar=0] The ending radius variance of the particles.
+ * @param {Number} [rotatePerSecond=0] Number of degrees to rotate a particle around the source pos per second.
+ * @param {Number} [rotatePerSecondVar=0] Variance in degrees for rotatePerSecond.
+ */
+cc.ParticleSystem.ModeB = function (startRadius, startRadiusVar, endRadius, endRadiusVar, rotatePerSecond, rotatePerSecondVar) {
+ /** The starting radius of the particles. Only available in 'Radius' mode. */
+ this.startRadius = startRadius || 0;
+ /** The starting radius variance of the particles. Only available in 'Radius' mode. */
+ this.startRadiusVar = startRadiusVar || 0;
+ /** The ending radius of the particles. Only available in 'Radius' mode. */
+ this.endRadius = endRadius || 0;
+ /** The ending radius variance of the particles. Only available in 'Radius' mode. */
+ this.endRadiusVar = endRadiusVar || 0;
+ /** Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. */
+ this.rotatePerSecond = rotatePerSecond || 0;
+ /** Variance in degrees for rotatePerSecond. Only available in 'Radius' mode. */
+ this.rotatePerSecondVar = rotatePerSecondVar || 0;
+};
+
+/**
+ * Shape Mode of Particle Draw
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.SHAPE_MODE = 0;
+
+/**
+ * Texture Mode of Particle Draw
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.TEXTURE_MODE = 1;
+
+/**
+ * Star Shape for ShapeMode of Particle
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.STAR_SHAPE = 0;
+
+/**
+ * Ball Shape for ShapeMode of Particle
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.BALL_SHAPE = 1;
+
+/**
+ * The Particle emitter lives forever
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.DURATION_INFINITY = -1;
+
+/**
+ * The starting size of the particle is equal to the ending size
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.START_SIZE_EQUAL_TO_END_SIZE = -1;
+
+/**
+ * The starting radius of the particle is equal to the ending radius
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.START_RADIUS_EQUAL_TO_END_RADIUS = -1;
+
+/**
+ * Gravity mode (A mode)
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.MODE_GRAVITY = 0;
+
+/**
+ * Radius mode (B mode)
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.MODE_RADIUS = 1;
+
+/**
+ * Living particles are attached to the world and are unaffected by emitter repositioning.
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.TYPE_FREE = 0;
+
+/**
+ * Living particles are attached to the world but will follow the emitter repositioning.
+ * Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite.
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.TYPE_RELATIVE = 1;
+
+/**
+ * Living particles are attached to the emitter and are translated along with it.
+ * @constant
+ * @type Number
+ */
+cc.ParticleSystem.TYPE_GROUPED = 2;
diff --git a/cocos2d/particle/CCParticleSystemCanvasRenderCmd.js b/cocos2d/particle/CCParticleSystemCanvasRenderCmd.js
new file mode 100644
index 0000000000..5f602e99f2
--- /dev/null
+++ b/cocos2d/particle/CCParticleSystemCanvasRenderCmd.js
@@ -0,0 +1,206 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * ParticleSystem's canvas render command
+ */
+(function () {
+ cc.ParticleSystem.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = true;
+
+ this._drawMode = cc.ParticleSystem.TEXTURE_MODE;
+ this._shapeType = cc.ParticleSystem.BALL_SHAPE;
+
+ this._pointRect = cc.rect(0, 0, 0, 0);
+ this._tintCache = null;
+ };
+ var proto = cc.ParticleSystem.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.ParticleSystem.CanvasRenderCmd;
+
+ proto.getDrawMode = function () {
+ return this._drawMode;
+ };
+
+ proto.setDrawMode = function (drawMode) {
+ this._drawMode = drawMode;
+ };
+
+ proto.getShapeType = function () {
+ return this._shapeType;
+ };
+
+ proto.setShapeType = function (shapeType) {
+ this._shapeType = shapeType;
+ };
+
+ proto.setBatchNode = function (batchNode) {
+ if (this._batchNode !== batchNode) {
+ this._node._batchNode = batchNode;
+ }
+ };
+
+ proto.updateQuadWithParticle = function (particle, newPosition) {
+ //do nothing
+ };
+
+ proto.updateParticlePosition = function (particle, position) {
+ cc.pIn(particle.drawPos, position);
+ };
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ //TODO: need refactor rendering for performance
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext(),
+ node = this._node, pointRect = this._pointRect;
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ wrapper.save();
+ if (node.isBlendAdditive())
+ context.globalCompositeOperation = 'lighter';
+ else
+ context.globalCompositeOperation = 'source-over';
+
+ var i, particle, lpx, alpha;
+ var particleCount = this._node.particleCount, particles = this._node._particles;
+ if (node.drawMode !== cc.ParticleSystem.SHAPE_MODE && node._texture) {
+ // Delay drawing until the texture is fully loaded by the browser
+ if (!node._texture._textureLoaded) {
+ wrapper.restore();
+ return;
+ }
+ var element = node._texture.getHtmlElementObj();
+ if (!element.width || !element.height) {
+ wrapper.restore();
+ return;
+ }
+
+ var drawElement = element;
+ for (i = 0; i < particleCount; i++) {
+ particle = particles[i];
+ lpx = (0 | (particle.size * 0.5));
+
+ alpha = particle.color.a / 255;
+ if (alpha === 0) continue;
+ context.globalAlpha = alpha;
+
+ context.save();
+ context.translate((0 | particle.drawPos.x), -(0 | particle.drawPos.y));
+
+ var size = Math.floor(particle.size / 4) * 4;
+ var w = pointRect.width;
+ var h = pointRect.height;
+
+ context.scale(Math.max((1 / w) * size, 0.000001), Math.max((1 / h) * size, 0.000001));
+ if (particle.rotation)
+ context.rotate(cc.degreesToRadians(particle.rotation));
+
+ drawElement = particle.isChangeColor ? this._changeTextureColor(node._texture, particle.color, this._pointRect) : element;
+ context.drawImage(drawElement, -(0 | (w / 2)), -(0 | (h / 2)));
+ context.restore();
+ }
+ } else {
+ var drawTool = cc._drawingUtil;
+ for (i = 0; i < particleCount; i++) {
+ particle = particles[i];
+ lpx = (0 | (particle.size * 0.5));
+ alpha = particle.color.a / 255;
+ if (alpha === 0) continue;
+ context.globalAlpha = alpha;
+
+ context.save();
+ context.translate(0 | particle.drawPos.x, -(0 | particle.drawPos.y));
+ if (node.shapeType === cc.ParticleSystem.STAR_SHAPE) {
+ if (particle.rotation)
+ context.rotate(cc.degreesToRadians(particle.rotation));
+ drawTool.drawStar(wrapper, lpx, particle.color);
+ } else
+ drawTool.drawColorBall(wrapper, lpx, particle.color);
+ context.restore();
+ }
+ }
+ wrapper.restore();
+ cc.g_NumberOfDraws++;
+ };
+
+ proto._changeTextureColor = function (texture, color, rect) {
+ if (!this._tintCache) {
+ this._tintCache = document.createElement("canvas");
+ }
+ var tintCache = this._tintCache;
+ var textureContentSize = texture.getContentSize();
+ tintCache.width = textureContentSize.width;
+ tintCache.height = textureContentSize.height;
+ return texture._generateColorTexture(color.r, color.g, color.b, rect, tintCache);
+ };
+
+ proto.initTexCoordsWithRect = function (pointRect) {
+ this._pointRect = pointRect;
+ };
+
+ proto.setTotalParticles = function (tp) {
+ //cc.assert(tp <= this._allocatedParticles, "Particle: resizing particle array only supported for quads");
+ this._node._totalParticles = (tp < 200) ? tp : 200;
+ };
+
+ proto.addParticle = function () {
+ var node = this._node,
+ particles = node._particles,
+ particle;
+ if (node.particleCount < particles.length) {
+ particle = particles[node.particleCount];
+ } else {
+ particle = new cc.Particle();
+ particles.push(particle);
+ }
+ return particle;
+ };
+
+ proto._setupVBO = function () {
+ };
+ proto._allocMemory = function () {
+ return true;
+ };
+
+ proto.postStep = function () {
+ };
+
+ proto._setBlendAdditive = function () {
+ var locBlendFunc = this._node._blendFunc;
+ locBlendFunc.src = cc.BLEND_SRC;
+ locBlendFunc.dst = cc.BLEND_DST;
+ };
+
+ proto._initWithTotalParticles = function (totalParticles) {
+ };
+ proto._updateDeltaColor = function (selParticle, dt) {
+ if (!this._node._dontTint) {
+ var deltaColor = selParticle.deltaColor;
+ selParticle.color.r += deltaColor.r * dt;
+ selParticle.color.g += deltaColor.g * dt;
+ selParticle.color.b += deltaColor.b * dt;
+ selParticle.color.a += deltaColor.a * dt;
+ selParticle.isChangeColor = deltaColor.r !== 0 || deltaColor.g !== 0 || deltaColor.b !== 0;
+ }
+ };
+})();
diff --git a/cocos2d/particle/CCParticleSystemWebGLRenderCmd.js b/cocos2d/particle/CCParticleSystemWebGLRenderCmd.js
new file mode 100644
index 0000000000..54b1236119
--- /dev/null
+++ b/cocos2d/particle/CCParticleSystemWebGLRenderCmd.js
@@ -0,0 +1,420 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ /**
+ * ParticleSystem's WebGL render command
+ */
+ cc.ParticleSystem.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = true;
+
+ this._matrix = null;
+
+ this._buffersVBO = [0, 0];
+ this._quads = [];
+ this._indices = [];
+ this._quadsArrayBuffer = null;
+ };
+ var proto = cc.ParticleSystem.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.ParticleSystem.WebGLRenderCmd;
+
+ proto.getDrawMode = function () {
+ };
+ proto.setDrawMode = function (drawMode) {
+ };
+ proto.getShapeType = function () {
+ };
+ proto.setShapeType = function (shapeType) {
+ };
+
+ proto.setBatchNode = function (batchNode) {
+ var node = this._node;
+ if (node._batchNode !== batchNode) {
+ var oldBatch = node._batchNode;
+ node._batchNode = batchNode; //weak reference
+
+ if (batchNode) {
+ var locParticles = node._particles;
+ for (var i = 0; i < node._totalParticles; i++)
+ locParticles[i].atlasIndex = i;
+ }
+
+ // NEW: is self render ?
+ if (!batchNode) {
+ this._allocMemory();
+ this.initIndices(node._totalParticles);
+ node.setTexture(oldBatch.getTexture());
+ this._setupVBO();
+
+ } else if (!oldBatch) {
+ // OLD: was it self render cleanup ?
+ // copy current state to batch
+ node._batchNode.textureAtlas._copyQuadsToTextureAtlas(this._quads, node.atlasIndex);
+
+ //delete buffer
+ cc._renderContext.deleteBuffer(this._buffersVBO[1]); //where is re-bindBuffer code?
+ }
+ }
+ };
+
+ proto.initIndices = function (totalParticles) {
+ var locIndices = this._indices;
+ for (var i = 0, len = totalParticles; i < len; ++i) {
+ var i6 = i * 6;
+ var i4 = i * 4;
+ locIndices[i6 + 0] = i4 + 0;
+ locIndices[i6 + 1] = i4 + 1;
+ locIndices[i6 + 2] = i4 + 2;
+
+ locIndices[i6 + 5] = i4 + 1;
+ locIndices[i6 + 4] = i4 + 2;
+ locIndices[i6 + 3] = i4 + 3;
+ }
+ };
+
+ proto.isDifferentTexture = function (texture1, texture2) {
+ return (texture1 === texture2);
+ };
+
+ proto.updateParticlePosition = function (particle, position) {
+ // IMPORTANT: newPos may not be used as a reference here! (as it is just the temporary tpa point)
+ // the implementation of updateQuadWithParticle must use
+ // the x and y values directly
+ this.updateQuadWithParticle(particle, position);
+ };
+
+ proto.updateQuadWithParticle = function (particle, newPosition) {
+ var quad = null, node = this._node;
+ if (node._batchNode) {
+ var batchQuads = node._batchNode.textureAtlas.quads;
+ quad = batchQuads[node.atlasIndex + particle.atlasIndex];
+ node._batchNode.textureAtlas.dirty = true;
+ } else
+ quad = this._quads[node._particleIdx];
+
+ var r, g, b, a;
+ if (node._opacityModifyRGB) {
+ r = 0 | (particle.color.r * particle.color.a / 255);
+ g = 0 | (particle.color.g * particle.color.a / 255);
+ b = 0 | (particle.color.b * particle.color.a / 255);
+ } else {
+ r = 0 | (particle.color.r );
+ g = 0 | (particle.color.g );
+ b = 0 | (particle.color.b );
+ }
+ a = 0 | (particle.color.a );
+
+ var blColors = quad.bl.colors, brColors = quad.br.colors, tlColors = quad.tl.colors, trColors = quad.tr.colors;
+ blColors.r = brColors.r = tlColors.r = trColors.r = r;
+ blColors.g = brColors.g = tlColors.g = trColors.g = g;
+ blColors.b = brColors.b = tlColors.b = trColors.b = b;
+ blColors.a = brColors.a = tlColors.a = trColors.a = a;
+
+ // vertices
+ var size_2 = particle.size / 2;
+ if (particle.rotation) {
+ var x1 = -size_2, y1 = -size_2;
+
+ var x2 = size_2, y2 = size_2;
+ var x = newPosition.x, y = newPosition.y;
+
+ var rad = -cc.degreesToRadians(particle.rotation);
+ var cr = Math.cos(rad), sr = Math.sin(rad);
+ var ax = x1 * cr - y1 * sr + x;
+ var ay = x1 * sr + y1 * cr + y;
+ var bx = x2 * cr - y1 * sr + x;
+ var by = x2 * sr + y1 * cr + y;
+ var cx = x2 * cr - y2 * sr + x;
+ var cy = x2 * sr + y2 * cr + y;
+ var dx = x1 * cr - y2 * sr + x;
+ var dy = x1 * sr + y2 * cr + y;
+
+ // bottom-left
+ quad.bl.vertices.x = ax;
+ quad.bl.vertices.y = ay;
+
+ // bottom-right vertex:
+ quad.br.vertices.x = bx;
+ quad.br.vertices.y = by;
+
+ // top-left vertex:
+ quad.tl.vertices.x = dx;
+ quad.tl.vertices.y = dy;
+
+ // top-right vertex:
+ quad.tr.vertices.x = cx;
+ quad.tr.vertices.y = cy;
+ } else {
+ // bottom-left vertex:
+ quad.bl.vertices.x = newPosition.x - size_2;
+ quad.bl.vertices.y = newPosition.y - size_2;
+
+ // bottom-right vertex:
+ quad.br.vertices.x = newPosition.x + size_2;
+ quad.br.vertices.y = newPosition.y - size_2;
+
+ // top-left vertex:
+ quad.tl.vertices.x = newPosition.x - size_2;
+ quad.tl.vertices.y = newPosition.y + size_2;
+
+ // top-right vertex:
+ quad.tr.vertices.x = newPosition.x + size_2;
+ quad.tr.vertices.y = newPosition.y + size_2;
+ }
+ };
+
+ proto.rendering = function (ctx) {
+ var node = this._node;
+ if (!node._texture)
+ return;
+
+ var gl = ctx || cc._renderContext;
+
+ if (!this._matrix) {
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ }
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ this._glProgramState.apply(this._matrix);
+
+ cc.glBindTexture2D(node._texture);
+ cc.glBlendFuncForParticle(node._blendFunc.src, node._blendFunc.dst);
+
+ //
+ // Using VBO without VAO
+ //
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); // vertices
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); // colors
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16); // tex coords
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
+ gl.drawElements(gl.TRIANGLES, node._particleIdx * 6, gl.UNSIGNED_SHORT, 0);
+ };
+
+ proto.initTexCoordsWithRect = function (pointRect) {
+ var node = this._node;
+ var texture = node.texture;
+ var scaleFactor = cc.contentScaleFactor();
+ // convert to pixels coords
+ var rect = cc.rect(
+ pointRect.x * scaleFactor,
+ pointRect.y * scaleFactor,
+ pointRect.width * scaleFactor,
+ pointRect.height * scaleFactor);
+
+ var wide = pointRect.width;
+ var high = pointRect.height;
+
+ if (texture) {
+ wide = texture.pixelsWidth;
+ high = texture.pixelsHeight;
+ }
+
+ var left, bottom, right, top;
+ if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
+ left = (rect.x * 2 + 1) / (wide * 2);
+ bottom = (rect.y * 2 + 1) / (high * 2);
+ right = left + (rect.width * 2 - 2) / (wide * 2);
+ top = bottom + (rect.height * 2 - 2) / (high * 2);
+ } else {
+ left = rect.x / wide;
+ bottom = rect.y / high;
+ right = left + rect.width / wide;
+ top = bottom + rect.height / high;
+ }
+
+ // Important. Texture in cocos2d are inverted, so the Y component should be inverted
+ var temp = top;
+ top = bottom;
+ bottom = temp;
+
+ var quads;
+ var start = 0, end = 0;
+ if (node._batchNode) {
+ quads = node._batchNode.textureAtlas.quads;
+ start = node.atlasIndex;
+ end = node.atlasIndex + node._totalParticles;
+ } else {
+ quads = this._quads;
+ start = 0;
+ end = node._totalParticles;
+ }
+
+ for (var i = start; i < end; i++) {
+ if (!quads[i])
+ quads[i] = cc.V3F_C4B_T2F_QuadZero();
+
+ // bottom-left vertex:
+ var selQuad = quads[i];
+ selQuad.bl.texCoords.u = left;
+ selQuad.bl.texCoords.v = bottom;
+ // bottom-right vertex:
+ selQuad.br.texCoords.u = right;
+ selQuad.br.texCoords.v = bottom;
+ // top-left vertex:
+ selQuad.tl.texCoords.u = left;
+ selQuad.tl.texCoords.v = top;
+ // top-right vertex:
+ selQuad.tr.texCoords.u = right;
+ selQuad.tr.texCoords.v = top;
+ }
+ };
+
+ proto.setTotalParticles = function (tp) {
+ var node = this._node;
+ // If we are setting the total numer of particles to a number higher
+ // than what is allocated, we need to allocate new arrays
+ if (tp > node._allocatedParticles) {
+ var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
+ // Allocate new memory
+ this._indices = new Uint16Array(tp * 6);
+ var locQuadsArrayBuffer = new ArrayBuffer(tp * quadSize);
+ //TODO need fix
+ // Assign pointers
+ var locParticles = node._particles;
+ locParticles.length = 0;
+ var locQuads = this._quads;
+ locQuads.length = 0;
+ for (var j = 0; j < tp; j++) {
+ locParticles[j] = new cc.Particle();
+ locQuads[j] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, j * quadSize);
+ }
+ node._allocatedParticles = tp;
+ node._totalParticles = tp;
+
+ // Init particles
+ if (node._batchNode) {
+ for (var i = 0; i < tp; i++)
+ locParticles[i].atlasIndex = i;
+ }
+
+ this._quadsArrayBuffer = locQuadsArrayBuffer;
+ this.initIndices(tp);
+ this._setupVBO();
+
+ //set the texture coord
+ if (node._texture) {
+ this.initTexCoordsWithRect(cc.rect(0, 0, node._texture.width, node._texture.height));
+ }
+ } else
+ node._totalParticles = tp;
+ node.resetSystem();
+ };
+
+ proto.addParticle = function () {
+ var node = this._node,
+ particles = node._particles;
+ return particles[node.particleCount];
+ };
+
+ proto._setupVBO = function () {
+ var node = this;
+ var gl = cc._renderContext;
+
+ //gl.deleteBuffer(this._buffersVBO[0]);
+ this._buffersVBO[0] = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
+ gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
+
+ this._buffersVBO[1] = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
+
+ //cc.checkGLErrorDebug();
+ };
+
+ proto._allocMemory = function () {
+ var node = this._node;
+ //cc.assert((!this._quads && !this._indices), "Memory already allocated");
+ if (node._batchNode) {
+ cc.log("cc.ParticleSystem._allocMemory(): Memory should not be allocated when not using batchNode");
+ return false;
+ }
+
+ var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
+ var totalParticles = node._totalParticles;
+ var locQuads = this._quads;
+ locQuads.length = 0;
+ this._indices = new Uint16Array(totalParticles * 6);
+ var locQuadsArrayBuffer = new ArrayBuffer(quadSize * totalParticles);
+
+ for (var i = 0; i < totalParticles; i++)
+ locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, i * quadSize);
+ if (!locQuads || !this._indices) {
+ cc.log("cocos2d: Particle system: not enough memory");
+ return false;
+ }
+ this._quadsArrayBuffer = locQuadsArrayBuffer;
+ return true;
+ };
+
+ proto.postStep = function () {
+ var gl = cc._renderContext;
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, this._quadsArrayBuffer);
+ };
+
+ proto._setBlendAdditive = function () {
+ var locBlendFunc = this._node._blendFunc;
+ if (this._texture && !this._texture.hasPremultipliedAlpha()) {
+ locBlendFunc.src = cc.SRC_ALPHA;
+ locBlendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
+ } else {
+ locBlendFunc.src = cc.BLEND_SRC;
+ locBlendFunc.dst = cc.BLEND_DST;
+ }
+ };
+
+ proto._initWithTotalParticles = function (totalParticles) {
+ // allocating data space
+ if (!this._allocMemory())
+ return false;
+
+ this.initIndices(totalParticles);
+ this._setupVBO();
+
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
+ };
+
+ proto._updateDeltaColor = function (selParticle, dt) {
+ selParticle.color.r += selParticle.deltaColor.r * dt;
+ selParticle.color.g += selParticle.deltaColor.g * dt;
+ selParticle.color.b += selParticle.deltaColor.b * dt;
+ selParticle.color.a += selParticle.deltaColor.a * dt;
+ selParticle.isChangeColor = true;
+ };
+})();
diff --git a/cocos2d/support/CCTIFFReader.js b/cocos2d/particle/CCTIFFReader.js
similarity index 97%
rename from cocos2d/support/CCTIFFReader.js
rename to cocos2d/particle/CCTIFFReader.js
index b4af93ccf2..185486539a 100644
--- a/cocos2d/support/CCTIFFReader.js
+++ b/cocos2d/particle/CCTIFFReader.js
@@ -2,7 +2,10 @@
Copyright (c) 2011 Gordon P. Hemsley
http://gphemsley.org/
- Copyright (c) 2010-2013 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,14 +27,15 @@
THE SOFTWARE.
****************************************************************************/
-cc.TIFFReader = cc.Class.extend({
+/**
+ * cc.tiffReader is a singleton object, it's a tiff file reader, it can parse byte array to draw into a canvas
+ * @class
+ * @name cc.tiffReader
+ */
+cc.tiffReader = /** @lends cc.tiffReader# */{
_littleEndian: false,
_tiffData: null,
- _fileDirectories: null,
-
- ctor: function () {
- this._fileDirectories = [];
- },
+ _fileDirectories: [],
getUint8: function (offset) {
return this._tiffData[offset];
@@ -209,7 +213,7 @@ cc.TIFFReader = cc.Class.extend({
tiffFields[fieldTagName] = { type: fieldTypeName, values: fieldValues };
}
- this.fileDirectories.push(tiffFields);
+ this._fileDirectories.push(tiffFields);
var nextIFDByteOffset = this.getUint32(i);
if (nextIFDByteOffset !== 0x00000000) {
@@ -223,6 +227,12 @@ cc.TIFFReader = cc.Class.extend({
return Math.floor((colorSample * multiplier) + (multiplier - 1));
},
+ /**
+ * @function
+ * @param {Array} tiffData
+ * @param {HTMLCanvasElement} canvas
+ * @returns {*}
+ */
parseTIFF: function (tiffData, canvas) {
canvas = canvas || document.createElement('canvas');
@@ -237,10 +247,10 @@ cc.TIFFReader = cc.Class.extend({
var firstIFDByteOffset = this.getUint32(4);
- this.fileDirectories = [];
+ this._fileDirectories.length = 0;
this.parseFileDirectory(firstIFDByteOffset);
- var fileDirectory = this.fileDirectories[0];
+ var fileDirectory = this._fileDirectories[0];
var imageWidth = fileDirectory['ImageWidth'].values[0];
var imageLength = fileDirectory['ImageLength'].values[0];
@@ -261,9 +271,9 @@ cc.TIFFReader = cc.Class.extend({
fileDirectory['BitsPerSample'].values.forEach(function (bitsPerSample, i, bitsPerSampleValues) {
sampleProperties[i] = {
- 'bitsPerSample': bitsPerSample,
- 'hasBytesPerSample': false,
- 'bytesPerSample': undefined
+ bitsPerSample: bitsPerSample,
+ hasBytesPerSample: false,
+ bytesPerSample: undefined
};
if ((bitsPerSample % 8) === 0) {
@@ -679,11 +689,4 @@ cc.TIFFReader = cc.Class.extend({
0x000B: 'FLOAT',
0x000C: 'DOUBLE'
}
-});
-
-cc.TIFFReader.__instance = null;
-cc.TIFFReader.getInstance = function () {
- if (!cc.TIFFReader.__instance)
- cc.TIFFReader.__instance = new cc.TIFFReader();
- return cc.TIFFReader.__instance;
-};
+};
\ No newline at end of file
diff --git a/cocos2d/particle_nodes/CCParticleSystem.js b/cocos2d/particle_nodes/CCParticleSystem.js
deleted file mode 100644
index 7203e2ed7b..0000000000
--- a/cocos2d/particle_nodes/CCParticleSystem.js
+++ /dev/null
@@ -1,2711 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-// ideas taken from:
-// . The ocean spray in your face [Jeff Lander]
-// http://www.double.co.nz/dust/col0798.pdf
-// . Building an Advanced Particle System [John van der Burg]
-// http://www.gamasutra.com/features/20000623/vanderburg_01.htm
-// . LOVE game engine
-// http://love2d.org/
-//
-//
-// Radius mode support, from 71 squared
-// http://particledesigner.71squared.com/
-//
-// IMPORTANT: Particle Designer is supported by cocos2d, but
-// 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
-// cocos2d uses a another approach, but the results are almost identical.
-//
-
-/**
- * Shape Mode of Particle Draw
- * @constant
- * @type Number
- */
-cc.PARTICLE_SHAPE_MODE = 0;
-/**
- * Texture Mode of Particle Draw
- * @constant
- * @type Number
- */
-cc.PARTICLE_TEXTURE_MODE = 1;
-
-/**
- * Star Shape for ShapeMode of Particle
- * @constant
- * @type Number
- */
-cc.PARTICLE_STAR_SHAPE = 0;
-/**
- * Ball Shape for ShapeMode of Particle
- * @constant
- * @type Number
- */
-cc.PARTICLE_BALL_SHAPE = 1;
-
-/**
- * The Particle emitter lives forever
- * @constant
- * @type Number
- */
-cc.PARTICLE_DURATION_INFINITY = -1;
-
-/**
- * The starting size of the particle is equal to the ending size
- * @constant
- * @type Number
- */
-cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE = -1;
-
-/**
- * The starting radius of the particle is equal to the ending radius
- * @constant
- * @type Number
- */
-cc.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS = -1;
-
-/**
- * Gravity mode (A mode)
- * @constant
- * @type Number
- */
-cc.PARTICLE_MODE_GRAVITY = 0;
-
-/**
- * Radius mode (B mode)
- * @constant
- * @type Number
- */
-cc.PARTICLE_MODE_RADIUS = 1;
-
-// tCCPositionType
-// possible types of particle positions
-
-/**
- * Living particles are attached to the world and are unaffected by emitter repositioning.
- * @constant
- * @type Number
- */
-cc.PARTICLE_TYPE_FREE = 0;
-
-/**
- * Living particles are attached to the world but will follow the emitter repositioning.
- * Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite.
- * @constant
- * @type Number
- */
-cc.PARTICLE_TYPE_RELATIVE = 1;
-
-/**
- * Living particles are attached to the emitter and are translated along with it.
- * @constant
- * @type Number
- */
-cc.PARTICLE_TYPE_GROUPED = 2;
-
-/**
- * Structure that contains the values of each particle
- * @Class
- * @Construct
- * @param {cc.Point} [pos=cc.PointZero()] Position of particle
- * @param {cc.Point} [startPos=cc.PointZero()]
- * @param {cc.Color4F} [color= cc.Color4F(0, 0, 0, 1)]
- * @param {cc.Color4F} [deltaColor=cc.Color4F(0, 0, 0, 1)]
- * @param {cc.Size} [size=0]
- * @param {cc.Size} [deltaSize=0]
- * @param {Number} [rotation=0]
- * @param {Number} [deltaRotation=0]
- * @param {Number} [timeToLive=0]
- * @param {Number} [atlasIndex=0]
- * @param {cc.Particle.ModeA} [modeA=]
- * @param {cc.Particle.ModeA} [modeB=]
- */
-cc.Particle = function (pos, startPos, color, deltaColor, size, deltaSize, rotation, deltaRotation, timeToLive, atlasIndex, modeA, modeB) {
- this.pos = pos ? pos : cc.PointZero();
- this.startPos = startPos ? startPos : cc.PointZero();
- this.color = color ? color : new cc.Color4F(0, 0, 0, 1);
- this.deltaColor = deltaColor ? deltaColor : new cc.Color4F(0, 0, 0, 1);
- this.size = size || 0;
- this.deltaSize = deltaSize || 0;
- this.rotation = rotation || 0;
- this.deltaRotation = deltaRotation || 0;
- this.timeToLive = timeToLive || 0;
- this.atlasIndex = atlasIndex || 0;
- this.modeA = modeA ? modeA : new cc.Particle.ModeA();
- this.modeB = modeB ? modeB : new cc.Particle.ModeB();
- this.isChangeColor = false;
- this.drawPos = cc.p(0, 0);
-};
-
-/**
- * Mode A: gravity, direction, radial accel, tangential accel
- * @Class
- * @Construct
- * @param {cc.Point} dir direction of particle
- * @param {Number} radialAccel
- * @param {Number} tangentialAccel
- */
-cc.Particle.ModeA = function (dir, radialAccel, tangentialAccel) {
- this.dir = dir ? dir : cc.PointZero();
- this.radialAccel = radialAccel || 0;
- this.tangentialAccel = tangentialAccel || 0;
-};
-
-/**
- * Mode B: radius mode
- * @Class
- * @Construct
- * @param {Number} angle
- * @param {Number} degreesPerSecond
- * @param {Number} radius
- * @param {Number} deltaRadius
- */
-cc.Particle.ModeB = function (angle, degreesPerSecond, radius, deltaRadius) {
- this.angle = angle || 0;
- this.degreesPerSecond = degreesPerSecond || 0;
- this.radius = radius || 0;
- this.deltaRadius = deltaRadius || 0;
-};
-
-/**
- * Array of Point instances used to optimize particle updates
- */
-cc.Particle.TemporaryPoints = [
- cc.p(),
- cc.p(),
- cc.p(),
- cc.p()
-];
-
-/**
- *
- * Particle System base class.
- * Attributes of a Particle System:
- * - emmision rate of the particles
- * - Gravity Mode (Mode A):
- * - gravity
- * - direction
- * - speed +- variance
- * - tangential acceleration +- variance
- * - radial acceleration +- variance
- * - Radius Mode (Mode B):
- * - startRadius +- variance
- * - endRadius +- variance
- * - rotate +- variance
- * - Properties common to all modes:
- * - life +- life variance
- * - start spin +- variance
- * - end spin +- variance
- * - start size +- variance
- * - end size +- variance
- * - start color +- variance
- * - end color +- variance
- * - life +- variance
- * - blending function
- * - texture
- *
- * cocos2d also supports particles generated by Particle Designer (http://particledesigner.71squared.com/).
- * 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
- * cocos2d uses a another approach, but the results are almost identical.
- * cocos2d supports all the variables used by Particle Designer plus a bit more:
- * - spinning particles (supported when using ParticleSystem)
- * - tangential acceleration (Gravity mode)
- * - radial acceleration (Gravity mode)
- * - radius direction (Radius mode) (Particle Designer supports outwards to inwards direction only)
- * It is possible to customize any of the above mentioned properties in runtime. Example:
- *
- * @class
- * @extends cc.Node
- *
- * @example
- * emitter.radialAccel = 15;
- * emitter.startSpin = 0;
- */
-cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{
- //***********variables*************
- _plistFile: "",
- //! time elapsed since the start of the system (in seconds)
- _elapsed: 0,
-
- _dontTint: false,
-
- // Different modes
- //! Mode A:Gravity + Tangential Accel + Radial Accel
- modeA: null,
- //! Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
- modeB: null,
-
- //private POINTZERO for ParticleSystem
- _pointZeroForParticle: cc.p(0, 0),
-
- //! Array of particles
- _particles: null,
-
- // color modulate
- // BOOL colorModulate;
-
- //! How many particles can be emitted per second
- _emitCounter: 0,
- //! particle idx
- _particleIdx: 0,
-
- _batchNode: null,
- _atlasIndex: 0,
-
- //true if scaled or rotated
- _transformSystemDirty: false,
- _allocatedParticles: 0,
-
- //drawMode
- _drawMode: cc.PARTICLE_SHAPE_MODE,
-
- //shape type
- _shapeType: cc.PARTICLE_BALL_SHAPE,
- _isActive: false,
- _particleCount: 0,
- _duration: 0,
- _sourcePosition: null,
- _posVar: null,
- _life: 0,
- _lifeVar: 0,
- _angle: 0,
- _angleVar: 0,
- _startSize: 0,
- _startSizeVar: 0,
- _endSize: 0,
- _endSizeVar: 0,
- _startColor: null,
- _startColorVar: null,
- _endColor: null,
- _endColorVar: null,
- _startSpin: 0,
- _startSpinVar: 0,
- _endSpin: 0,
- _endSpinVar: 0,
- _emissionRate: 0,
- _totalParticles: 0,
- _texture: null,
- _blendFunc: null,
- _opacityModifyRGB: false,
- _positionType: cc.PARTICLE_TYPE_FREE,
- _isAutoRemoveOnFinish: false,
- _emitterMode: 0,
-
- // quads to be rendered
- _quads:null,
- // indices
- _indices:null,
-
- //_VAOname:0,
- //0: vertex 1: indices
- _buffersVBO:null,
- _pointRect:null,
-
- _textureLoaded: null,
- _quadsArrayBuffer:null,
-
- /**
- * Constructor
- * @override
- */
- ctor:function () {
- cc.Node.prototype.ctor.call(this);
- this._emitterMode = cc.PARTICLE_MODE_GRAVITY;
- this.modeA = new cc.ParticleSystem.ModeA();
- this.modeB = new cc.ParticleSystem.ModeB();
- this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST};
-
- this._particles = [];
- this._sourcePosition = new cc.Point(0, 0);
- this._posVar = new cc.Point(0, 0);
-
- this._startColor = new cc.Color4F(1, 1, 1, 1);
- this._startColorVar = new cc.Color4F(1, 1, 1, 1);
- this._endColor = new cc.Color4F(1, 1, 1, 1);
- this._endColorVar = new cc.Color4F(1, 1, 1, 1);
-
- this._plistFile = "";
- this._elapsed = 0;
- this._dontTint = false;
- this._pointZeroForParticle = cc.p(0, 0);
- this._emitCounter = 0;
- this._particleIdx = 0;
- this._batchNode = null;
- this._atlasIndex = 0;
-
- this._transformSystemDirty = false;
- this._allocatedParticles = 0;
- this._drawMode = cc.PARTICLE_SHAPE_MODE;
- this._shapeType = cc.PARTICLE_BALL_SHAPE;
- this._isActive = false;
- this._particleCount = 0;
- this._duration = 0;
- this._life = 0;
- this._lifeVar = 0;
- this._angle = 0;
- this._angleVar = 0;
- this._startSize = 0;
- this._startSizeVar = 0;
- this._endSize = 0;
- this._endSizeVar = 0;
-
- this._startSpin = 0;
- this._startSpinVar = 0;
- this._endSpin = 0;
- this._endSpinVar = 0;
- this._emissionRate = 0;
- this._totalParticles = 0;
- this._texture = null;
- this._opacityModifyRGB = false;
- this._positionType = cc.PARTICLE_TYPE_FREE;
- this._isAutoRemoveOnFinish = false;
-
- this._buffersVBO = [0, 0];
- this._quads = [];
- this._indices = [];
- this._pointRect = cc.RectZero();
- this._textureLoaded = true;
-
- if (cc.renderContextType === cc.WEBGL) {
- this._quadsArrayBuffer = null;
- }
- },
-
- /**
- * initializes the indices for the vertices
- */
- initIndices:function () {
- var locIndices = this._indices;
- for (var i = 0, len = this._totalParticles; i < len; ++i) {
- var i6 = i * 6;
- var i4 = i * 4;
- locIndices[i6 + 0] = i4 + 0;
- locIndices[i6 + 1] = i4 + 1;
- locIndices[i6 + 2] = i4 + 2;
-
- locIndices[i6 + 5] = i4 + 1;
- locIndices[i6 + 4] = i4 + 2;
- locIndices[i6 + 3] = i4 + 3;
- }
- },
-
- /**
- * initializes the texture with a rectangle measured Points
- * pointRect should be in Texture coordinates, not pixel coordinates
- *
- * @param {cc.Rect} pointRect
- */
- initTexCoordsWithRect:function (pointRect) {
- var scaleFactor = cc.CONTENT_SCALE_FACTOR();
- // convert to pixels coords
- var rect = cc.rect(
- pointRect.x * scaleFactor,
- pointRect.y * scaleFactor,
- pointRect.width * scaleFactor,
- pointRect.height * scaleFactor);
-
- var wide = pointRect.width;
- var high = pointRect.height;
-
- if (this._texture) {
- wide = this._texture.getPixelsWide();
- high = this._texture.getPixelsHigh();
- }
-
- if(cc.renderContextType === cc.CANVAS)
- return;
-
- var left, bottom, right, top;
- if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
- left = (rect.x * 2 + 1) / (wide * 2);
- bottom = (rect.y * 2 + 1) / (high * 2);
- right = left + (rect.width * 2 - 2) / (wide * 2);
- top = bottom + (rect.height * 2 - 2) / (high * 2);
- } else {
- left = rect.x / wide;
- bottom = rect.y / high;
- right = left + rect.width / wide;
- top = bottom + rect.height / high;
- }
-
- // Important. Texture in cocos2d are inverted, so the Y component should be inverted
- var temp = top;
- top = bottom;
- bottom = temp;
-
- var quads;
- var start = 0, end = 0;
- if (this._batchNode) {
- quads = this._batchNode.getTextureAtlas().getQuads();
- start = this._atlasIndex;
- end = this._atlasIndex + this._totalParticles;
- } else {
- quads = this._quads;
- start = 0;
- end = this._totalParticles;
- }
-
- for (var i = start; i < end; i++) {
- if (!quads[i])
- quads[i] = cc.V3F_C4B_T2F_QuadZero();
-
- // bottom-left vertex:
- var selQuad = quads[i];
- selQuad.bl.texCoords.u = left;
- selQuad.bl.texCoords.v = bottom;
- // bottom-right vertex:
- selQuad.br.texCoords.u = right;
- selQuad.br.texCoords.v = bottom;
- // top-left vertex:
- selQuad.tl.texCoords.u = left;
- selQuad.tl.texCoords.v = top;
- // top-right vertex:
- selQuad.tr.texCoords.u = right;
- selQuad.tr.texCoords.v = top;
- }
- },
-
- /**
- * return weak reference to the cc.SpriteBatchNode that renders the cc.Sprite
- * @return {cc.ParticleBatchNode}
- */
- getBatchNode:function () {
- return this._batchNode;
- },
-
- /**
- * set weak reference to the cc.SpriteBatchNode that renders the cc.Sprite
- * @param {cc.ParticleBatchNode} batchNode
- */
- setBatchNode:function (batchNode) {
- if (this._batchNode != batchNode) {
- var oldBatch = this._batchNode;
-
- this._batchNode = batchNode; //weak reference
-
- if (batchNode) {
- var locParticles = this._particles;
- for (var i = 0; i < this._totalParticles; i++)
- locParticles[i].atlasIndex = i;
- }
-
- // NEW: is self render ?
- if (!batchNode) {
- this._allocMemory();
- this.initIndices();
- this.setTexture(oldBatch.getTexture());
- //if (cc.TEXTURE_ATLAS_USE_VAO)
- // this._setupVBOandVAO();
- //else
- this._setupVBO();
- } else if (!oldBatch) {
- // OLD: was it self render cleanup ?
- // copy current state to batch
- this._batchNode.getTextureAtlas()._copyQuadsToTextureAtlas(this._quads, this._atlasIndex);
-
- //delete buffer
- cc.renderContext.deleteBuffer(this._buffersVBO[1]); //where is re-bindBuffer code?
-
- //if (cc.TEXTURE_ATLAS_USE_VAO)
- // glDeleteVertexArrays(1, this._VAOname);
- }
- }
- },
-
- /**
- * return index of system in batch node array
- * @return {Number}
- */
- getAtlasIndex:function () {
- return this._atlasIndex;
- },
-
- /**
- * set index of system in batch node array
- * @param {Number} atlasIndex
- */
- setAtlasIndex:function (atlasIndex) {
- this._atlasIndex = atlasIndex;
- },
-
- /**
- * Return DrawMode of ParticleSystem
- * @return {Number}
- */
- getDrawMode:function () {
- return this._drawMode;
- },
-
- /**
- * DrawMode of ParticleSystem setter
- * @param {Number} drawMode
- */
- setDrawMode:function (drawMode) {
- this._drawMode = drawMode;
- },
-
- /**
- * Return ShapeType of ParticleSystem
- * @return {Number}
- */
- getShapeType:function () {
- return this._shapeType;
- },
-
- /**
- * ShapeType of ParticleSystem setter
- * @param {Number} shapeType
- */
- setShapeType:function (shapeType) {
- this._shapeType = shapeType;
- },
-
- /**
- * Return ParticleSystem is active
- * @return {Boolean}
- */
- isActive:function () {
- return this._isActive;
- },
-
- /**
- * Quantity of particles that are being simulated at the moment
- * @return {Number}
- */
- getParticleCount:function () {
- return this._particleCount;
- },
-
- /**
- * Quantity of particles setter
- * @param {Number} particleCount
- */
- setParticleCount:function (particleCount) {
- this._particleCount = particleCount;
- },
-
- /**
- * How many seconds the emitter wil run. -1 means 'forever'
- * @return {Number}
- */
- getDuration:function () {
- return this._duration;
- },
-
- /**
- * set run seconds of the emitter
- * @param {Number} duration
- */
- setDuration:function (duration) {
- this._duration = duration;
- },
-
- /**
- * Return sourcePosition of the emitter
- * @return {cc.Point | Object}
- */
- getSourcePosition:function () {
- return {x:this._sourcePosition.x, y:this._sourcePosition.y};
- },
-
- /**
- * sourcePosition of the emitter setter
- * @param sourcePosition
- */
- setSourcePosition:function (sourcePosition) {
- this._sourcePosition = sourcePosition;
- },
-
- /**
- * Return Position variance of the emitter
- * @return {cc.Point | Object}
- */
- getPosVar:function () {
- return {x: this._posVar.x, y: this._posVar.y};
- },
-
- /**
- * Position variance of the emitter setter
- * @param {cc.Point} posVar
- */
- setPosVar:function (posVar) {
- this._posVar = posVar;
- },
-
- /**
- * Return life of each particle
- * @return {Number}
- */
- getLife:function () {
- return this._life;
- },
-
- /**
- * life of each particle setter
- * @param {Number} life
- */
- setLife:function (life) {
- this._life = life;
- },
-
- /**
- * Return life variance of each particle
- * @return {Number}
- */
- getLifeVar:function () {
- return this._lifeVar;
- },
-
- /**
- * life variance of each particle setter
- * @param {Number} lifeVar
- */
- setLifeVar:function (lifeVar) {
- this._lifeVar = lifeVar;
- },
-
- /**
- * Return angle of each particle
- * @return {Number}
- */
- getAngle:function () {
- return this._angle;
- },
-
- /**
- * angle of each particle setter
- * @param {Number} angle
- */
- setAngle:function (angle) {
- this._angle = angle;
- },
-
- /**
- * Return angle variance of each particle
- * @return {Number}
- */
- getAngleVar:function () {
- return this._angleVar;
- },
-
- /**
- * angle variance of each particle setter
- * @param angleVar
- */
- setAngleVar:function (angleVar) {
- this._angleVar = angleVar;
- },
-
- // mode A
- /**
- * Return Gravity of emitter
- * @return {cc.Point}
- */
- getGravity:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- var locGravity = this.modeA.gravity;
- return cc.p(locGravity.x, locGravity.y);
- },
-
- /**
- * Gravity of emitter setter
- * @param {cc.Point} gravity
- */
- setGravity:function (gravity) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.gravity = gravity;
- },
-
- /**
- * Return Speed of each particle
- * @return {Number}
- */
- getSpeed:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- return this.modeA.speed;
- },
-
- /**
- * Speed of each particle setter
- * @param {Number} speed
- */
- setSpeed:function (speed) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.speed = speed;
- },
-
- /**
- * return speed variance of each particle. Only available in 'Gravity' mode.
- * @return {Number}
- */
- getSpeedVar:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- return this.modeA.speedVar;
- },
-
- /**
- * speed variance of each particle setter. Only available in 'Gravity' mode.
- * @param {Number} speedVar
- */
- setSpeedVar:function (speedVar) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.speedVar = speedVar;
- },
-
- /**
- * Return tangential acceleration of each particle. Only available in 'Gravity' mode.
- * @return {Number}
- */
- getTangentialAccel:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- return this.modeA.tangentialAccel;
- },
-
- /**
- * Tangential acceleration of each particle setter. Only available in 'Gravity' mode.
- * @param {Number} tangentialAccel
- */
- setTangentialAccel:function (tangentialAccel) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.tangentialAccel = tangentialAccel;
- },
-
- /**
- * Return tangential acceleration variance of each particle. Only available in 'Gravity' mode.
- * @return {Number}
- */
- getTangentialAccelVar:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- return this.modeA.tangentialAccelVar;
- },
-
- /**
- * tangential acceleration variance of each particle setter. Only available in 'Gravity' mode.
- * @param {Number} tangentialAccelVar
- */
- setTangentialAccelVar:function (tangentialAccelVar) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.tangentialAccelVar = tangentialAccelVar;
- },
-
- /**
- * Return radial acceleration of each particle. Only available in 'Gravity' mode.
- * @return {Number}
- */
- getRadialAccel:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- return this.modeA.radialAccel;
- },
-
- /**
- * radial acceleration of each particle setter. Only available in 'Gravity' mode.
- * @param {Number} radialAccel
- */
- setRadialAccel:function (radialAccel) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.radialAccel = radialAccel;
- },
-
- /**
- * Return radial acceleration variance of each particle. Only available in 'Gravity' mode.
- * @return {Number}
- */
- getRadialAccelVar:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- return this.modeA.radialAccelVar;
- },
-
- /**
- * radial acceleration variance of each particle setter. Only available in 'Gravity' mode.
- * @param {Number} radialAccelVar
- */
- setRadialAccelVar:function (radialAccelVar) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.radialAccelVar = radialAccelVar;
- },
-
- /**
- * get the rotation of each particle to its direction Only available in 'Gravity' mode.
- * @returns {boolean}
- */
- getRotationIsDir: function(){
- cc.Assert( this._emitterMode === cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- return this.modeA.rotationIsDir;
- },
-
- /**
- * set the rotation of each particle to its direction Only available in 'Gravity' mode.
- * @param {boolean} t
- */
- setRotationIsDir: function(t){
- cc.Assert( this._emitterMode === cc.PARTICLE_MODE_GRAVITY, "Particle Mode should be Gravity");
- this.modeA.rotationIsDir = t;
- },
-
- // mode B
- /**
- * Return starting radius of the particles. Only available in 'Radius' mode.
- * @return {Number}
- */
- getStartRadius:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- return this.modeB.startRadius;
- },
-
- /**
- * starting radius of the particles setter. Only available in 'Radius' mode.
- * @param {Number} startRadius
- */
- setStartRadius:function (startRadius) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- this.modeB.startRadius = startRadius;
- },
-
- /**
- * Return starting radius variance of the particles. Only available in 'Radius' mode.
- * @return {Number}
- */
- getStartRadiusVar:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- return this.modeB.startRadiusVar;
- },
-
- /**
- * starting radius variance of the particles setter. Only available in 'Radius' mode.
- * @param {Number} startRadiusVar
- */
- setStartRadiusVar:function (startRadiusVar) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- this.modeB.startRadiusVar = startRadiusVar;
- },
-
- /**
- * Return ending radius of the particles. Only available in 'Radius' mode.
- * @return {Number}
- */
- getEndRadius:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- return this.modeB.endRadius;
- },
-
- /**
- * ending radius of the particles setter. Only available in 'Radius' mode.
- * @param {Number} endRadius
- */
- setEndRadius:function (endRadius) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- this.modeB.endRadius = endRadius;
- },
-
- /**
- * Return ending radius variance of the particles. Only available in 'Radius' mode.
- * @return {Number}
- */
- getEndRadiusVar:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- return this.modeB.endRadiusVar;
- },
-
- /**
- * ending radius variance of the particles setter. Only available in 'Radius' mode.
- * @param endRadiusVar
- */
- setEndRadiusVar:function (endRadiusVar) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- this.modeB.endRadiusVar = endRadiusVar;
- },
-
- /**
- * get Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
- * @return {Number}
- */
- getRotatePerSecond:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- return this.modeB.rotatePerSecond;
- },
-
- /**
- * set Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode.
- * @param {Number} degrees
- */
- setRotatePerSecond:function (degrees) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- this.modeB.rotatePerSecond = degrees;
- },
-
- /**
- * Return Variance in degrees for rotatePerSecond. Only available in 'Radius' mode.
- * @return {Number}
- */
- getRotatePerSecondVar:function () {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- return this.modeB.rotatePerSecondVar;
- },
-
- /**
- * Variance in degrees for rotatePerSecond setter. Only available in 'Radius' mode.
- * @param degrees
- */
- setRotatePerSecondVar:function (degrees) {
- cc.Assert(this._emitterMode == cc.PARTICLE_MODE_RADIUS, "Particle Mode should be Radius");
- this.modeB.rotatePerSecondVar = degrees;
- },
- //////////////////////////////////////////////////////////////////////////
-
- //don't use a transform matrix, this is faster
- setScale:function (scale, scaleY) {
- this._transformSystemDirty = true;
- cc.Node.prototype.setScale.call(this, scale, scaleY);
- },
-
- setRotation:function (newRotation) {
- this._transformSystemDirty = true;
- cc.Node.prototype.setRotation.call(this, newRotation);
- },
-
- setScaleX:function (newScaleX) {
- this._transformSystemDirty = true;
- cc.Node.prototype.setScaleX.call(this, newScaleX);
- },
-
- setScaleY:function (newScaleY) {
- this._transformSystemDirty = true;
- cc.Node.prototype.setScaleY.call(this, newScaleY);
- },
-
- /**
- * get start size in pixels of each particle
- * @return {Number}
- */
- getStartSize:function () {
- return this._startSize;
- },
-
- /**
- * set start size in pixels of each particle
- * @param {Number} startSize
- */
- setStartSize:function (startSize) {
- this._startSize = startSize;
- },
-
- /**
- * get size variance in pixels of each particle
- * @return {Number}
- */
- getStartSizeVar:function () {
- return this._startSizeVar;
- },
-
- /**
- * set size variance in pixels of each particle
- * @param {Number} startSizeVar
- */
- setStartSizeVar:function (startSizeVar) {
- this._startSizeVar = startSizeVar;
- },
-
- /**
- * get end size in pixels of each particle
- * @return {Number}
- */
- getEndSize:function () {
- return this._endSize;
- },
-
- /**
- * set end size in pixels of each particle
- * @param endSize
- */
- setEndSize:function (endSize) {
- this._endSize = endSize;
- },
-
- /**
- * get end size variance in pixels of each particle
- * @return {Number}
- */
- getEndSizeVar:function () {
- return this._endSizeVar;
- },
-
- /**
- * set end size variance in pixels of each particle
- * @param {Number} endSizeVar
- */
- setEndSizeVar:function (endSizeVar) {
- this._endSizeVar = endSizeVar;
- },
-
- /**
- * set start color of each particle
- * @return {cc.Color4F}
- */
- getStartColor:function () {
- return this._startColor;
- },
-
- /**
- * get start color of each particle
- * @param {cc.Color4F} startColor
- */
- setStartColor:function (startColor) {
- if (startColor instanceof cc.Color3B)
- startColor = cc.c4FFromccc3B(startColor);
- this._startColor = startColor;
- },
-
- /**
- * get start color variance of each particle
- * @return {cc.Color4F}
- */
- getStartColorVar:function () {
- return this._startColorVar;
- },
-
- /**
- * set start color variance of each particle
- * @param {cc.Color4F} startColorVar
- */
- setStartColorVar:function (startColorVar) {
- if (startColorVar instanceof cc.Color3B)
- startColorVar = cc.c4FFromccc3B(startColorVar);
- this._startColorVar = startColorVar;
- },
-
- /**
- * get end color and end color variation of each particle
- * @return {cc.Color4F}
- */
- getEndColor:function () {
- return this._endColor;
- },
-
- /**
- * set end color and end color variation of each particle
- * @param {cc.Color4F} endColor
- */
- setEndColor:function (endColor) {
- if (endColor instanceof cc.Color3B)
- endColor = cc.c4FFromccc3B(endColor);
- this._endColor = endColor;
- },
-
- /**
- * get end color variance of each particle
- * @return {cc.Color4F}
- */
- getEndColorVar:function () {
- return this._endColorVar;
- },
-
- /**
- * set end color variance of each particle
- * @param {cc.Color4F} endColorVar
- */
- setEndColorVar:function (endColorVar) {
- if (endColorVar instanceof cc.Color3B)
- endColorVar = cc.c4FFromccc3B(endColorVar);
- this._endColorVar = endColorVar;
- },
-
- /**
- * get initial angle of each particle
- * @return {Number}
- */
- getStartSpin:function () {
- return this._startSpin;
- },
-
- /**
- * set initial angle of each particle
- * @param {Number} startSpin
- */
- setStartSpin:function (startSpin) {
- this._startSpin = startSpin;
- },
-
- /**
- * get initial angle variance of each particle
- * @return {Number}
- */
- getStartSpinVar:function () {
- return this._startSpinVar;
- },
-
- /**
- * set initial angle variance of each particle
- * @param {Number} startSpinVar
- */
- setStartSpinVar:function (startSpinVar) {
- this._startSpinVar = startSpinVar;
- },
-
- /**
- * get end angle of each particle
- * @return {Number}
- */
- getEndSpin:function () {
- return this._endSpin;
- },
-
- /**
- * set end angle of each particle
- * @param {Number} endSpin
- */
- setEndSpin:function (endSpin) {
- this._endSpin = endSpin;
- },
-
- /**
- * get end angle variance of each particle
- * @return {Number}
- */
- getEndSpinVar:function () {
- return this._endSpinVar;
- },
-
- /**
- * set end angle variance of each particle
- * @param {Number} endSpinVar
- */
- setEndSpinVar:function (endSpinVar) {
- this._endSpinVar = endSpinVar;
- },
-
- /**
- * get emission rate of the particles
- * @return {Number}
- */
- getEmissionRate:function () {
- return this._emissionRate;
- },
-
- /**
- * set emission rate of the particles
- * @param {Number} emissionRate
- */
- setEmissionRate:function (emissionRate) {
- this._emissionRate = emissionRate;
- },
-
- /**
- * get maximum particles of the system
- * @return {Number}
- */
- getTotalParticles:function () {
- return this._totalParticles;
- },
-
- /**
- * set maximum particles of the system
- * @param {Number} tp totalParticles
- */
- setTotalParticles:function (tp) {
- //cc.Assert(tp <= this._allocatedParticles, "Particle: resizing particle array only supported for quads");
- if (cc.renderContextType === cc.CANVAS){
- this._totalParticles = (tp < 200) ? tp : 200;
- return;
- }
-
- // If we are setting the total numer of particles to a number higher
- // than what is allocated, we need to allocate new arrays
- if (tp > this._allocatedParticles) {
- var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
- // Allocate new memory
- this._indices = new Uint16Array(tp * 6);
- var locQuadsArrayBuffer = new ArrayBuffer(tp * quadSize);
- //TODO need fix
- // Assign pointers
- var locParticles = [];
- var locQuads = [];
- for (var j = 0; j < tp; j++) {
- locParticles[j] = new cc.Particle();
- locQuads[j] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, j * quadSize);
- }
- this._allocatedParticles = tp;
- this._totalParticles = tp;
-
- // Init particles
- if (this._batchNode) {
- for (var i = 0; i < tp; i++)
- locParticles[i].atlasIndex = i;
- }
-
- this._particles = locParticles;
- this._quadsArrayBuffer = locQuadsArrayBuffer;
- this._quads = locQuads;
-
- this.initIndices();
- //if (cc.TEXTURE_ATLAS_USE_VAO)
- // this._setupVBOandVAO();
- //else
- this._setupVBO();
-
- //set the texture coord
- if(this._texture){
- var size = this._texture.getContentSize();
- this.initTexCoordsWithRect(cc.rect(0, 0, size.width, size.height));
- }
- } else
- this._totalParticles = tp;
- this.resetSystem();
- },
-
- /**
- * get Texture of Particle System
- * @return {cc.Texture2D}
- */
- getTexture:function () {
- return this._texture;
- },
-
- /**
- * set Texture of Particle System
- * @param {cc.Texture2D } texture
- */
- setTexture:function (texture) {
- if(texture.isLoaded()){
- var size = texture.getContentSize();
- this.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height));
- } else {
- this._textureLoaded = false;
- texture.addLoadedEventListener(function(sender){
- this._textureLoaded = true;
- var size = sender.getContentSize();
- this.setTextureWithRect(sender, cc.rect(0, 0, size.width, size.height));
- }, this);
- }
- },
-
- /** conforms to CocosNodeTexture protocol */
- /**
- * get BlendFunc of Particle System
- * @return {cc.BlendFunc}
- */
- getBlendFunc:function () {
- return this._blendFunc;
- },
-
- /**
- * set BlendFunc of Particle System
- * @param {Number} src
- * @param {Number} dst
- */
- setBlendFunc:function (src, dst) {
- if (arguments.length == 1) {
- if (this._blendFunc != src) {
- this._blendFunc = src;
- this._updateBlendFunc();
- }
- } else {
- if (this._blendFunc.src != src || this._blendFunc.dst != dst) {
- this._blendFunc = {src:src, dst:dst};
- this._updateBlendFunc();
- }
- }
- },
-
- /**
- * does the alpha value modify color getter
- * @return {Boolean}
- */
- getOpacityModifyRGB:function () {
- return this._opacityModifyRGB;
- },
-
- /**
- * does the alpha value modify color setter
- * @param newValue
- */
- setOpacityModifyRGB:function (newValue) {
- this._opacityModifyRGB = newValue;
- },
-
- /**
- * whether or not the particles are using blend additive.
- * If enabled, the following blending function will be used.
- *
- * @return {Boolean}
- * @example
- * source blend function = GL_SRC_ALPHA;
- * dest blend function = GL_ONE;
- */
- isBlendAdditive:function () {
- return (( this._blendFunc.src == gl.SRC_ALPHA && this._blendFunc.dst == gl.ONE) || (this._blendFunc.src == gl.ONE && this._blendFunc.dst == gl.ONE));
- },
-
- /**
- * whether or not the particles are using blend additive.
- * If enabled, the following blending function will be used.
- *
- * @param {Boolean} isBlendAdditive
- */
- setBlendAdditive:function (isBlendAdditive) {
- var locBlendFunc = this._blendFunc;
- if (isBlendAdditive) {
- locBlendFunc.src = gl.SRC_ALPHA;
- locBlendFunc.dst = gl.ONE;
- } else {
- if (cc.renderContextType === cc.WEBGL) {
- if (this._texture && !this._texture.hasPremultipliedAlpha()) {
- locBlendFunc.src = gl.SRC_ALPHA;
- locBlendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
- } else {
- locBlendFunc.src = cc.BLEND_SRC;
- locBlendFunc.dst = cc.BLEND_DST;
- }
- } else {
- locBlendFunc.src = cc.BLEND_SRC;
- locBlendFunc.dst = cc.BLEND_DST;
- }
- }
- },
-
- /**
- * get particles movement type: Free or Grouped
- * @return {Number}
- */
- getPositionType:function () {
- return this._positionType;
- },
-
- /**
- * set particles movement type: Free or Grouped
- * @param {Number} positionType
- */
- setPositionType:function (positionType) {
- this._positionType = positionType;
- },
-
- /**
- * return whether or not the node will be auto-removed when it has no particles left.
- * By default it is false.
- *
- * @return {Boolean}
- */
- isAutoRemoveOnFinish:function () {
- return this._isAutoRemoveOnFinish;
- },
-
- /**
- * set whether or not the node will be auto-removed when it has no particles left.
- * By default it is false.
- *
- * @param {Boolean} isAutoRemoveOnFinish
- */
- setAutoRemoveOnFinish:function (isAutoRemoveOnFinish) {
- this._isAutoRemoveOnFinish = isAutoRemoveOnFinish;
- },
-
- /**
- * return kind of emitter modes
- * @return {Number}
- */
- getEmitterMode:function () {
- return this._emitterMode;
- },
-
- /**
- * Switch between different kind of emitter modes:
- * - CCPARTICLE_MODE_GRAVITY: uses gravity, speed, radial and tangential acceleration
- * - CCPARTICLE_MODE_RADIUS: uses radius movement + rotation
- *
- * @param {Number} emitterMode
- */
- setEmitterMode:function (emitterMode) {
- this._emitterMode = emitterMode;
- },
-
- /**
- * initializes a cc.ParticleSystem
- */
- init:function () {
- return this.initWithTotalParticles(150);
- },
-
- /**
- *
- * initializes a CCParticleSystem from a plist file.
- * This plist files can be creted manually or with Particle Designer:
- * http://particledesigner.71squared.com/
- *
- * @param {String} plistFile
- * @return {boolean}
- */
- initWithFile:function (plistFile) {
- this._plistFile = plistFile;
- var fileUtils = cc.FileUtils.getInstance();
- var fullPath = fileUtils.fullPathForFilename(plistFile);
-
- var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(fullPath);
-
- cc.Assert(dict != null, "Particles: file not found");
-
- // XXX compute path from a path, should define a function somewhere to do it
- return this.initWithDictionary(dict, "");
- },
-
- /**
- * return bounding box of particle system in world space
- * @return {cc.Rect}
- */
- getBoundingBoxToWorld:function () {
- return cc.rect(0, 0, cc.canvas.width, cc.canvas.height);
- },
-
- /**
- * initializes a particle system from a NSDictionary and the path from where to load the png
- * @param {object} dictionary
- * @param {String} dirname
- * @return {Boolean}
- */
- initWithDictionary:function (dictionary, dirname) {
- var ret = false;
- var buffer = null;
- var image = null;
- var locValueForKey = this._valueForKey;
-
- var maxParticles = parseInt(locValueForKey("maxParticles", dictionary));
- // self, not super
- if (this.initWithTotalParticles(maxParticles)) {
- // angle
- this._angle = parseFloat(locValueForKey("angle", dictionary));
- this._angleVar = parseFloat(locValueForKey("angleVariance", dictionary));
-
- // duration
- this._duration = parseFloat(locValueForKey("duration", dictionary));
-
- // blend function
- this._blendFunc.src = parseInt(locValueForKey("blendFuncSource", dictionary));
- this._blendFunc.dst = parseInt(locValueForKey("blendFuncDestination", dictionary));
-
- // color
- var locStartColor = this._startColor;
- locStartColor.r = parseFloat(locValueForKey("startColorRed", dictionary));
- locStartColor.g = parseFloat(locValueForKey("startColorGreen", dictionary));
- locStartColor.b = parseFloat(locValueForKey("startColorBlue", dictionary));
- locStartColor.a = parseFloat(locValueForKey("startColorAlpha", dictionary));
-
- var locStartColorVar = this._startColorVar;
- locStartColorVar.r = parseFloat(locValueForKey("startColorVarianceRed", dictionary));
- locStartColorVar.g = parseFloat(locValueForKey("startColorVarianceGreen", dictionary));
- locStartColorVar.b = parseFloat(locValueForKey("startColorVarianceBlue", dictionary));
- locStartColorVar.a = parseFloat(locValueForKey("startColorVarianceAlpha", dictionary));
-
- var locEndColor = this._endColor;
- locEndColor.r = parseFloat(locValueForKey("finishColorRed", dictionary));
- locEndColor.g = parseFloat(locValueForKey("finishColorGreen", dictionary));
- locEndColor.b = parseFloat(locValueForKey("finishColorBlue", dictionary));
- locEndColor.a = parseFloat(locValueForKey("finishColorAlpha", dictionary));
-
- var locEndColorVar = this._endColorVar;
- locEndColorVar.r = parseFloat(locValueForKey("finishColorVarianceRed", dictionary));
- locEndColorVar.g = parseFloat(locValueForKey("finishColorVarianceGreen", dictionary));
- locEndColorVar.b = parseFloat(locValueForKey("finishColorVarianceBlue", dictionary));
- locEndColorVar.a = parseFloat(locValueForKey("finishColorVarianceAlpha", dictionary));
-
- // particle size
- this._startSize = parseFloat(locValueForKey("startParticleSize", dictionary));
- this._startSizeVar = parseFloat(locValueForKey("startParticleSizeVariance", dictionary));
- this._endSize = parseFloat(locValueForKey("finishParticleSize", dictionary));
- this._endSizeVar = parseFloat(locValueForKey("finishParticleSizeVariance", dictionary));
-
- // position
- var x = parseFloat(locValueForKey("sourcePositionx", dictionary));
- var y = parseFloat(locValueForKey("sourcePositiony", dictionary));
- this.setPosition(x, y);
- this._posVar.x = parseFloat(locValueForKey("sourcePositionVariancex", dictionary));
- this._posVar.y = parseFloat(locValueForKey("sourcePositionVariancey", dictionary));
-
- // Spinning
- this._startSpin = parseFloat(locValueForKey("rotationStart", dictionary));
- this._startSpinVar = parseFloat(locValueForKey("rotationStartVariance", dictionary));
- this._endSpin = parseFloat(locValueForKey("rotationEnd", dictionary));
- this._endSpinVar = parseFloat(locValueForKey("rotationEndVariance", dictionary));
-
- this._emitterMode = parseInt(locValueForKey("emitterType", dictionary));
-
- // Mode A: Gravity + tangential accel + radial accel
- if (this._emitterMode == cc.PARTICLE_MODE_GRAVITY) {
- var locModeA = this.modeA;
- // gravity
- locModeA.gravity.x = parseFloat(locValueForKey("gravityx", dictionary));
- locModeA.gravity.y = parseFloat(locValueForKey("gravityy", dictionary));
-
- // speed
- locModeA.speed = parseFloat(locValueForKey("speed", dictionary));
- locModeA.speedVar = parseFloat(locValueForKey("speedVariance", dictionary));
-
- // radial acceleration
- var pszTmp = locValueForKey("radialAcceleration", dictionary);
- locModeA.radialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
-
- pszTmp = locValueForKey("radialAccelVariance", dictionary);
- locModeA.radialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
-
- // tangential acceleration
- pszTmp = locValueForKey("tangentialAcceleration", dictionary);
- locModeA.tangentialAccel = (pszTmp) ? parseFloat(pszTmp) : 0;
-
- pszTmp = locValueForKey("tangentialAccelVariance", dictionary);
- locModeA.tangentialAccelVar = (pszTmp) ? parseFloat(pszTmp) : 0;
-
- // rotation is dir
- var locRotationIsDir = locValueForKey("rotationIsDir", dictionary).toLowerCase();
- locModeA.rotationIsDir = (locRotationIsDir != null && (locRotationIsDir === "true" || locRotationIsDir === "1"));
- } else if (this._emitterMode == cc.PARTICLE_MODE_RADIUS) {
- // or Mode B: radius movement
- var locModeB = this.modeB;
- locModeB.startRadius = parseFloat(locValueForKey("maxRadius", dictionary));
- locModeB.startRadiusVar = parseFloat(locValueForKey("maxRadiusVariance", dictionary));
- locModeB.endRadius = parseFloat(locValueForKey("minRadius", dictionary));
- locModeB.endRadiusVar = 0;
- locModeB.rotatePerSecond = parseFloat(locValueForKey("rotatePerSecond", dictionary));
- locModeB.rotatePerSecondVar = parseFloat(locValueForKey("rotatePerSecondVariance", dictionary));
- } else {
- cc.Assert(false, "Invalid emitterType in config file");
- return false;
- }
-
- // life span
- this._life = parseFloat(locValueForKey("particleLifespan", dictionary));
- this._lifeVar = parseFloat(locValueForKey("particleLifespanVariance", dictionary));
-
- // emission Rate
- this._emissionRate = this._totalParticles / this._life;
-
- //don't get the internal texture if a batchNode is used
- if (!this._batchNode) {
- // Set a compatible default for the alpha transfer
- this._opacityModifyRGB = false;
-
- // texture
- // Try to get the texture from the cache
- var textureName = locValueForKey("textureFileName", dictionary);
- var fileUtils = cc.FileUtils.getInstance();
- var imgPath = fileUtils.fullPathFromRelativeFile(textureName, this._plistFile);
- var tex = cc.TextureCache.getInstance().textureForKey(imgPath);
-
- if (tex) {
- this.setTexture(tex);
- } else {
- var textureData = locValueForKey("textureImageData", dictionary);
-
- if (textureData && textureData.length == 0) {
- cc.Assert(textureData, "cc.ParticleSystem.initWithDictory:textureImageData is null");
- tex = cc.TextureCache.getInstance().addImage(imgPath);
- if (!tex)
- return false;
- this.setTexture(tex);
- } else {
- buffer = cc.unzipBase64AsArray(textureData, 1);
- if (!buffer) {
- cc.log("cc.ParticleSystem: error decoding or ungzipping textureImageData");
- return false;
- }
-
- var imageFormat = cc.getImageFormatByData(buffer);
-
- if(imageFormat !== cc.FMT_TIFF && imageFormat !== cc.FMT_PNG){
- cc.log("cc.ParticleSystem: unknown image format with Data");
- return false;
- }
-
- var canvasObj = document.createElement("canvas");
- if(imageFormat === cc.FMT_PNG){
- var myPngObj = new cc.PNGReader(buffer);
- myPngObj.render(canvasObj);
-
- } else {
- var myTIFFObj = cc.TIFFReader.getInstance();
- myTIFFObj.parseTIFF(buffer,canvasObj);
- }
-
- var imgFullPath = fileUtils.fullPathForFilename(imgPath);
- cc.TextureCache.getInstance().cacheImage(imgFullPath, canvasObj);
-
- var addTexture = cc.TextureCache.getInstance().textureForKey(imgPath);
-
- cc.Assert(addTexture != null, "cc.ParticleSystem: error loading the texture");
-
- this.setTexture(addTexture);
- }
- }
-
- }
- ret = true;
- }
- return ret;
- },
-
- /**
- * Initializes a system with a fixed number of particles
- * @param {Number} numberOfParticles
- * @return {Boolean}
- */
- initWithTotalParticles:function (numberOfParticles) {
- this._totalParticles = numberOfParticles;
-
- var i;
- this._particles = [];
- for(i = 0; i< numberOfParticles; i++){
- this._particles[i] = new cc.Particle();
- }
-
- if (!this._particles) {
- cc.log("Particle system: not enough memory");
- return false;
- }
- this._allocatedParticles = numberOfParticles;
-
- if (this._batchNode)
- for (i = 0; i < this._totalParticles; i++)
- this._particles[i].atlasIndex = i;
-
- // default, active
- this._isActive = true;
-
- // default blend function
- this._blendFunc.src = cc.BLEND_SRC;
- this._blendFunc.dst = cc.BLEND_DST;
-
- // default movement type;
- this._positionType = cc.PARTICLE_TYPE_FREE;
-
- // by default be in mode A:
- this._emitterMode = cc.PARTICLE_MODE_GRAVITY;
-
- // default: modulate
- // XXX: not used
- // colorModulate = YES;
- this._isAutoRemoveOnFinish = false;
-
- // Optimization: compile udpateParticle method
- //updateParticleSel = @selector(updateQuadWithParticle:newPosition:);
- //updateParticleImp = (CC_UPDATE_PARTICLE_IMP) [self methodForSelector:updateParticleSel];
-
- //for batchNode
- this._transformSystemDirty = false;
-
- // udpate after action in run!
- this.scheduleUpdateWithPriority(1);
-
- if(cc.renderContextType === cc.WEBGL){
- // allocating data space
- if (!this._allocMemory())
- return false;
-
- this.initIndices();
- //if (cc.TEXTURE_ATLAS_USE_VAO)
- // this._setupVBOandVAO();
- //else
- this._setupVBO();
-
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
- }
-
- return true;
- },
-
- destroyParticleSystem:function () {
- this.unscheduleUpdate();
- },
-
- /**
- * Add a particle to the emitter
- * @return {Boolean}
- */
- addParticle: function () {
- if (this.isFull())
- return false;
- var particle, particles = this._particles;
- if (cc.renderContextType === cc.CANVAS) {
- if (this._particleCount < particles.length) {
- particle = particles[this._particleCount];
- } else {
- particle = new cc.Particle();
- particles.push(particle);
- }
- } else {
- particle = particles[this._particleCount];
- }
- this.initParticle(particle);
- ++this._particleCount;
- return true;
- },
-
- /**
- * Initializes a particle
- * @param {cc.Particle} particle
- */
- initParticle:function (particle) {
- var locRandomMinus11 = cc.RANDOM_MINUS1_1;
- // timeToLive
- // no negative life. prevent division by 0
- particle.timeToLive = this._life + this._lifeVar * locRandomMinus11();
- particle.timeToLive = Math.max(0, particle.timeToLive);
-
- // position
- particle.pos.x = this._sourcePosition.x + this._posVar.x * locRandomMinus11();
- particle.pos.y = this._sourcePosition.y + this._posVar.y * locRandomMinus11();
-
- // Color
- var start, end;
- var locStartColor = this._startColor, locStartColorVar = this._startColorVar;
- var locEndColor = this._endColor, locEndColorVar = this._endColorVar;
- if (cc.renderContextType === cc.CANVAS) {
- start = new cc.Color4F(
- cc.clampf(locStartColor.r + locStartColorVar.r * locRandomMinus11(), 0, 1),
- cc.clampf(locStartColor.g + locStartColorVar.g * locRandomMinus11(), 0, 1),
- cc.clampf(locStartColor.b + locStartColorVar.b * locRandomMinus11(), 0, 1),
- cc.clampf(locStartColor.a + locStartColorVar.a * locRandomMinus11(), 0, 1)
- );
- end = new cc.Color4F(
- cc.clampf(locEndColor.r + locEndColorVar.r * locRandomMinus11(), 0, 1),
- cc.clampf(locEndColor.g + locEndColorVar.g * locRandomMinus11(), 0, 1),
- cc.clampf(locEndColor.b + locEndColorVar.b * locRandomMinus11(), 0, 1),
- cc.clampf(locEndColor.a + locEndColorVar.a * locRandomMinus11(), 0, 1)
- );
- } else {
- start = {
- r: cc.clampf(locStartColor.r + locStartColorVar.r * locRandomMinus11(), 0, 1),
- g: cc.clampf(locStartColor.g + locStartColorVar.g * locRandomMinus11(), 0, 1),
- b: cc.clampf(locStartColor.b + locStartColorVar.b * locRandomMinus11(), 0, 1),
- a: cc.clampf(locStartColor.a + locStartColorVar.a * locRandomMinus11(), 0, 1)
- };
- end = {
- r: cc.clampf(locEndColor.r + locEndColorVar.r * locRandomMinus11(), 0, 1),
- g: cc.clampf(locEndColor.g + locEndColorVar.g * locRandomMinus11(), 0, 1),
- b: cc.clampf(locEndColor.b + locEndColorVar.b * locRandomMinus11(), 0, 1),
- a: cc.clampf(locEndColor.a + locEndColorVar.a * locRandomMinus11(), 0, 1)
- };
- }
-
- particle.color = start;
- var locParticleDeltaColor = particle.deltaColor, locParticleTimeToLive = particle.timeToLive;
- locParticleDeltaColor.r = (end.r - start.r) / locParticleTimeToLive;
- locParticleDeltaColor.g = (end.g - start.g) / locParticleTimeToLive;
- locParticleDeltaColor.b = (end.b - start.b) / locParticleTimeToLive;
- locParticleDeltaColor.a = (end.a - start.a) / locParticleTimeToLive;
-
- // size
- var startS = this._startSize + this._startSizeVar * locRandomMinus11();
- startS = Math.max(0, startS); // No negative value
-
- particle.size = startS;
- if (this._endSize === cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE) {
- particle.deltaSize = 0;
- } else {
- var endS = this._endSize + this._endSizeVar * locRandomMinus11();
- endS = Math.max(0, endS); // No negative values
- particle.deltaSize = (endS - startS) / locParticleTimeToLive;
- }
-
- // rotation
- var startA = this._startSpin + this._startSpinVar * locRandomMinus11();
- var endA = this._endSpin + this._endSpinVar * locRandomMinus11();
- particle.rotation = startA;
- particle.deltaRotation = (endA - startA) / locParticleTimeToLive;
-
- // position
- if (this._positionType == cc.PARTICLE_TYPE_FREE)
- particle.startPos = this.convertToWorldSpace(this._pointZeroForParticle);
- else if (this._positionType == cc.PARTICLE_TYPE_RELATIVE){
- particle.startPos.x = this._position.x;
- particle.startPos.y = this._position.y;
- }
-
- // direction
- var a = cc.DEGREES_TO_RADIANS(this._angle + this._angleVar * locRandomMinus11());
-
- // Mode Gravity: A
- if (this._emitterMode === cc.PARTICLE_MODE_GRAVITY) {
- var locModeA = this.modeA, locParticleModeA = particle.modeA;
- var s = locModeA.speed + locModeA.speedVar * locRandomMinus11();
-
- // direction
- locParticleModeA.dir.x = Math.cos(a);
- locParticleModeA.dir.y = Math.sin(a);
- cc.pMultIn(locParticleModeA.dir, s);
-
- // radial accel
- locParticleModeA.radialAccel = locModeA.radialAccel + locModeA.radialAccelVar * locRandomMinus11();
-
- // tangential accel
- locParticleModeA.tangentialAccel = locModeA.tangentialAccel + locModeA.tangentialAccelVar * locRandomMinus11();
-
- // rotation is dir
- if(locModeA.rotationIsDir)
- particle.rotation = -cc.RADIANS_TO_DEGREES(cc.pToAngle(locParticleModeA.dir));
- } else {
- // Mode Radius: B
- var locModeB = this.modeB, locParitlceModeB = particle.modeB;
-
- // Set the default diameter of the particle from the source position
- var startRadius = locModeB.startRadius + locModeB.startRadiusVar * locRandomMinus11();
- var endRadius = locModeB.endRadius + locModeB.endRadiusVar * locRandomMinus11();
-
- locParitlceModeB.radius = startRadius;
- locParitlceModeB.deltaRadius = (locModeB.endRadius === cc.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS) ? 0 : (endRadius - startRadius) / locParticleTimeToLive;
-
- locParitlceModeB.angle = a;
- locParitlceModeB.degreesPerSecond = cc.DEGREES_TO_RADIANS(locModeB.rotatePerSecond + locModeB.rotatePerSecondVar * locRandomMinus11());
- }
- },
-
- /**
- * stop emitting particles. Running particles will continue to run until they die
- */
- stopSystem:function () {
- this._isActive = false;
- this._elapsed = this._duration;
- this._emitCounter = 0;
- },
-
- /**
- * Kill all living particles.
- */
- resetSystem:function () {
- this._isActive = true;
- this._elapsed = 0;
- var locParticles = this._particles;
- for (this._particleIdx = 0; this._particleIdx < this._particleCount; ++this._particleIdx)
- locParticles[this._particleIdx].timeToLive = 0 ;
- },
-
- /**
- * whether or not the system is full
- * @return {Boolean}
- */
- isFull:function () {
- return (this._particleCount >= this._totalParticles);
- },
-
- /**
- * should be overridden by subclasses
- * @param {cc.Particle} particle
- * @param {cc.Point} newPosition
- */
- updateQuadWithParticle:function (particle, newPosition) {
- var quad = null;
- if (this._batchNode) {
- var batchQuads = this._batchNode.getTextureAtlas().getQuads();
- quad = batchQuads[this._atlasIndex + particle.atlasIndex];
- this._batchNode.getTextureAtlas()._dirty = true;
- } else
- quad = this._quads[this._particleIdx];
-
- var r, g, b, a;
- if(this._opacityModifyRGB){
- r = 0 | (particle.color.r * particle.color.a * 255);
- g = 0 | (particle.color.g * particle.color.a * 255);
- b = 0 | (particle.color.b * particle.color.a * 255);
- a = 0 | (particle.color.a * 255);
- }else{
- r = 0 | (particle.color.r * 255);
- g = 0 | (particle.color.g * 255);
- b = 0 | (particle.color.b * 255);
- a = 0 | (particle.color.a * 255);
- }
-
- var locColors = quad.bl.colors;
- locColors.r = r;
- locColors.g = g;
- locColors.b = b;
- locColors.a = a;
-
- locColors = quad.br.colors;
- locColors.r = r;
- locColors.g = g;
- locColors.b = b;
- locColors.a = a;
-
- locColors = quad.tl.colors;
- locColors.r = r;
- locColors.g = g;
- locColors.b = b;
- locColors.a = a;
-
- locColors = quad.tr.colors;
- locColors.r = r;
- locColors.g = g;
- locColors.b = b;
- locColors.a = a;
-
- // vertices
- var size_2 = particle.size / 2;
- if (particle.rotation) {
- var x1 = -size_2;
- var y1 = -size_2;
-
- var x2 = size_2;
- var y2 = size_2;
- var x = newPosition.x;
- var y = newPosition.y;
-
- var rad = -cc.DEGREES_TO_RADIANS(particle.rotation);
- var cr = Math.cos(rad);
- var sr = Math.sin(rad);
- var ax = x1 * cr - y1 * sr + x;
- var ay = x1 * sr + y1 * cr + y;
- var bx = x2 * cr - y1 * sr + x;
- var by = x2 * sr + y1 * cr + y;
- var cx = x2 * cr - y2 * sr + x;
- var cy = x2 * sr + y2 * cr + y;
- var dx = x1 * cr - y2 * sr + x;
- var dy = x1 * sr + y2 * cr + y;
-
- // bottom-left
- quad.bl.vertices.x = ax;
- quad.bl.vertices.y = ay;
-
- // bottom-right vertex:
- quad.br.vertices.x = bx;
- quad.br.vertices.y = by;
-
- // top-left vertex:
- quad.tl.vertices.x = dx;
- quad.tl.vertices.y = dy;
-
- // top-right vertex:
- quad.tr.vertices.x = cx;
- quad.tr.vertices.y = cy;
- } else {
- // bottom-left vertex:
- quad.bl.vertices.x = newPosition.x - size_2;
- quad.bl.vertices.y = newPosition.y - size_2;
-
- // bottom-right vertex:
- quad.br.vertices.x = newPosition.x + size_2;
- quad.br.vertices.y = newPosition.y - size_2;
-
- // top-left vertex:
- quad.tl.vertices.x = newPosition.x - size_2;
- quad.tl.vertices.y = newPosition.y + size_2;
-
- // top-right vertex:
- quad.tr.vertices.x = newPosition.x + size_2;
- quad.tr.vertices.y = newPosition.y + size_2;
- }
- },
-
- /**
- * should be overridden by subclasses
- */
- postStep:function () {
- if (cc.renderContextType === cc.WEBGL) {
- var gl = cc.renderContext;
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
- gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
-
- // Option 2: Data
- // glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * particleCount, quads_, GL_DYNAMIC_DRAW);
-
- // Option 3: Orphaning + glMapBuffer
- // glBufferData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0])*m_uTotalParticles, NULL, GL_STREAM_DRAW);
- // void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
- // memcpy(buf, m_pQuads, sizeof(m_pQuads[0])*m_uTotalParticles);
- // glUnmapBuffer(GL_ARRAY_BUFFER);
-
- //cc.CHECK_GL_ERROR_DEBUG();
- }
- },
-
- /**
- * update emitter's status
- * @override
- * @param {Number} dt delta time
- */
- update:function (dt) {
- if (this._isActive && this._emissionRate) {
- var rate = 1.0 / this._emissionRate;
- //issue #1201, prevent bursts of particles, due to too high emitCounter
- if (this._particleCount < this._totalParticles)
- this._emitCounter += dt;
-
- while ((this._particleCount < this._totalParticles) && (this._emitCounter > rate)) {
- this.addParticle();
- this._emitCounter -= rate;
- }
-
- this._elapsed += dt;
- if (this._duration != -1 && this._duration < this._elapsed)
- this.stopSystem();
- }
- this._particleIdx = 0;
-
- var currentPosition = cc.Particle.TemporaryPoints[0];
- if (this._positionType == cc.PARTICLE_TYPE_FREE) {
- cc.pIn(currentPosition, this.convertToWorldSpace(this._pointZeroForParticle));
- } else if (this._positionType == cc.PARTICLE_TYPE_RELATIVE) {
- currentPosition.x = this._position.x;
- currentPosition.y = this._position.y;
- }
-
- if (this._visible) {
-
- // Used to reduce memory allocation / creation within the loop
- var tpa = cc.Particle.TemporaryPoints[1],
- tpb = cc.Particle.TemporaryPoints[2],
- tpc = cc.Particle.TemporaryPoints[3];
-
- var locParticles = this._particles;
- while (this._particleIdx < this._particleCount) {
-
- // Reset the working particles
- cc.pZeroIn(tpa);
- cc.pZeroIn(tpb);
- cc.pZeroIn(tpc);
-
- var selParticle = locParticles[this._particleIdx];
-
- // life
- selParticle.timeToLive -= dt;
-
- if (selParticle.timeToLive > 0) {
- // Mode A: gravity, direction, tangential accel & radial accel
- if (this._emitterMode == cc.PARTICLE_MODE_GRAVITY) {
-
- var tmp = tpc, radial = tpa, tangential = tpb;
-
- // radial acceleration
- if (selParticle.pos.x || selParticle.pos.y) {
- cc.pIn(radial, selParticle.pos);
- cc.pNormalizeIn(radial);
- } else {
- cc.pZeroIn(radial);
- }
-
- cc.pIn(tangential, radial);
- cc.pMultIn(radial, selParticle.modeA.radialAccel);
-
- // tangential acceleration
- var newy = tangential.x;
- tangential.x = -tangential.y;
- tangential.y = newy;
-
- cc.pMultIn(tangential, selParticle.modeA.tangentialAccel);
-
- cc.pIn(tmp, radial);
- cc.pAddIn(tmp, tangential);
- cc.pAddIn(tmp, this.modeA.gravity);
- cc.pMultIn(tmp, dt);
- cc.pAddIn(selParticle.modeA.dir, tmp);
-
-
- cc.pIn(tmp, selParticle.modeA.dir);
- cc.pMultIn(tmp, dt);
- cc.pAddIn(selParticle.pos, tmp);
-
- } else {
- // Mode B: radius movement
- var selModeB = selParticle.modeB;
- // Update the angle and radius of the particle.
- selModeB.angle += selModeB.degreesPerSecond * dt;
- selModeB.radius += selModeB.deltaRadius * dt;
-
- selParticle.pos.x = -Math.cos(selModeB.angle) * selModeB.radius;
- selParticle.pos.y = -Math.sin(selModeB.angle) * selModeB.radius;
- }
-
- // color
- if (!this._dontTint) {
- selParticle.color.r += (selParticle.deltaColor.r * dt);
- selParticle.color.g += (selParticle.deltaColor.g * dt);
- selParticle.color.b += (selParticle.deltaColor.b * dt);
- selParticle.color.a += (selParticle.deltaColor.a * dt);
- selParticle.isChangeColor = true;
- }
-
- // size
- selParticle.size += (selParticle.deltaSize * dt);
- selParticle.size = Math.max(0, selParticle.size);
-
- // angle
- selParticle.rotation += (selParticle.deltaRotation * dt);
-
- //
- // update values in quad
- //
- var newPos = tpa;
- if (this._positionType == cc.PARTICLE_TYPE_FREE || this._positionType == cc.PARTICLE_TYPE_RELATIVE) {
-
- var diff = tpb;
- cc.pIn(diff, currentPosition);
- cc.pSubIn(diff, selParticle.startPos);
-
- cc.pIn(newPos, selParticle.pos);
- cc.pSubIn(newPos, diff);
-
- } else {
- cc.pIn(newPos, selParticle.pos);
- }
-
- // translate newPos to correct position, since matrix transform isn't performed in batchnode
- // don't update the particle with the new position information, it will interfere with the radius and tangential calculations
- if (this._batchNode) {
- newPos.x += this._position.x;
- newPos.y += this._position.y;
- }
-
- if (cc.renderContextType == cc.WEBGL) {
- // IMPORTANT: newPos may not be used as a reference here! (as it is just the temporary tpa point)
- // the implementation of updateQuadWithParticle must use
- // the x and y values directly
- this.updateQuadWithParticle(selParticle, newPos);
- } else {
- cc.pIn(selParticle.drawPos, newPos);
- }
- //updateParticleImp(self, updateParticleSel, p, newPos);
-
- // update particle counter
- ++this._particleIdx;
- } else {
- // life < 0
- var currentIndex = selParticle.atlasIndex;
- if(this._particleIdx !== this._particleCount -1){
- var deadParticle = locParticles[this._particleIdx];
- locParticles[this._particleIdx] = locParticles[this._particleCount -1];
- locParticles[this._particleCount -1] = deadParticle;
- }
- if (this._batchNode) {
- //disable the switched particle
- this._batchNode.disableParticle(this._atlasIndex + currentIndex);
-
- //switch indexes
- locParticles[this._particleCount - 1].atlasIndex = currentIndex;
- }
-
- --this._particleCount;
- if (this._particleCount == 0 && this._isAutoRemoveOnFinish) {
- this.unscheduleUpdate();
- this._parent.removeChild(this, true);
- return;
- }
- }
- }
- this._transformSystemDirty = false;
- }
-
- if (!this._batchNode)
- this.postStep();
- },
-
- updateWithNoTime:function () {
- this.update(0);
- },
-
- /**
- * return the string found by key in dict.
- * @param {string} key
- * @param {object} dict
- * @return {String} "" if not found; return the string if found.
- * @private
- */
- _valueForKey:function (key, dict) {
- if (dict) {
- var pString = dict[key];
- return pString != null ? pString : "";
- }
- return "";
- },
-
- _updateBlendFunc:function () {
- cc.Assert(!this._batchNode, "Can't change blending functions when the particle is being batched");
-
- var locTexture = this._texture;
- if (locTexture && locTexture instanceof cc.Texture2D) {
- this._opacityModifyRGB = false;
- var locBlendFunc = this._blendFunc;
- if (locBlendFunc.src == cc.BLEND_SRC && locBlendFunc.dst == cc.BLEND_DST) {
- if (locTexture.hasPremultipliedAlpha()) {
- this._opacityModifyRGB = true;
- } else {
- locBlendFunc.src = gl.SRC_ALPHA;
- locBlendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
- }
- }
- }
- },
-
- clone:function () {
- var retParticle = new cc.ParticleSystem();
-
- // self, not super
- if (retParticle.initWithTotalParticles(this._totalParticles)) {
- // angle
- retParticle._angle = this._angle;
- retParticle._angleVar = this._angleVar;
-
- // duration
- retParticle._duration = this._duration;
-
- // blend function
- retParticle._blendFunc.src = this._blendFunc.src;
- retParticle._blendFunc.dst = this._blendFunc.dst;
-
- // color
- var particleStartColor = retParticle._startColor, locStartColor = this._startColor;
- particleStartColor.r = locStartColor.r;
- particleStartColor.g = locStartColor.g;
- particleStartColor.b = locStartColor.b;
- particleStartColor.a = locStartColor.a;
-
- var particleStartColorVar = retParticle._startColorVar, locStartColorVar = this._startColorVar;
- particleStartColorVar.r = locStartColorVar.r;
- particleStartColorVar.g = locStartColorVar.g;
- particleStartColorVar.b = locStartColorVar.b;
- particleStartColorVar.a = locStartColorVar.a;
-
- var particleEndColor = retParticle._endColor, locEndColor = this._endColor;
- particleEndColor.r = locEndColor.r;
- particleEndColor.g = locEndColor.g;
- particleEndColor.b = locEndColor.b;
- particleEndColor.a = locEndColor.a;
-
- var particleEndColorVar = retParticle._endColorVar, locEndColorVar = this._endColorVar;
- particleEndColorVar.r = locEndColorVar.r;
- particleEndColorVar.g = locEndColorVar.g;
- particleEndColorVar.b = locEndColorVar.b;
- particleEndColorVar.a = locEndColorVar.a;
-
- // particle size
- retParticle._startSize = this._startSize;
- retParticle._startSizeVar = this._startSizeVar;
- retParticle._endSize = this._endSize;
- retParticle._endSizeVar = this._endSizeVar;
-
- // position
- retParticle.setPosition(new cc.Point(this._position.x, this._position.y));
- retParticle._posVar.x = this._posVar.x;
- retParticle._posVar.y = this._posVar.y;
-
- // Spinning
- retParticle._startSpin = this._startSpin;
- retParticle._startSpinVar = this._startSpinVar;
- retParticle._endSpin = this._endSpin;
- retParticle._endSpinVar = this._endSpinVar;
-
- retParticle._emitterMode = this._emitterMode;
-
- // Mode A: Gravity + tangential accel + radial accel
- if (this._emitterMode == cc.PARTICLE_MODE_GRAVITY) {
- var particleModeA = retParticle.modeA, locModeA = this.modeA;
- // gravity
- particleModeA.gravity.x = locModeA.gravity.x;
- particleModeA.gravity.y = locModeA.gravity.y;
-
- // speed
- particleModeA.speed = locModeA.speed;
- particleModeA.speedVar = locModeA.speedVar;
-
- // radial acceleration
- particleModeA.radialAccel = locModeA.radialAccel;
-
- particleModeA.radialAccelVar = locModeA.radialAccelVar;
-
- // tangential acceleration
- particleModeA.tangentialAccel = locModeA.tangentialAccel;
-
- particleModeA.tangentialAccelVar = locModeA.tangentialAccelVar;
- } else if (this._emitterMode == cc.PARTICLE_MODE_RADIUS) {
- var particleModeB = retParticle.modeB, locModeB = this.modeB;
- // or Mode B: radius movement
- particleModeB.startRadius = locModeB.startRadius;
- particleModeB.startRadiusVar = locModeB.startRadiusVar;
- particleModeB.endRadius = locModeB.endRadius;
- particleModeB.endRadiusVar = locModeB.endRadiusVar;
- particleModeB.rotatePerSecond = locModeB.rotatePerSecond;
- particleModeB.rotatePerSecondVar = locModeB.rotatePerSecondVar;
- }
-
- // life span
- retParticle._life = this._life;
- retParticle._lifeVar = this._lifeVar;
-
- // emission Rate
- retParticle._emissionRate = this._emissionRate;
-
- //don't get the internal texture if a batchNode is used
- if (!this._batchNode) {
- // Set a compatible default for the alpha transfer
- retParticle._opacityModifyRGB = this._opacityModifyRGB;
-
- // texture
- retParticle._texture = this._texture;
- }
- }
- return retParticle;
- },
-
- /**
- * Sets a new CCSpriteFrame as particle.
- * WARNING: this method is experimental. Use setTextureWithRect instead.
- *
- * @param {cc.SpriteFrame} spriteFrame
- */
- setDisplayFrame:function (spriteFrame) {
- cc.Assert(cc._rectEqualToZero(spriteFrame.getOffsetInPixels()), "QuadParticle only supports SpriteFrames with no offsets");
-
- // update texture before updating texture rect
- if (cc.renderContextType === cc.WEBGL)
- if (!this._texture || spriteFrame.getTexture()._webTextureObj != this._texture._webTextureObj)
- this.setTexture(spriteFrame.getTexture());
- },
-
- /**
- * Sets a new texture with a rect. The rect is in Points.
- * @param {cc.Texture2D} texture
- * @param {cc.Rect} rect
- */
- setTextureWithRect:function (texture, rect) {
- var locTexture = this._texture;
- if (cc.renderContextType === cc.WEBGL) {
- // Only update the texture if is different from the current one
- if ((!locTexture || texture._webTextureObj != locTexture._webTextureObj) && (locTexture != texture)) {
- this._texture = texture;
- this._updateBlendFunc();
- }
- } else {
- if ((!locTexture || texture != locTexture) && (locTexture != texture)) {
- this._texture = texture;
- this._updateBlendFunc();
- }
- }
-
- this._pointRect = rect;
- this.initTexCoordsWithRect(rect);
- },
-
- /**
- * draw particle
- * @param {CanvasRenderingContext2D} ctx CanvasContext
- * @override
- */
- draw:function (ctx) {
- cc.Assert(!this._batchNode, "draw should not be called when added to a particleBatchNode");
- if(!this._textureLoaded)
- return;
-
- if (cc.renderContextType === cc.CANVAS)
- this._drawForCanvas(ctx);
- else
- this._drawForWebGL(ctx);
-
- cc.g_NumberOfDraws++;
- },
-
- _drawForCanvas:function (ctx) {
- var context = ctx || cc.renderContext;
- context.save();
- if (this.isBlendAdditive())
- context.globalCompositeOperation = 'lighter';
- else
- context.globalCompositeOperation = 'source-over';
-
- for (var i = 0; i < this._particleCount; i++) {
- var particle = this._particles[i];
- var lpx = (0 | (particle.size * 0.5));
-
- if (this._drawMode == cc.PARTICLE_TEXTURE_MODE) {
-
- var element = this._texture.getHtmlElementObj();
-
- // Delay drawing until the texture is fully loaded by the browser
- if (!element.width || !element.height)
- continue;
-
- context.save();
- context.globalAlpha = particle.color.a;
- context.translate((0 | particle.drawPos.x), -(0 | particle.drawPos.y));
-
- var size = Math.floor(particle.size / 4) * 4;
- var w = this._pointRect.width;
- var h = this._pointRect.height;
-
- context.scale(
- Math.max((1 / w) * size, 0.000001),
- Math.max((1 / h) * size, 0.000001)
- );
-
-
- if (particle.rotation)
- context.rotate(cc.DEGREES_TO_RADIANS(particle.rotation));
-
- context.translate(-(0 | (w / 2)), -(0 | (h / 2)));
- if (particle.isChangeColor) {
-
- var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(element);
- if (cacheTextureForColor) {
- // Create another cache for the tinted version
- // This speeds up things by a fair bit
- if (!cacheTextureForColor.tintCache) {
- cacheTextureForColor.tintCache = document.createElement('canvas');
- cacheTextureForColor.tintCache.width = element.width;
- cacheTextureForColor.tintCache.height = element.height;
- }
- cc.generateTintImage(element, cacheTextureForColor, particle.color, this._pointRect, cacheTextureForColor.tintCache);
- element = cacheTextureForColor.tintCache;
- }
- }
-
- context.drawImage(element, 0, 0);
- context.restore();
-
- } else {
- context.save();
- context.globalAlpha = particle.color.a;
-
- context.translate(0 | particle.drawPos.x, -(0 | particle.drawPos.y));
-
- if (this._shapeType == cc.PARTICLE_STAR_SHAPE) {
- if (particle.rotation)
- context.rotate(cc.DEGREES_TO_RADIANS(particle.rotation));
- cc.drawingUtil.drawStar(context, lpx, particle.color);
- } else
- cc.drawingUtil.drawColorBall(context, lpx, particle.color);
- context.restore();
- }
- }
- context.restore();
- },
-
- _drawForWebGL:function (ctx) {
- if(!this._texture)
- return;
-
- var gl = ctx || cc.renderContext;
-
- this._shaderProgram.use();
- this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
-
- cc.glBindTexture2D(this._texture);
- cc.glBlendFuncForParticle(this._blendFunc.src, this._blendFunc.dst);
-
- //cc.Assert(this._particleIdx == this._particleCount, "Abnormal error in particle quad");
-
- //
- // Using VBO without VAO
- //
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX);
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); // vertices
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); // colors
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16); // tex coords
-
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
- gl.drawElements(gl.TRIANGLES, this._particleIdx * 6, gl.UNSIGNED_SHORT, 0);
- },
-
- /**
- * listen the event that coming to foreground on Android
- * @param {cc.Class} obj
- */
- listenBackToForeground:function (obj) {
- if (cc.TEXTURE_ATLAS_USE_VAO)
- this._setupVBOandVAO();
- else
- this._setupVBO();
- },
-
- _setupVBOandVAO:function () {
- //Not support on WebGL
- /*if (cc.renderContextType == cc.CANVAS) {
- return;
- }*/
-
- //NOT SUPPORTED
- /*glGenVertexArrays(1, this._VAOname);
- glBindVertexArray(this._VAOname);
-
- var kQuadSize = sizeof(m_pQuads[0].bl);
-
- glGenBuffers(2, this._buffersVBO[0]);
-
- glBindBuffer(GL_ARRAY_BUFFER, this._buffersVBO[0]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(this._quads[0]) * this._totalParticles, this._quads, GL_DYNAMIC_DRAW);
-
- // vertices
- glEnableVertexAttribArray(kCCVertexAttrib_Position);
- glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, vertices));
-
- // colors
- glEnableVertexAttribArray(kCCVertexAttrib_Color);
- glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, offsetof(ccV3F_C4B_T2F, colors));
-
- // tex coords
- glEnableVertexAttribArray(kCCVertexAttrib_TexCoords);
- glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, texCoords));
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_pIndices[0]) * m_uTotalParticles * 6, m_pIndices, GL_STATIC_DRAW);
-
- glBindVertexArray(0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- CHECK_GL_ERROR_DEBUG();*/
- },
-
- _setupVBO:function () {
- if (cc.renderContextType == cc.CANVAS)
- return;
-
- var gl = cc.renderContext;
-
- //gl.deleteBuffer(this._buffersVBO[0]);
- this._buffersVBO[0] = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]);
- gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW);
-
- this._buffersVBO[1] = gl.createBuffer();
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]);
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW);
-
- //cc.CHECK_GL_ERROR_DEBUG();
- },
-
- _allocMemory:function () {
- if (cc.renderContextType === cc.CANVAS)
- return true;
-
- //cc.Assert((!this._quads && !this._indices), "Memory already allocated");
- cc.Assert(!this._batchNode, "Memory should not be allocated when not using batchNode");
- var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT;
- var totalParticles = this._totalParticles;
- var locQuads = [];
- this._indices = new Uint16Array(totalParticles * 6);
- var locQuadsArrayBuffer = new ArrayBuffer(quadSize * totalParticles);
-
- for (var i = 0; i < totalParticles; i++)
- locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, i * quadSize);
- if (!locQuads || !this._indices) {
- cc.log("cocos2d: Particle system: not enough memory");
- return false;
- }
- this._quads = locQuads;
- this._quadsArrayBuffer = locQuadsArrayBuffer;
- return true;
- }
-});
-
-/**
- * return the string found by key in dict.
- * This plist files can be create manually or with Particle Designer:
- * http://particledesigner.71squared.com/
- *
- * @param {String} plistFile
- * @return {cc.ParticleSystem}
- */
-cc.ParticleSystem.create = function (plistFile) {
- var ret = new cc.ParticleSystem();
- if (!plistFile || typeof(plistFile) === "number") {
- var ton = plistFile || 100;
- ret.setDrawMode(cc.PARTICLE_TEXTURE_MODE);
- ret.initWithTotalParticles(ton);
- return ret;
- }
-
- if (ret && ret.initWithFile(plistFile))
- return ret;
- return null;
-};
-
-/**
- * create a system with a fixed number of particles
- * @param {Number} number_of_particles
- * @return {cc.ParticleSystem}
- */
-cc.ParticleSystem.createWithTotalParticles = function (number_of_particles) {
- //emitter.initWithTotalParticles(number_of_particles);
- var particle = new cc.ParticleSystem();
- if (particle && particle.initWithTotalParticles(number_of_particles))
- return particle;
- return null;
-};
-
-// Different modes
-/**
- * Mode A:Gravity + Tangential Accel + Radial Accel
- * @Class
- * @Construct
- * @param {cc.Point} [gravity=] Gravity value.
- * @param {Number} [speed=0] speed of each particle.
- * @param {Number} [speedVar=0] speed variance of each particle.
- * @param {Number} [tangentialAccel=0] tangential acceleration of each particle.
- * @param {Number} [tangentialAccelVar=0] tangential acceleration variance of each particle.
- * @param {Number} [radialAccel=0] radial acceleration of each particle.
- * @param {Number} [radialAccelVar=0] radial acceleration variance of each particle.
- * @param {boolean} [rotationIsDir=false]
- */
-cc.ParticleSystem.ModeA = function (gravity, speed, speedVar, tangentialAccel, tangentialAccelVar, radialAccel, radialAccelVar, rotationIsDir) {
- /** Gravity value. Only available in 'Gravity' mode. */
- this.gravity = gravity ? gravity : cc.PointZero();
- /** speed of each particle. Only available in 'Gravity' mode. */
- this.speed = speed || 0;
- /** speed variance of each particle. Only available in 'Gravity' mode. */
- this.speedVar = speedVar || 0;
- /** tangential acceleration of each particle. Only available in 'Gravity' mode. */
- this.tangentialAccel = tangentialAccel || 0;
- /** tangential acceleration variance of each particle. Only available in 'Gravity' mode. */
- this.tangentialAccelVar = tangentialAccelVar || 0;
- /** radial acceleration of each particle. Only available in 'Gravity' mode. */
- this.radialAccel = radialAccel || 0;
- /** radial acceleration variance of each particle. Only available in 'Gravity' mode. */
- this.radialAccelVar = radialAccelVar || 0;
- /** set the rotation of each particle to its direction Only available in 'Gravity' mode. */
- this.rotationIsDir = rotationIsDir || false;
-};
-
-/**
- * Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode)
- * @Class
- * @Construct
- * @param {Number} startRadius The starting radius of the particles.
- * @param {Number} startRadiusVar The starting radius variance of the particles.
- * @param {Number} endRadius The ending radius of the particles.
- * @param {Number} endRadiusVar The ending radius variance of the particles.
- * @param {Number} rotatePerSecond Number of degress to rotate a particle around the source pos per second.
- * @param {Number} rotatePerSecondVar Variance in degrees for rotatePerSecond.
- */
-cc.ParticleSystem.ModeB = function (startRadius, startRadiusVar, endRadius, endRadiusVar, rotatePerSecond, rotatePerSecondVar) {
- /** The starting radius of the particles. Only available in 'Radius' mode. */
- this.startRadius = startRadius || 0;
- /** The starting radius variance of the particles. Only available in 'Radius' mode. */
- this.startRadiusVar = startRadiusVar || 0;
- /** The ending radius of the particles. Only available in 'Radius' mode. */
- this.endRadius = endRadius || 0;
- /** The ending radius variance of the particles. Only available in 'Radius' mode. */
- this.endRadiusVar = endRadiusVar || 0;
- /** Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. */
- this.rotatePerSecond = rotatePerSecond || 0;
- /** Variance in degrees for rotatePerSecond. Only available in 'Radius' mode. */
- this.rotatePerSecondVar = rotatePerSecondVar || 0;
-};
diff --git a/cocos2d/physics_nodes/CCPhysicsDebugNode.js b/cocos2d/physics/CCPhysicsDebugNode.js
similarity index 66%
rename from cocos2d/physics_nodes/CCPhysicsDebugNode.js
rename to cocos2d/physics/CCPhysicsDebugNode.js
index d598ba7732..003bfe3f74 100644
--- a/cocos2d/physics_nodes/CCPhysicsDebugNode.js
+++ b/cocos2d/physics/CCPhysicsDebugNode.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2012 Scott Lembcke and Howling Moon Software
http://www.cocos2d-x.org
@@ -34,7 +34,12 @@
as the private API may change with little or no warning.
*/
-// Helper. Converts an array of numbers into an array of vectors(x,y)
+/**
+ * Converts an array of numbers into an array of vectors(x,y)
+ * @function
+ * @param {Array} verts
+ * @return {Array}
+ */
cc.__convertVerts = function (verts) {
var ret = [];
for (var i = 0; i < verts.length / 2; i++) {
@@ -43,16 +48,27 @@ cc.__convertVerts = function (verts) {
return ret;
};
+/**
+ * color for body
+ * @function
+ * @param {cp.Body} body
+ * @return {cc.color}
+ */
cc.ColorForBody = function (body) {
if (body.isRogue() || body.isSleeping()) {
- return cc.c4f(0.5, 0.5, 0.5, 0.5);
+ return cc.color(128, 128, 128, 128);
} else if (body.nodeIdleTime > body.space.sleepTimeThreshold) {
- return cc.c4f(0.33, 0.33, 0.33, 0.5);
+ return cc.color(84, 84, 84, 128);
} else {
- return cc.c4f(1, 0, 0, 0.5);
+ return cc.color(255, 0, 0, 128);
}
};
+/**
+ * draw shape
+ * @param {cp.Shape} shape
+ * @param renderer
+ */
cc.DrawShape = function (shape, renderer) {
var body = shape.body;
var color = cc.ColorForBody(body);
@@ -65,14 +81,20 @@ cc.DrawShape = function (shape, renderer) {
this.drawSegment(shape.ta, shape.tb, Math.max(shape.r, 2.0), color);
break;
case cp.PolyShape.prototype.collisionCode:
- var line = cc.c4f(color.r, color.g, color.b, cc.lerp(color.a, 1.0, 0.5));
+ var line = cc.color(color.r, color.g, color.b, cc.lerp(color.a, 255, 0.5));
this.drawPoly(cc.__convertVerts(shape.tVerts), color, 1.0, line);
break;
default:
- cc.Assert(false, "Bad assertion in DrawShape()");
+ cc.log("cc.DrawShape(): Bad assertion in DrawShape()");
+ break;
}
};
+/**
+ * draw constraint
+ * @param {cp.Constraint} constraint
+ * @param renderer
+ */
cc.DrawConstraint = function (constraint, renderer) {
var body_a = constraint.a;
var body_b = constraint.b;
@@ -110,57 +132,81 @@ cc.DrawConstraint = function (constraint, renderer) {
}
};
-cc.CONSTRAINT_COLOR = cc.c4f(0, 1, 0, 0.5);
+/**
+ * @constant
+ * @type {cc.color}
+ */
+cc.CONSTRAINT_COLOR = cc.color(0, 255, 0, 128);
+
/**
- A Node that draws the components of a physics engine.
- Supported physics engines:
- - Chipmunk
- - Objective-Chipmunk
+ * A Node that draws the components of a physics engine.
+ * Supported physics engines:
+ * - Chipmunk
+ * - Objective-Chipmunk
+ *
+ * @class
+ * @extends cc.DrawNode
+ *
+ * @property {cp.Space} space Physic world space
*/
cc.PhysicsDebugNode = cc.DrawNode.extend({
- _spaceObj:null,
- _spacePtr:null,
+ _space:null,
+ _className:"PhysicsDebugNode",
+
+ /**
+ * constructor of cc.PhysicsDebugNode
+ * @param {cp.Space} space
+ */
+ ctor: function (space) {
+ cc.DrawNode.prototype.ctor.call(this);
+ this._space = space;
+ },
+ /**
+ * get space
+ * @returns {cp.Space}
+ */
getSpace:function () {
- return this._spacePtr;
+ return this._space;
},
+ /**
+ * set space
+ * @param {cp.Space} space
+ */
setSpace:function (space) {
- this._spacePtr = space;
+ this._space = space;
},
+ /**
+ * draw
+ * @param {object} context
+ */
draw:function (context) {
- if (!this._spacePtr)
+ if (!this._space)
return;
- this._spacePtr.eachShape(cc.DrawShape.bind(this));
- this._spacePtr.eachConstraint(cc.DrawConstraint.bind(this));
+ this._space.eachShape(cc.DrawShape.bind(this));
+ this._space.eachConstraint(cc.DrawConstraint.bind(this));
cc.DrawNode.prototype.draw.call(this);
this.clear();
- }
-});
+ },
-/** Create a debug node for an Objective-Chipmunk space. */
-cc.PhysicsDebugNode.debugNodeForChipmunkSpace = function (space) {
- var node = new cc.PhysicsDebugNode();
- if (node.init()) {
- node._spaceObj = space;
- node._spacePtr = space.space;
- return node;
+ _createRenderCmd: function(){
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.PhysicsDebugNode.CanvasRenderCmd(this);
+ else
+ return new cc.PhysicsDebugNode.WebGLRenderCmd(this);
}
- return null;
-};
+});
-/** Create a debug node for a regular Chipmunk space. */
-cc.PhysicsDebugNode.debugNodeForCPSpace = function (space) {
- var node = new cc.PhysicsDebugNode();
- if (node.init()) {
- node._spacePtr = space;
- return node;
- }
- return null;
+/**
+ * Create a debug node for a regular Chipmunk space.
+ * @deprecated since v3.0, please use new cc.PhysicsDebugNode(space)
+ * @param {cp.Space} space
+ * @return {cc.PhysicsDebugNode}
+ */
+cc.PhysicsDebugNode.create = function (space) {
+ return new cc.PhysicsDebugNode(space);
};
-
-cc.PhysicsDebugNode.create = cc.PhysicsDebugNode.debugNodeForCPSpace;
-
diff --git a/cocos2d/physics/CCPhysicsDebugNodeCanvasRenderCmd.js b/cocos2d/physics/CCPhysicsDebugNodeCanvasRenderCmd.js
new file mode 100644
index 0000000000..1adf9a3f49
--- /dev/null
+++ b/cocos2d/physics/CCPhysicsDebugNodeCanvasRenderCmd.js
@@ -0,0 +1,52 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.PhysicsDebugNode's rendering objects of Canvas
+ */
+(function () {
+ cc.PhysicsDebugNode.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._buffer = renderableObject._buffer;
+ this._needDraw = true;
+ };
+
+ var proto = cc.PhysicsDebugNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.PhysicsDebugNode.CanvasRenderCmd;
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var node = this._node;
+ if (!node._space)
+ return;
+ node._space.eachShape(cc.DrawShape.bind(node));
+ node._space.eachConstraint(cc.DrawConstraint.bind(node));
+ cc.DrawNode.CanvasRenderCmd.prototype.rendering.call(this, ctx, scaleX, scaleY);
+ node.clear();
+ };
+
+ proto._drawDot = cc.DrawNode.CanvasRenderCmd.prototype._drawDot;
+ proto._drawSegment = cc.DrawNode.CanvasRenderCmd.prototype._drawSegment;
+ proto._drawPoly = cc.DrawNode.CanvasRenderCmd.prototype._drawPoly;
+
+})();
diff --git a/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js b/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js
new file mode 100644
index 0000000000..0b8a18504c
--- /dev/null
+++ b/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js
@@ -0,0 +1,62 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.PhysicsDebugNode's rendering objects of WebGL
+ */
+(function () {
+ cc.PhysicsDebugNode.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ };
+
+ cc.PhysicsDebugNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ cc.PhysicsDebugNode.WebGLRenderCmd.prototype.constructor = cc.PhysicsDebugNode.WebGLRenderCmd;
+
+ cc.PhysicsDebugNode.WebGLRenderCmd.prototype.rendering = function (ctx) {
+ var node = this._node;
+ if (!node._space)
+ return;
+
+ node._space.eachShape(cc.DrawShape.bind(node));
+ node._space.eachConstraint(cc.DrawConstraint.bind(node));
+
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ //cc.DrawNode.prototype.draw.call(node);
+ cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
+ this._glProgramState.apply(this._matrix);
+ node._render();
+
+ node.clear();
+ };
+})();
diff --git a/cocos2d/physics/CCPhysicsSprite.js b/cocos2d/physics/CCPhysicsSprite.js
new file mode 100644
index 0000000000..dde3546318
--- /dev/null
+++ b/cocos2d/physics/CCPhysicsSprite.js
@@ -0,0 +1,442 @@
+/**
+ * Copyright (c) 2012 Scott Lembcke and Howling Moon Software
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
+ *
+ * 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.
+ */
+
+/** A CCSprite subclass that is bound to a physics body.
+ It works with:
+ - Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined
+ - Objective-Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined
+ - Box2d: Preprocessor macro CC_ENABLE_BOX2D_INTEGRATION should be defined
+
+ Features and Limitations:
+ - Scale and Skew properties are ignored.
+ - Position and rotation are going to updated from the physics body
+ - If you update the rotation or position manually, the physics body will be updated
+ - You can't eble both Chipmunk support and Box2d support at the same time. Only one can be enabled at compile time
+ */
+(function () {
+ var box2dAPI = {
+ _ignoreBodyRotation: false,
+ _body: null,
+ _PTMRatio: 32,
+ _rotation: 1,
+ /**
+ * Create a PhysicsSprite with filename and rect
+ * Constructor of cc.PhysicsSprite for Box2d
+ * @param {String|cc.Texture2D|cc.SpriteFrame} fileName
+ * @param {cc.Rect} rect
+ * @example
+ *
+ * 1.Create a sprite with image path and rect
+ * var physicsSprite1 = new cc.PhysicsSprite("res/HelloHTML5World.png");
+ * var physicsSprite2 = new cc.PhysicsSprite("res/HelloHTML5World.png",cc.rect(0,0,480,320));
+ *
+ * 2.Create a sprite with a sprite frame name. Must add "#" before fame name.
+ * var physicsSprite = new cc.PhysicsSprite('#grossini_dance_01.png');
+ *
+ * 3.Create a sprite with a sprite frame
+ * var spriteFrame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png");
+ * var physicsSprite = new cc.PhysicsSprite(spriteFrame);
+ *
+ * 4.Creates a sprite with an existing texture contained in a CCTexture2D object
+ * After creation, the rect will be the size of the texture, and the offset will be (0,0).
+ * var texture = cc.textureCache.addImage("HelloHTML5World.png");
+ * var physicsSprite1 = new cc.PhysicsSprite(texture);
+ * var physicsSprite2 = new cc.PhysicsSprite(texture, cc.rect(0,0,480,320));
+ *
+ */
+ ctor: function (fileName, rect) {
+ cc.Sprite.prototype.ctor.call(this);
+
+ if (fileName === undefined) {
+ cc.PhysicsSprite.prototype.init.call(this);
+ } else if (cc.isString(fileName)) {
+ if (fileName[0] === "#") {
+ //init with a sprite frame name
+ var frameName = fileName.substr(1, fileName.length - 1);
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(frameName);
+ this.initWithSpriteFrame(spriteFrame);
+ } else {
+ //init with filename and rect
+ this.init(fileName, rect);
+ }
+ } else if (cc.isObject(fileName)) {
+ if (fileName instanceof cc.Texture2D) {
+ //init with texture and rect
+ this.initWithTexture(fileName, rect);
+ } else if (fileName instanceof cc.SpriteFrame) {
+ //init with a sprite frame
+ this.initWithSpriteFrame(fileName);
+ }
+ }
+ //this._transformCmd = new cc.PhysicsSpriteTransformCmdCanvas(this);
+ //cc.rendererCanvas.pushRenderCommand(this._transformCmd);
+ },
+
+ //visit: function(){
+ // cc.Sprite.prototype.visit.call(this);
+ // cc.rendererCanvas.pushRenderCommand(this._transformCmd);
+ //},
+
+ /**
+ * set body
+ * @param {Box2D.Dynamics.b2Body} body
+ */
+ setBody: function (body) {
+ this._body = body;
+ },
+
+ /**
+ * get body
+ * @return {Box2D.Dynamics.b2Body}
+ */
+ getBody: function () {
+ return this._body;
+ },
+
+ /**
+ * set PTM ratio
+ * @param {Number} r
+ */
+ setPTMRatio: function (r) {
+ this._PTMRatio = r;
+ },
+
+ /**
+ * get PTM ration
+ * @return {Number}
+ */
+ getPTMRatio: function () {
+ return this._PTMRatio;
+ },
+
+ /**
+ * get position
+ * @return {cc.Point}
+ */
+ getPosition: function () {
+ var pos = this._body.GetPosition();
+ var locPTMRatio = this._PTMRatio;
+ return cc.p(pos.x * locPTMRatio, pos.y * locPTMRatio);
+ },
+
+ /**
+ * set position
+ * @param {cc.Point} p
+ */
+ setPosition: function (p) {
+ var angle = this._body.GetAngle();
+ var locPTMRatio = this._PTMRatio;
+ this._body.setTransform(Box2D.b2Vec2(p.x / locPTMRatio, p.y / locPTMRatio), angle);
+ this.setNodeDirty();
+ },
+
+ /**
+ * get rotation
+ * @return {Number}
+ */
+ getRotation: function () {
+ return (this._ignoreBodyRotation ? cc.radiansToDegrees(this._rotationRadians) : cc.radiansToDegrees(this._body.GetAngle()));
+ },
+
+ /**
+ * set rotation
+ * @param {Number} r
+ */
+ setRotation: function (r) {
+ if (this._ignoreBodyRotation) {
+ this._rotation = r;
+ } else {
+ var locBody = this._body;
+ var p = locBody.GetPosition();
+ locBody.SetTransform(p, cc.degreesToRadians(r));
+ }
+ this.setNodeDirty();
+ },
+
+ _syncPosition: function () {
+ var locPosition = this._position,
+ pos = this._body.GetPosition(),
+ x = pos.x * this._PTMRatio,
+ y = pos.y * this._PTMRatio;
+ if (locPosition.x !== pos.x || locPosition.y !== pos.y) {
+ cc.Sprite.prototype.setPosition.call(this, x, y);
+ }
+ },
+ _syncRotation: function () {
+ this._rotationRadians = this._body.GetAngle();
+ var a = cc.radiansToDegrees(this._rotationRadians);
+ if (this._rotationX !== a) {
+ cc.Sprite.prototype.setRotation.call(this, a);
+ }
+ },
+
+ /**
+ * set whether to ingore body's rotation
+ * @param {Boolean} b
+ */
+ setIgnoreBodyRotation: function (b) {
+ this._ignoreBodyRotation = b;
+ }
+ };
+
+ var chipmunkAPI = {
+ _ignoreBodyRotation: false,
+ _body: null, //physics body
+ _rotation: 1,
+
+ /**
+ * Create a PhysicsSprite with filename and rect
+ * Constructor of cc.PhysicsSprite for chipmunk
+ * @param {String|cc.Texture2D|cc.SpriteFrame} fileName
+ * @param {cc.Rect} rect
+ * @example
+ *
+ * 1.Create a sprite with image path and rect
+ * var physicsSprite1 = new cc.PhysicsSprite("res/HelloHTML5World.png");
+ * var physicsSprite2 = new cc.PhysicsSprite("res/HelloHTML5World.png",cc.rect(0,0,480,320));
+ *
+ * 2.Create a sprite with a sprite frame name. Must add "#" before frame name.
+ * var physicsSprite = new cc.PhysicsSprite('#grossini_dance_01.png');
+ *
+ * 3.Create a sprite with a sprite frame
+ * var spriteFrame = cc.spriteFrameCache.getSpriteFrame("grossini_dance_01.png");
+ * var physicsSprite = new cc.PhysicsSprite(spriteFrame);
+ *
+ * 4.Creates a sprite with an exsiting texture contained in a CCTexture2D object
+ * After creation, the rect will be the size of the texture, and the offset will be (0,0).
+ * var texture = cc.textureCache.addImage("HelloHTML5World.png");
+ * var physicsSprite1 = new cc.PhysicsSprite(texture);
+ * var physicsSprite2 = new cc.PhysicsSprite(texture, cc.rect(0,0,480,320));
+ *
+ */
+ ctor: function (fileName, rect) {
+ cc.Sprite.prototype.ctor.call(this);
+
+ if (fileName === undefined) {
+ cc.PhysicsSprite.prototype.init.call(this);
+ } else if (cc.isString(fileName)) {
+ if (fileName[0] === "#") {
+ //init with a sprite frame name
+ var frameName = fileName.substr(1, fileName.length - 1);
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(frameName);
+ this.initWithSpriteFrame(spriteFrame);
+ } else {
+ //init with filename and rect
+ this.init(fileName, rect);
+ }
+ } else if (cc.isObject(fileName)) {
+ if (fileName instanceof cc.Texture2D) {
+ //init with texture and rect
+ this.initWithTexture(fileName, rect);
+ } else if (fileName instanceof cc.SpriteFrame) {
+ //init with a sprite frame
+ this.initWithSpriteFrame(fileName);
+ }
+ }
+
+ cc.renderer.pushRenderCommand(this._renderCmd);
+ },
+
+ visit: function () {
+ cc.renderer.pushRenderCommand(this._renderCmd);
+ cc.Sprite.prototype.visit.call(this);
+ },
+
+ /**
+ * set body
+ * @param {cp.Body} body
+ */
+ setBody: function (body) {
+ this._body = body;
+ },
+
+ /**
+ * get body
+ * @returns {cp.Body}
+ */
+ getBody: function () {
+ return this._body;
+ },
+
+ /**
+ * get position
+ * @return {cc.Point}
+ */
+ getPosition: function () {
+ var locBody = this._body;
+ return {x: locBody.p.x, y: locBody.p.y};
+ },
+
+ /**
+ * get position x
+ * @return {Number}
+ */
+ getPositionX: function () {
+ return this._body.p.x;
+ },
+
+ /**
+ * get position y
+ * @return {Number}
+ */
+ getPositionY: function () {
+ return this._body.p.y;
+ },
+
+ /**
+ * set position
+ * @param {cc.Point|Number}newPosOrxValue
+ * @param {Number}yValue
+ */
+ setPosition: function (newPosOrxValue, yValue) {
+ if (yValue === undefined) {
+ this._body.p.x = newPosOrxValue.x;
+ this._body.p.y = newPosOrxValue.y;
+ } else {
+ this._body.p.x = newPosOrxValue;
+ this._body.p.y = yValue;
+ }
+ },
+
+ /**
+ * set position x
+ * @param {Number} xValue
+ */
+ setPositionX: function (xValue) {
+ this._body.p.x = xValue;
+ },
+
+ /**
+ * set position y
+ * @param {Number} yValue
+ */
+ setPositionY: function (yValue) {
+ this._body.p.y = yValue;
+ },
+
+ _syncPosition: function () {
+ var locPosition = this._position, locBody = this._body;
+ if (locPosition.x !== locBody.p.x || locPosition.y !== locBody.p.y) {
+ cc.Sprite.prototype.setPosition.call(this, locBody.p.x, locBody.p.y);
+ }
+ },
+
+ /**
+ * get rotation
+ * @return {Number}
+ */
+ getRotation: function () {
+ return this._ignoreBodyRotation ? this._rotationX : -cc.radiansToDegrees(this._body.a);
+ },
+
+ /**
+ * set rotation
+ * @param {Number} r
+ */
+ setRotation: function (r) {
+ if (this._ignoreBodyRotation) {
+ cc.Sprite.prototype.setRotation.call(this, r);
+ } else {
+ this._body.a = -cc.degreesToRadians(r);
+ }
+ },
+ _syncRotation: function () {
+ var a = -cc.radiansToDegrees(this._body.a);
+ if (this._rotationX !== a) {
+ cc.Sprite.prototype.setRotation.call(this, a);
+ }
+ },
+
+ /**
+ * get the affine transform matrix of node to parent coordinate frame
+ * @return {cc.AffineTransform}
+ */
+ getNodeToParentTransform: function () {
+ return this._renderCmd.getNodeToParentTransform();
+ },
+
+ /**
+ * whether dirty
+ * @return {Boolean}
+ */
+ isDirty: function () {
+ return !this._body.isSleeping();
+ },
+ setDirty: function () {
+ },
+
+ /**
+ * set whether to ignore rotation of body
+ * @param {Boolean} b
+ */
+ setIgnoreBodyRotation: function (b) {
+ this._ignoreBodyRotation = b;
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.PhysicsSprite.CanvasRenderCmd(this);
+ else
+ return new cc.PhysicsSprite.WebGLRenderCmd(this);
+ }
+ };
+ /**
+ * @class
+ */
+ cc.PhysicsSprite = cc.Sprite.extend(chipmunkAPI);
+ cc.PhysicsSprite._className = "PhysicsSprite";
+ var _p = cc.PhysicsSprite.prototype;
+ // Extended properties
+ /** @expose */
+ _p.body;
+ cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody);
+ /** @expose */
+ _p.dirty;
+ cc.defineGetterSetter(_p, "dirty", _p.isDirty, _p.setDirty);
+
+
+ /**
+ * Create a PhysicsSprite with filename and rect
+ * @deprecated since v3.0, please use new cc.PhysicsSprite(fileName, rect) instead
+ * @param {String|cc.Texture2D|cc.SpriteFrame} fileName
+ * @param {cc.Rect} rect
+ * @return {cc.PhysicsSprite}
+ */
+ cc.PhysicsSprite.create = function (fileName, rect) {
+ return new cc.PhysicsSprite(fileName, rect);
+ };
+
+ /**
+ * @deprecated since v3.0, please use new cc.PhysicsSprite(spriteFrameName) instead
+ * @type {Function}
+ */
+ cc.PhysicsSprite.createWithSpriteFrameName = cc.PhysicsSprite.create;
+
+ /**
+ * @deprecated since v3.0, please use new cc.PhysicsSprite(spriteFrame) instead
+ * @type {Function}
+ */
+ cc.PhysicsSprite.createWithSpriteFrame = cc.PhysicsSprite.create;
+})();
diff --git a/cocos2d/physics/CCPhysicsSpriteCanvasRenderCmd.js b/cocos2d/physics/CCPhysicsSpriteCanvasRenderCmd.js
new file mode 100644
index 0000000000..09279e65ea
--- /dev/null
+++ b/cocos2d/physics/CCPhysicsSpriteCanvasRenderCmd.js
@@ -0,0 +1,50 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.PhysicsSprite's rendering objects of Canvas
+ */
+(function () {
+ cc.PhysicsSprite.CanvasRenderCmd = function (renderableObject) {
+ this._spriteCmdCtor(renderableObject);
+ this._needDraw = true;
+ };
+
+ var proto = cc.PhysicsSprite.CanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
+ proto.constructor = cc.PhysicsSprite.CanvasRenderCmd;
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ // This is a special class
+ // Sprite can not obtain sign
+ // So here must to calculate of each frame
+ var node = this._node;
+ node._syncPosition();
+ if (!node._ignoreBodyRotation)
+ node._syncRotation();
+ this.transform(this.getParentRenderCmd());
+
+ cc.Sprite.CanvasRenderCmd.prototype.rendering.call(this, ctx, scaleX, scaleY);
+ };
+
+})();
diff --git a/cocos2d/physics/CCPhysicsSpriteWebGLRenderCmd.js b/cocos2d/physics/CCPhysicsSpriteWebGLRenderCmd.js
new file mode 100644
index 0000000000..25fc120601
--- /dev/null
+++ b/cocos2d/physics/CCPhysicsSpriteWebGLRenderCmd.js
@@ -0,0 +1,51 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.PhysicsSprite's rendering objects of WebGL
+ */
+(function () {
+ cc.PhysicsSprite.WebGLRenderCmd = function (renderableObject) {
+ this._spriteCmdCtor(renderableObject);
+ this._needDraw = true;
+ };
+
+ var proto = cc.PhysicsSprite.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
+ proto.constructor = cc.PhysicsSprite.WebGLRenderCmd;
+
+ proto.spUploadData = cc.Sprite.WebGLRenderCmd.prototype.uploadData;
+
+ proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
+ // This is a special class
+ // Sprite can not obtain sign
+ // So here must to calculate of each frame
+ var node = this._node;
+ node._syncPosition();
+ if (!node._ignoreBodyRotation)
+ node._syncRotation();
+ this.transform(this.getParentRenderCmd(), true);
+
+ return this.spUploadData(f32buffer, ui32buffer, vertexDataOffset);
+ };
+})();
diff --git a/cocos2d/physics_nodes/CCPhysicsSprite.js b/cocos2d/physics_nodes/CCPhysicsSprite.js
deleted file mode 100644
index 1660fe2564..0000000000
--- a/cocos2d/physics_nodes/CCPhysicsSprite.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/** Copyright (c) 2012 Scott Lembcke and Howling Moon Software
- *
- * 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.
- */
-
-/** A CCSprite subclass that is bound to a physics body.
- It works with:
- - Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined
- - Objective-Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined
- - Box2d: Preprocessor macro CC_ENABLE_BOX2D_INTEGRATION should be defined
-
- Features and Limitations:
- - Scale and Skew properties are ignored.
- - Position and rotation are going to updated from the physics body
- - If you update the rotation or position manually, the physics body will be updated
- - You can't eble both Chipmunk support and Box2d support at the same time. Only one can be enabled at compile time
- */
-(function () {
- var box2dAPI = {
- _ignoreBodyRotation:false,
- _body:null,
- _PTMRatio:32,
- _rotation:1,
- setBody:function (body) {
- this._body = body;
- },
- getBody:function () {
- return this._body;
- },
- setPTMRatio:function (r) {
- this._PTMRatio = r;
- },
- getPTMRatio:function () {
- return this._PTMRatio;
- },
- getPosition:function () {
- var pos = this._body.GetPosition();
- var locPTMRatio =this._PTMRatio;
- return cc.p(pos.x * locPTMRatio, pos.y * locPTMRatio);
- },
- setPosition:function (p) {
- var angle = this._body.GetAngle();
- var locPTMRatio =this._PTMRatio;
- this._body.setTransform(Box2D.b2Vec2(p.x / locPTMRatio, p.y / locPTMRatio), angle);
- this.setNodeDirty();
- },
- getRotation:function () {
- return (this._ignoreBodyRotation ? cc.RADIANS_TO_DEGREES(this._rotationRadians) : cc.RADIANS_TO_DEGREES(this._body.GetAngle()));
- },
- setRotation:function (r) {
- if (this._ignoreBodyRotation) {
- this._rotation = r;
- } else {
- var locBody = this._body;
- var p = locBody.GetPosition();
- locBody.SetTransform(p, cc.DEGREES_TO_RADIANS(r));
- }
- this.setNodeDirty();
- },
- _syncPosition:function () {
- var pos = this._body.GetPosition();
- this._position = cc.p(pos.x * this._PTMRatio, pos.y * this._PTMRatio);
- this._rotationRadians = this._rotation * (Math.PI / 180);
- },
- _syncRotation:function () {
- this._rotationRadians = this._body.GetAngle();
- },
- visit:function () {
- if (this._body && this._PTMRatio) {
- this._syncPosition();
- if (!this._ignoreBodyRotation)
- this._syncRotation();
- }
- else {
- cc.log("PhysicsSprite body or PTIMRatio was not set");
- }
- this._super();
- }
- };
- var chipmunkAPI = {
- _ignoreBodyRotation:false,
- _body:null, //physics body
- _rotation:1,
- setBody:function (body) {
- this._body = body;
- },
- getBody:function () {
- return this._body;
- },
- getPosition:function () {
- var locBody = this._body;
- return {x:locBody.p.x, y:locBody.p.y};
- },
-
- getPositionX:function () {
- return this._body.p.x;
- },
-
- getPositionY:function () {
- return this._body.p.y;
- },
-
- setPosition:function (newPosOrxValue, yValue) {
- if(arguments.length==2){
- this._body.p.x = newPosOrxValue;
- this._body.p.y = yValue;
- }else{
- this._body.p.x = newPosOrxValue.x;
- this._body.p.y = newPosOrxValue.y;
- }
- //this._syncPosition();
- },
- _syncPosition:function () {
- var locPosition = this._position, locBody = this._body;
- if (locPosition.x != locBody.p.x || locPosition.y != locBody.p.y) {
- cc.Sprite.prototype.setPosition.call(this, locBody.p.x, locBody.p.y);
- }
- },
- getRotation:function () {
- return this._ignoreBodyRotation ? cc.RADIANS_TO_DEGREES(this._rotationRadiansX) : -cc.RADIANS_TO_DEGREES(this._body.a)
- },
- setRotation:function (r) {
- if (this._ignoreBodyRotation) {
- cc.Sprite.prototype.setRotation.call(this, r);
- } else {
- this._body.a = -cc.DEGREES_TO_RADIANS(r);
- //this._syncRotation();
- }
- },
- _syncRotation:function () {
- if (this._rotationRadiansX != -this._body.a) {
- cc.Sprite.prototype.setRotation.call(this, -cc.RADIANS_TO_DEGREES(this._body.a));
- }
- },
- nodeToParentTransform:function () {
- if(cc.renderContextType === cc.CANVAS)
- return this._nodeToParentTransformForCanvas();
-
- var locBody = this._body, locAnchorPIP = this._anchorPointInPoints, locScaleX = this._scaleX, locScaleY = this._scaleY;
- var x = locBody.p.x;
- var y = locBody.p.y;
-
- if (this._ignoreAnchorPointForPosition) {
- x += locAnchorPIP.x;
- y += locAnchorPIP.y;
- }
-
- // Make matrix
- var radians = locBody.a;
- var c = Math.cos(radians);
- var s = Math.sin(radians);
-
- // Although scale is not used by physics engines, it is calculated just in case
- // the sprite is animated (scaled up/down) using actions.
- // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990
- if (!cc._rectEqualToZero(locAnchorPIP)) {
- x += c * -locAnchorPIP.x * locScaleX + -s * -locAnchorPIP.y * locScaleY;
- y += s * -locAnchorPIP.x * locScaleX + c * -locAnchorPIP.y * locScaleY;
- }
-
- // Rot, Translate Matrix
- this._transform = cc.AffineTransformMake(c * locScaleX, s * locScaleX,
- -s * locScaleY, c * locScaleY,
- x, y);
-
- return this._transform;
- },
-
- _nodeToParentTransformForCanvas: function () {
- if (this.isDirty()) {
- var t = this._transform;// quick reference
- // base position
- var locBody = this._body, locScaleX = this._scaleX, locScaleY = this._scaleY, locAnchorPIP = this._anchorPointInPoints;
- t.tx = locBody.p.x;
- t.ty = locBody.p.y;
-
- // rotation Cos and Sin
- var radians = -locBody.a;
- var Cos = 1, Sin = 0;
- if (radians) {
- Cos = Math.cos(radians);
- Sin = Math.sin(radians);
- }
-
- // base abcd
- t.a = t.d = Cos;
- t.b = -Sin;
- t.c = Sin;
-
- // scale
- if (locScaleX !== 1 || locScaleY !== 1) {
- t.a *= locScaleX;
- t.c *= locScaleX;
- t.b *= locScaleY;
- t.d *= locScaleY;
- }
-
- // adjust anchorPoint
- t.tx += Cos * -locAnchorPIP.x * locScaleX + -Sin * locAnchorPIP.y * locScaleY;
- t.ty -= Sin * -locAnchorPIP.x * locScaleX + Cos * locAnchorPIP.y * locScaleY;
-
- // if ignore anchorPoint
- if (this._ignoreAnchorPointForPosition) {
- t.tx += locAnchorPIP.x;
- t.ty += locAnchorPIP.y;
- }
- this._transformDirty = false;
- }
- return this._transform;
- },
-
- isDirty:function(){
- return !this._body.isSleeping();
- }
- };
- cc.PhysicsSprite = cc.Sprite.extend(chipmunkAPI);
-
- /**
- * Create a PhysicsSprite with filename and rect
- * @constructs
- * @param {String} fileName
- * @param {cc.Rect} rect
- * @return {cc.Sprite}
- * @example
- * //create a sprite with filename
- * var sprite1 = cc.Sprite.create("HelloHTML5World.png");
- *
- * //create a sprite with filename and rect
- * var sprite2 = cc.PhysicsSprite.create("HelloHTML5World.png",cc.rect(0,0,480,320));
- */
- cc.PhysicsSprite.create = function (fileName, rect) {
- var argnum = arguments.length;
- var sprite = new cc.PhysicsSprite();
- if (argnum === 0) {
- if (sprite.init())
- return sprite;
- return null;
- } else if (argnum < 2) {
- /** Creates an sprite with an image filename.
- The rect used will be the size of the image.
- The offset will be (0,0).
- */
- if (sprite && sprite.initWithFile(fileName)) {
- return sprite;
- }
- return null;
- } else {
- /** Creates an sprite with an CCBatchNode and a rect
- */
- if (sprite && sprite.initWithFile(fileName, rect)) {
- return sprite;
- }
- return null;
- }
- };
-
- /**
- * Creates a PhysicsSprite with a sprite frame name
- * @param {String} spriteFrameName
- * @return {cc.Sprite}
- * @example
- *
- * //create a PhysicsSprite with a sprite frame
- * var sprite = cc.PhysicsSprite.createWithSpriteFrameName('grossini_dance_01.png');
- */
- cc.PhysicsSprite.createWithSpriteFrameName = function (spriteFrameName) {
- var spriteFrame = null;
- if (typeof(spriteFrameName) == 'string') {
- spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName);
- if (!spriteFrame) {
- cc.log("Invalid spriteFrameName: " + spriteFrameName);
- return null;
- }
- } else {
- cc.log("Invalid argument. Expecting string.");
- return null;
- }
- var sprite = new cc.PhysicsSprite();
- if (sprite && sprite.initWithSpriteFrame(spriteFrame)) {
- return sprite;
- }
- return null;
- };
-
- /**
- * Creates a sprite with a sprite frame.
- * @param {cc.SpriteFrame} spriteFrame
- * @return {cc.Sprite}
- * @example
- * //get a sprite frame
- * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png");
- *
- * //create a sprite with a sprite frame
- * var sprite = cc.Sprite.createWithSpriteFrameName(spriteFrame);
- */
- cc.PhysicsSprite.createWithSpriteFrame = function (spriteFrame) {
- var sprite = new cc.PhysicsSprite();
- if (sprite && sprite.initWithSpriteFrame(spriteFrame)) {
- return sprite;
- }
- return null;
- };
-})();
diff --git a/cocos2d/platform/AppControl.js b/cocos2d/platform/AppControl.js
deleted file mode 100644
index 09340a351d..0000000000
--- a/cocos2d/platform/AppControl.js
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Controller of Game Application
- * @class
- * @extends cc.Class
- */
-cc.AppController = cc.Class.extend(/** @lends cc.AppController# */{
- /**
- * did something when Finish Launching
- * @return {Boolean}
- */
- didFinishLaunchingWithOptions:function () {
- // Override point for customization after application launch.
- //var app = new cc.AppDelegate();
- cc.Application.getInstance().run();
-
- return true;
- },
-
- /**
- *
- * Sent when the application is about to move from active to inactive state.
- * This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message)
- * or when the user quits the application and it begins the transition to the background state.
- * Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates.
- * Games should use this method to pause the game.
- *
- */
- applicationWillResignActive:function () {
- cc.Director.getInstance().pause();
- },
-
- /**
- *
- * Restart any tasks that were paused (or not yet started) while the application was inactive.
- * If the application was previously in the background, optionally refresh the user interface.
- *
- */
- applicationDidBecomeActive:function () {
- cc.Director.getInstance().resume();
- },
-
- /**
- *
- * Use this method to release shared resources, save user data, invalidate timers, and store enough application state information
- * to restore your application to its current state in case it is terminated later.
- * If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
- *
- */
- applicationDidEnterBackground:function () {
- cc.Application.getInstance().applicationDidEnterBackground();
- },
-
- /**
- *
- * Called as part of transition from the background to the inactive state:
- * here you can undo many of the changes made on entering the background.
- *
- */
- applicationWillEnterForeground:function () {
- cc.Application.getInstance().applicationWillEnterForeground();
- },
-
- /**
- * Called when the application is about to terminate. See also applicationDidEnterBackground.
- */
- applicationWillTerminate:function () {
- }
-});
-
-/**
- * Return Controller of Game Application
- * @return {cc.AppController}
- */
-cc.AppController.shareAppController = function () {
- if (cc.sharedAppController == null) {
- cc.sharedAppController = new cc.AppController();
- }
- cc.Assert(cc.sharedAppController, "shareAppController");
- return cc.sharedAppController;
-};
-
-/**
- * cocos2d application instance
- * @type cc.AppController
- */
-cc.sharedAppController = null;
diff --git a/cocos2d/platform/CCAccelerometer.js b/cocos2d/platform/CCAccelerometer.js
deleted file mode 100644
index 322a97cf29..0000000000
--- a/cocos2d/platform/CCAccelerometer.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.UIInterfaceOrientationLandscapeLeft = -90;
-
-cc.UIInterfaceOrientationLandscapeRight = 90;
-
-cc.UIInterfaceOrientationPortraitUpsideDown = 180;
-
-cc.UIInterfaceOrientationPortrait = 0;
-
-/**
- * he device accelerometer reports values for each axis in units of g-force
- */
-cc.Acceleration = function (x, y, z, timestamp) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- this.timestamp = timestamp || 0;
-};
-
-/**
- * @class
- * @extends cc.Class
- */
-cc.Accelerometer = cc.Class.extend(/** @lends cc.Accelerometer# */{
- setDelegate: function (delegate) {
- cc.AccelerometerDispatcher.getInstance().addDelegate(delegate);
- },
- setAccelerometerInterval: function (interval) {
- cc.AccelerometerDispatcher.getInstance().setAccelerometerInterval(interval);
- }
-});
-
-/**
- *
- * The cc.AccelerometerDelegate defines a single method for
- * receiving acceleration-related data from the system.
- * @class
- * @extends cc.Class
- */
-cc.AccelerometerDispatcher = cc.Class.extend(/** @lends cc.AccelerometerDispatcher# */{
- _delegate: null,
- _acceleration: null,
- _deviceEvent: null,
- _interval: 0,
- _minus: 1,
- init: function () {
- this._acceleration = new cc.Acceleration();
- this._deviceEvent = window.DeviceMotionEvent || window.DeviceOrientationEvent;
- var ua = navigator.userAgent;
- if (/Android/.test(ua) || (/Adr/.test(ua) && cc.Browser.type == "ucbrowser")) {
- this._minus = -1;
- }
-
- //TODO fix DeviceMotionEvent bug on QQ Browser version 4.1 and below.
- if (cc.Browser.type == "mqqbrowser") {
- this._deviceEvent = window.DeviceOrientationEvent;
- }
- return true;
- },
-
- getDelegate: function () {
- return this._delegate;
- },
-
- addDelegate: function (delegate) {
- this._delegate = delegate;
- var acc = this.didAccelerate.bind(this);
-
- if (this._delegate) {
- if (this._deviceEvent == window.DeviceMotionEvent) {
- window.addEventListener('devicemotion', acc, false);
- }
- else {
- window.addEventListener('deviceorientation', acc, false);
- }
- }
- else {
- if (this._deviceEvent == window.DeviceMotionEvent) {
- window.removeEventListener('devicemotion', acc);
- }
- else {
- window.removeEventListener('deviceorientation', acc);
- }
- }
- },
-
- setAccelerometerInterval: function (interval) {
- if (this._interval !== interval) {
- this._interval = interval;
- }
- },
-
- didAccelerate: function (eventData) {
- if (!this._delegate) {
- return;
- }
-
- var now = Date.now();
- if ((now - this._acceleration.timestamp) / 1000 < this._interval) return;
-
- if (this._deviceEvent == window.DeviceMotionEvent) {
- var acceleration = eventData.accelerationIncludingGravity;
- this._acceleration.x = this._minus * acceleration.x * 0.1;
- this._acceleration.y = this._minus * acceleration.y * 0.1;
- this._acceleration.z = acceleration.z * 0.1;
- }
- else {
- this._acceleration.x = (eventData.gamma / 90) * 0.981;
- this._acceleration.y = -(eventData.beta / 90) * 0.981;
- this._acceleration.z = (eventData.alpha / 90) * 0.981;
- }
- this._acceleration.timestamp = Date.now();
-
- var tmp = this._acceleration.x;
- switch (window.orientation) {
- case cc.UIInterfaceOrientationLandscapeRight://-90
- this._acceleration.x = -this._acceleration.y;
- this._acceleration.y = tmp;
- break;
-
- case cc.UIInterfaceOrientationLandscapeLeft://90
- this._acceleration.x = this._acceleration.y;
- this._acceleration.y = -tmp;
- break;
-
- case cc.UIInterfaceOrientationPortraitUpsideDown://180
- this._acceleration.x = -this._acceleration.x
- this._acceleration.y = -this._acceleration.y;
- break;
-
- case cc.UIInterfaceOrientationPortrait://0
- break;
- }
-
- this._delegate.onAccelerometer(this._acceleration);
- }
-});
-
-
-cc.AccelerometerDispatcher.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.AccelerometerDispatcher();
- this._instance.init();
- }
-
- return this._instance;
-};
\ No newline at end of file
diff --git a/cocos2d/platform/CCApplication.js b/cocos2d/platform/CCApplication.js
deleted file mode 100644
index 30339aa89d..0000000000
--- a/cocos2d/platform/CCApplication.js
+++ /dev/null
@@ -1,434 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Device type
- * @constant
- * @type {Object}
- */
-cc.TARGET_PLATFORM = {
- WINDOWS:0,
- LINUX:1,
- MACOS:2,
- ANDROID:3,
- IPHONE:4,
- IPAD:5,
- BLACKBERRY:6,
- NACL:7,
- EMSCRIPTEN:8,
- MOBILE_BROWSER:100,
- PC_BROWSER:101
-};
-
-/**
- * Device oriented vertically, home button on the bottom
- * @constant
- * @type Number
- */
-cc.ORIENTATION_PORTRAIT = 0;
-
-/**
- * Device oriented vertically, home button on the top
- * @constant
- * @type Number
- */
-cc.ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1;
-
-/**
- * Device oriented horizontally, home button on the right
- * @constant
- * @type Number
- */
-cc.ORIENTATION_LANDSCAPE_LEFT = 2;
-
-/**
- * Device oriented horizontally, home button on the left
- * @constant
- * @type Number
- */
-cc.ORIENTATION_LANDSCAPE_RIGHT = 3;
-
-//engine render type
-
-/**
- * Canvas of render type
- * @constant
- * @type Number
- */
-cc.CANVAS = 0;
-
-/**
- * WebGL of render type
- * @constant
- * @type Number
- */
-cc.WEBGL = 1;
-
-/**
- * drawing primitive of game engine
- * @type cc.DrawingPrimitive
- */
-cc.drawingUtil = null;
-
-/**
- * main Canvas 2D/3D Context of game engine
- * @type CanvasRenderingContext2D|WebGLRenderingContext
- */
-cc.renderContext = null;
-
-/**
- * main Canvas of game engine
- * @type HTMLCanvasElement
- */
-cc.canvas = null;
-
-/**
- * This Div element contain all game canvas
- * @type HTMLDivElement
- */
-cc.gameDiv = null;
-
-/**
- * current render type of game engine
- * @type Number
- */
-cc.renderContextType = cc.CANVAS;
-
-/**
- * save original size of canvas, use for resize canvas
- * @type cc.Size
- */
-cc.originalCanvasSize = cc.size(0, 0);
-
-window.requestAnimFrame = (function () {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame
-})();
-
-
-if (!window.console) {
- window.console = {};
- window.console.log = function () {
- };
- window.console.assert = function () {
- };
-}
-
-cc.isAddedHiddenEvent = false;
-
-/**
- *
- * setup game main canvas,renderContext,gameDiv and drawingUtil with argument
- *
- * can receive follow type of arguemnt:
- * - empty: create a canvas append to document's body, and setup other option
- * - string: search the element by document.getElementById(),
- * if this element is HTMLCanvasElement, set this element as main canvas of engine, and set it's ParentNode as cc.gameDiv.
- * if this element is HTMLDivElement, set it's ParentNode to cc.gameDiv, and create a canvas as main canvas of engine.
- *
- * @function
- * @example
- * //setup with null
- * cc.setup();
- *
- * // setup with HTMLCanvasElement, gameCanvas is Canvas element
- * // declare like this:
- * cc.setup("gameCanvas");
- *
- * //setup with HTMLDivElement, gameDiv is Div element
- * // declare like this:
- * cc.setup("Cocos2dGameContainer");
- */
-cc.setup = function (el, width, height) {
- var element = cc.$(el) || cc.$('#' + el);
- if (element.tagName == "CANVAS") {
- width = width || element.width;
- height = height || element.height;
-
- //it is already a canvas, we wrap it around with a div
- cc.container = cc.$new("DIV");
- cc.canvas = element;
- cc.canvas.parentNode.insertBefore(cc.container, cc.canvas);
- cc.canvas.appendTo(cc.container);
- cc.container.style.width = (width || 480) + "px";
- cc.container.style.height = (height || 320) + "px";
- cc.container.setAttribute('id', 'Cocos2dGameContainer');
- cc.container.style.margin = "0 auto";
- cc.canvas.setAttribute("width", width || 480);
- cc.canvas.setAttribute("height", height || 320);
- } else {//we must make a new canvas and place into this element
- if (element.tagName != "DIV") {
- cc.log("Warning: target element is not a DIV or CANVAS");
- }
- width = width || element.clientWidth;
- height = height || element.clientHeight;
-
- cc.canvas = cc.$new("CANVAS");
- cc.canvas.addClass("gameCanvas");
- cc.canvas.setAttribute("width", width || 480);
- cc.canvas.setAttribute("height", height || 320);
- cc.container = element;
- element.appendChild(cc.canvas);
- cc.container.style.width = (width || 480) + "px";
- cc.container.style.height = (height || 320) + "px";
- }
- cc.container.style.position = 'relative';
- cc.container.style.overflow = 'hidden';
- cc.container.top = '100%';
-
- if(cc.__renderDoesnotSupport)
- return;
-
- if (cc.Browser.supportWebGL)
- cc.renderContext = cc.webglContext = cc.create3DContext(cc.canvas,{'stencil': true, 'preserveDrawingBuffer': true, 'alpha': false });
- if(cc.renderContext){
- cc.renderContextType = cc.WEBGL;
- window.gl = cc.renderContext; // global variable declared in CCMacro.js
- cc.drawingUtil = new cc.DrawingPrimitiveWebGL(cc.renderContext);
- cc.TextureCache.getInstance()._initializingRenderer();
- } else {
- cc.renderContext = cc.canvas.getContext("2d");
- cc.mainRenderContextBackup = cc.renderContext;
- cc.renderContextType = cc.CANVAS;
- cc.renderContext.translate(0, cc.canvas.height);
- cc.drawingUtil = new cc.DrawingPrimitiveCanvas(cc.renderContext);
- }
-
- cc.originalCanvasSize = cc.size(cc.canvas.width, cc.canvas.height);
- cc.gameDiv = cc.container;
-
- cc.log(cc.ENGINE_VERSION);
- cc.Configuration.getInstance();
-
- cc.setContextMenuEnable(false);
-
- if(cc.Browser.isMobile){
- cc._addUserSelectStatus();
- cc._addBottomTag();
- }
-
- var hidden, visibilityChange;
- if (typeof document.hidden !== "undefined") {
- hidden = "hidden";
- visibilityChange = "visibilitychange";
- } else if (typeof document.mozHidden !== "undefined") {
- hidden = "mozHidden";
- visibilityChange = "mozvisibilitychange";
- } else if (typeof document.msHidden !== "undefined") {
- hidden = "msHidden";
- visibilityChange = "msvisibilitychange";
- } else if (typeof document.webkitHidden !== "undefined") {
- hidden = "webkitHidden";
- visibilityChange = "webkitvisibilitychange";
- }
-
- function handleVisibilityChange() {
- if (!document[hidden])
- cc.Director.getInstance()._resetLastUpdate();
- }
-
- if (typeof document.addEventListener === "undefined" ||
- typeof hidden === "undefined") {
- cc.isAddedHiddenEvent = false;
- } else {
- cc.isAddedHiddenEvent = true;
- document.addEventListener(visibilityChange, handleVisibilityChange, false);
- }
-};
-
-cc._addUserSelectStatus = function(){
- var fontStyle = document.createElement("style");
- fontStyle.type = "text/css";
- document.body.appendChild(fontStyle);
-
- fontStyle.textContent = "body,canvas,div{ -moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;-khtml-user-select: none;"
- +"-webkit-tap-highlight-color:rgba(0,0,0,0);}";
-};
-
-cc._addBottomTag = function () {
- var bottom = document.createElement("div");
- bottom.id = "bottom";
- bottom.style.border = bottom.style.margin = bottom.style.padding = bottom.style.height = bottom.style.lineHeight = bottom.style.fontSize = "0px";
- document.body.appendChild(bottom);
- window.location.href="#bottom";
-};
-
-cc._isContextMenuEnable = false;
-/**
- * enable/disable contextMenu for Canvas
- * @param {Boolean} enabled
- */
-cc.setContextMenuEnable = function (enabled) {
- cc._isContextMenuEnable = enabled;
- if (!cc._isContextMenuEnable) {
- cc.canvas.oncontextmenu = function () {
- return false;
- };
- } else {
- cc.canvas.oncontextmenu = function () {
- };
- }
-};
-
-/**
- * Run main loop of game engine
- * @class
- * @extends cc.Class
- */
-cc.Application = cc.Class.extend(/** @lends cc.Application# */{
- _animationInterval:null,
- /**
- * Constructor
- */
- ctor:function () {
- this._animationInterval = 0;
- cc.Assert(!cc._sharedApplication, "CCApplication ctor");
- cc._sharedApplication = this;
- },
-
- /**
- * Callback by cc.Director for limit FPS.
- * @param {Number} interval The time, which expressed in second, between current frame and next.
- */
- setAnimationInterval:function (interval) {
- this._animationInterval = interval;
- },
-
- /**
- * Get status bar rectangle in EGLView window.
- * @param {cc.Rect} rect
- * @deprecated
- */
- statusBarFrame:function (rect) {
- if (rect) {
- // Windows doesn't have status bar.
- rect = cc.rect(0, 0, 0, 0);
- }
- },
-
- getTargetPlatform:function(){
- return cc.Browser.isMobile ? cc.TARGET_PLATFORM.MOBILE_BROWSER : cc.TARGET_PLATFORM.PC_BROWSER;
- },
-
- /**
- * Run the message loop.
- * @return {Number}
- */
- run:function () {
- // Initialize instance and cocos2d.
- if (!this.applicationDidFinishLaunching())
- return 0;
-
- var callback, director = cc.Director.getInstance(), w = window;
- if (w.requestAnimFrame && this._animationInterval == 1 / 60) {
- callback = function () {
- director.mainLoop();
- w.requestAnimFrame(callback);
- };
- //cc.log(window.requestAnimFrame);
- w.requestAnimFrame(callback);
- } else {
- callback = function () {
- director.mainLoop();
- };
- setInterval(callback, this._animationInterval * 1000);
- }
- return 0;
- }
-});
-
-/**
- * Get current applicaiton instance.
- * @return {cc.Application} Current application instance pointer.
- */
-cc.Application.getInstance = function () {
- cc.Assert(cc._sharedApplication, "sharedApplication");
- return cc._sharedApplication;
-};
-
-/**
- * Get current language config
- * @return {Number} Current language config
- */
-cc.Application.getCurrentLanguage = function () {
- var ret = cc.LANGUAGE_ENGLISH;
-
- var currentLang = navigator.language;
- if(!currentLang)
- currentLang = navigator.browserLanguage || navigator.userLanguage;
- if(!currentLang)
- return ret;
-
- currentLang = currentLang.toLowerCase();
- switch (currentLang) {
- case "zh-cn":
- ret = cc.LANGUAGE_CHINESE;
- break;
- case "fr":
- ret = cc.LANGUAGE_FRENCH;
- break;
- case "it":
- ret = cc.LANGUAGE_ITALIAN;
- break;
- case "de":
- ret = cc.LANGUAGE_GERMAN;
- break;
- case "es":
- ret = cc.LANGUAGE_SPANISH;
- break;
- case "ru":
- ret = cc.LANGUAGE_RUSSIAN;
- break;
- case "ko":
- ret = cc.LANGUAGE_KOREAN;
- break;
- case "ja":
- ret = cc.LANGUAGE_JAPANESE;
- break;
- case "hu":
- ret = cc.LANGUAGE_HUNGARIAN;
- break;
- case "pt":
- ret = cc.LANGUAGE_PORTUGUESE;
- break;
- case "ar":
- ret = cc.LANGUAGE_ARABIC;
- break;
- case "no":
- ret = cc.LANGUAGE_NORWEGIAN;
- break;
- case "pl":
- ret = cc.LANGUAGE_POLISH;
- break;
- }
-
- return ret;
-};
-
-cc._sharedApplication = null;
diff --git a/cocos2d/platform/CCClass.js b/cocos2d/platform/CCClass.js
deleted file mode 100644
index 05f1cc6cb7..0000000000
--- a/cocos2d/platform/CCClass.js
+++ /dev/null
@@ -1,248 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-/* Managed JavaScript Inheritance
- * Based on John Resig's Simple JavaScript Inheritance http://ejohn.org/blog/simple-javascript-inheritance/
- * MIT Licensed.
- */
-
-/**
- * @namespace
- */
-var cc = cc || {};
-
-//
-function ClassManager(){
- //tells own name
- return arguments.callee.name || (arguments.callee.toString()).match(/^function ([^(]+)/)[1];
-}
-ClassManager.id=(0|(Math.random()*998));
-ClassManager.compileSuper=function(func, name, id){
- //make the func to a string
- var str = func.toString();
- //find parameters
- var pstart = str.indexOf('(');
- var pend = str.indexOf(')');
- var params = str.substring(pstart+1, pend);
- params = params.trim();
-
- //find function body
- var bstart = str.indexOf('{');
- var bend = str.lastIndexOf('}');
- var str = str.substring(bstart+1, bend);
-
- //now we have the content of the function, replace this._super
- //find this._super
- while(str.indexOf('this._super')!= -1)
- {
- var sp = str.indexOf('this._super');
- //find the first '(' from this._super)
- var bp = str.indexOf('(', sp);
-
- //find if we are passing params to super
- var bbp = str.indexOf(')', bp);
- var superParams = str.substring(bp+1, bbp);
- superParams = superParams.trim();
- var coma = superParams? ',':'';
-
- //find name of ClassManager
- var Cstr = arguments.callee.ClassManager();
-
- //replace this._super
- str = str.substring(0, sp)+ Cstr+'['+id+'].'+name+'.call(this'+coma+str.substring(bp+1);
- }
- return Function(params, str);
-};
-ClassManager.compileSuper.ClassManager = ClassManager;
-ClassManager.getNewID=function(){
- return this.id++;
-};
-
-
-(function () {
- var initializing = false, fnTest = /\b_super\b/;
- var releaseMode = (document['ccConfig'] && document['ccConfig']['CLASS_RELEASE_MODE']) ? document['ccConfig']['CLASS_RELEASE_MODE'] : null;
- if(releaseMode) {
- console.log("release Mode");
- }
-
- /**
- * The base Class implementation (does nothing)
- * @class
- */
- cc.Class = function () {
- };
-
- /**
- * Create a new Class that inherits from this Class
- * @param {object} prop
- * @return {function}
- */
- cc.Class.extend = function (prop) {
- var _super = this.prototype;
-
- // Instantiate a base Class (but only create the instance,
- // don't run the init constructor)
- var prototype = Object.create(_super);
-
- var classId = ClassManager.getNewID();
- ClassManager[classId] = _super;
- // Copy the properties over onto the new prototype. We make function
- // properties non-eumerable as this makes typeof === 'function' check
- // unneccessary in the for...in loop used 1) for generating Class()
- // 2) for cc.clone and perhaps more. It is also required to make
- // these function properties cacheable in Carakan.
- var desc = { writable: true, enumerable: false, configurable: true };
- for (var name in prop) {
- if(releaseMode && typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) {
- desc.value = ClassManager.compileSuper(prop[name], name, classId);
- Object.defineProperty(prototype, name, desc);
- } else if(typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])){
- desc.value = (function (name, fn) {
- return function () {
- var tmp = this._super;
-
- // Add a new ._super() method that is the same method
- // but on the super-Class
- this._super = _super[name];
-
- // The method only need to be bound temporarily, so we
- // remove it when we're done executing
- var ret = fn.apply(this, arguments);
- this._super = tmp;
-
- return ret;
- };
- })(name, prop[name]);
- Object.defineProperty(prototype, name, desc);
- } else if(typeof prop[name] == "function") {
- desc.value = prop[name];
- Object.defineProperty(prototype, name, desc);
- } else{
- prototype[name] = prop[name];
- }
- }
-
- // The dummy Class constructor
- function Class() {
- // All construction is actually done in the init method
- if (this.ctor)
- this.ctor.apply(this, arguments);
- }
-
- Class.id = classId;
- // desc = { writable: true, enumerable: false, configurable: true,
- // value: XXX }; Again, we make this non-enumerable.
- desc.value = classId;
- Object.defineProperty(prototype, '__pid', desc);
-
- // Populate our constructed prototype object
- Class.prototype = prototype;
-
- // Enforce the constructor to be what we expect
- desc.value = Class;
- Object.defineProperty(Class.prototype, 'constructor', desc);
-
- // And make this Class extendable
- Class.extend = arguments.callee;
-
- //add implementation method
- Class.implement = function (prop) {
- for (var name in prop) {
- prototype[name] = prop[name];
- }
- };
- return Class;
- };
-
- Function.prototype.bind = Function.prototype.bind || function (bind) {
- var self = this;
- return function () {
- var args = Array.prototype.slice.call(arguments);
- return self.apply(bind || null, args);
- };
- };
-
-})();
-
-//
-// Another way to subclass: Using Google Closure.
-// The following code was copied + pasted from goog.base / goog.inherits
-//
-cc.inherits = function (childCtor, parentCtor) {
- /** @constructor */
- function tempCtor() {}
- tempCtor.prototype = parentCtor.prototype;
- childCtor.superClass_ = parentCtor.prototype;
- childCtor.prototype = new tempCtor();
- childCtor.prototype.constructor = childCtor;
-
- // Copy "static" method, but doesn't generate subclasses.
-// for( var i in parentCtor ) {
-// childCtor[ i ] = parentCtor[ i ];
-// }
-};
-cc.base = function(me, opt_methodName, var_args) {
- var caller = arguments.callee.caller;
- if (caller.superClass_) {
- // This is a constructor. Call the superclass constructor.
- ret = caller.superClass_.constructor.apply( me, Array.prototype.slice.call(arguments, 1));
- return ret;
- }
-
- var args = Array.prototype.slice.call(arguments, 2);
- var foundCaller = false;
- for (var ctor = me.constructor;
- ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
- if (ctor.prototype[opt_methodName] === caller) {
- foundCaller = true;
- } else if (foundCaller) {
- return ctor.prototype[opt_methodName].apply(me, args);
- }
- }
-
- // If we did not find the caller in the prototype chain,
- // then one of two things happened:
- // 1) The caller is an instance method.
- // 2) This method was not called by the right caller.
- if (me[opt_methodName] === caller) {
- return me.constructor.prototype[opt_methodName].apply(me, args);
- } else {
- throw Error(
- 'cc.base called from a method of one name ' +
- 'to a method of a different name');
- }
-};
-
-cc.concatObjectProperties = function(dstObject, srcObject){
- if(!dstObject)
- dstObject = {};
-
- for(var selKey in srcObject){
- dstObject[selKey] = srcObject[selKey];
- }
- return dstObject;
-};
-
diff --git a/cocos2d/platform/CCCommon.js b/cocos2d/platform/CCCommon.js
deleted file mode 100644
index 9fd76a5523..0000000000
--- a/cocos2d/platform/CCCommon.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * copy an new object
- * @function
- * @param {object|Array} obj source object
- * @return {Array|object}
- */
-cc.clone = function (obj) {
- // Cloning is better if the new object is having the same prototype chain
- // as the copied obj (or otherwise, the cloned object is certainly going to
- // have a different hidden class). Play with C1/C2 of the
- // PerformanceVirtualMachineTests suite to see how this makes an impact
- // under extreme conditions.
- //
- // Object.create(Object.getPrototypeOf(obj)) doesn't work well because the
- // prototype lacks a link to the constructor (Carakan, V8) so the new
- // object wouldn't have the hidden class that's associated with the
- // constructor (also, for whatever reasons, utilizing
- // Object.create(Object.getPrototypeOf(obj)) + Object.defineProperty is even
- // slower than the original in V8). Therefore, we call the constructor, but
- // there is a big caveat - it is possible that the this.init() in the
- // constructor would throw with no argument. It is also possible that a
- // derived class forgets to set "constructor" on the prototype. We ignore
- // these possibities for and the ultimate solution is a standardized
- // Object.clone().
- var newObj = (obj.constructor) ? new obj.constructor : {};
-
- // Assuming that the constuctor above initialized all properies on obj, the
- // following keyed assignments won't turn newObj into dictionary mode
- // becasue they're not *appending new properties* but *assigning existing
- // ones* (note that appending indexed properties is another story). See
- // CCClass.js for a link to the devils when the assumption fails.
- for (var key in obj) {
- var copy = obj[key];
- // Beware that typeof null == "object" !
- if (((typeof copy) == "object") && copy &&
- !(copy instanceof cc.Node) && !(copy instanceof HTMLElement)) {
- newObj[key] = cc.clone(copy);
- } else {
- newObj[key] = copy;
- }
- }
- return newObj;
-};
-
-/**
- * Function added for JS bindings compatibility. Not needed in cocos2d-html5.
- * @function
- * @param {object} jsObj subclass
- * @param {object} superclass
- */
-cc.associateWithNative = function (jsObj, superclass) {
-};
-
-/**
- * Is show bebug info on web page
- * @constant
- * @type {Boolean}
- */
-cc.IS_SHOW_DEBUG_ON_PAGE = cc.IS_SHOW_DEBUG_ON_PAGE || false;
-
-cc._logToWebPage = function (message) {
- var logList = document.getElementById("logInfoList");
- if (!logList) {
- var logDiv = document.createElement("Div");
- logDiv.setAttribute("id", "logInfoDiv");
- cc.canvas.parentNode.appendChild(logDiv);
- logDiv.setAttribute("width", "300");
- logDiv.setAttribute("height", cc.canvas.height);
- logDiv.style.zIndex = "99999";
- logDiv.style.position = "absolute";
- logDiv.style.top = "0";
- logDiv.style.left = "0";
-
- logList = document.createElement("ul");
- logDiv.appendChild(logList);
- logList.setAttribute("id", "logInfoList");
- logList.style.height = "450px";
- logList.style.color = "#fff";
- logList.style.textAlign = "left";
- logList.style.listStyle = "disc outside";
- logList.style.fontSize = "12px";
- logList.style.fontFamily = "arial";
- logList.style.padding = "0 0 0 20px";
- logList.style.margin = "0";
- logList.style.textShadow = "0 0 3px #000";
- logList.style.zIndex = "99998";
- logList.style.position = "absolute";
- logList.style.top = "0";
- logList.style.left = "0";
- logList.style.overflowY = "hidden";
-
- var tempDiv = document.createElement("Div");
- logDiv.appendChild(tempDiv);
- tempDiv.style.width = "300px";
- tempDiv.style.height = cc.canvas.height + "px";
- tempDiv.style.opacity = "0.1";
- tempDiv.style.background = "#fff";
- tempDiv.style.border = "1px solid #dfdfdf";
- tempDiv.style.borderRadius = "8px";
- }
- var addMessage = document.createElement("li");
- //var now = new Date();
- //addMessage.innerHTML = now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds() + " " + now.getMilliseconds() + " " + message;
- addMessage.innerHTML = message;
- if (logList.childNodes.length == 0) {
- logList.appendChild(addMessage);
- } else {
- logList.insertBefore(addMessage, logList.childNodes[0]);
- }
-};
-
-/**
- * Output Debug message.
- * @function
- * @param {String} message
- */
-cc.log = function (message) {
- if (!cc.IS_SHOW_DEBUG_ON_PAGE) {
- console.log(message);
- } else {
- cc._logToWebPage(message);
- }
-};
-
-/**
- * Pop out a message box
- * @param {String} message
- * @function
- */
-cc.MessageBox = function (message) {
- console.log(message);
-};
-
-/**
- * Output Assert message.
- * @function
- * @param {Boolean} cond If cond is false, assert.
- * @param {String} message
- */
-cc.Assert = function (cond, message) {
- if (console.assert)
- console.assert(cond, message);
- else {
- if (!cond) {
- if (message)
- alert(message);
- }
- }
-};
-
-/**
- * Update Debug setting.
- * @function
- */
-cc.initDebugSetting = function () {
- // cocos2d debug
- if (cc.COCOS2D_DEBUG == 0) {
- cc.log = function () {
- };
- cc.logINFO = function () {
- };
- cc.logERROR = function () {
- };
- cc.Assert = function () {
- };
- } else if (cc.COCOS2D_DEBUG == 1) {
- cc.logINFO = cc.log;
- cc.logERROR = function () {
- };
- } else if (cc.COCOS2D_DEBUG > 1) {
- cc.logINFO = cc.log;
- cc.logERROR = cc.log;
- }// COCOS2D_DEBUG
-};
-
-// Enum the language type supportted now
-/**
- * English language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_ENGLISH = 0;
-
-/**
- * Chinese language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_CHINESE = 1;
-
-/**
- * French language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_FRENCH = 2;
-
-/**
- * Italian language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_ITALIAN = 3;
-
-/**
- * German language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_GERMAN = 4;
-
-/**
- * Spanish language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_SPANISH = 5;
-
-/**
- * Russian language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_RUSSIAN = 6;
-
-/**
- * Korean language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_KOREAN = 7;
-
-/**
- * Japanese language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_JAPANESE = 8;
-
-/**
- * Hungarian language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_HUNGARIAN = 9;
-
-/**
- * Portuguese language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_PORTUGUESE = 10;
-
-/**
- * Arabic language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_ARABIC = 11;
-
-/**
- * Norwegian language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_NORWEGIAN = 12;
-
-/**
- * Polish language code
- * @constant
- * @type Number
- */
-cc.LANGUAGE_POLISH = 13;
-
-
diff --git a/cocos2d/platform/CCEGLView.js b/cocos2d/platform/CCEGLView.js
deleted file mode 100644
index 6c2ba9bc31..0000000000
--- a/cocos2d/platform/CCEGLView.js
+++ /dev/null
@@ -1,800 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.RESOLUTION_POLICY = {
- // The entire application is visible in the specified area without trying to preserve the original aspect ratio.
- // Distortion can occur, and the application may appear stretched or compressed.
- EXACT_FIT:0,
- // The entire application fills the specified area, without distortion but possibly with some cropping,
- // while maintaining the original aspect ratio of the application.
- NO_BORDER:1,
- // The entire application is visible in the specified area without distortion while maintaining the original
- // aspect ratio of the application. Borders can appear on two sides of the application.
- SHOW_ALL:2,
- // The application takes the height of the design resolution size and modifies the width of the internal
- // canvas so that it fits the aspect ratio of the device
- // no distortion will occur however you must make sure your application works on different
- // aspect ratios
- FIXED_HEIGHT:3,
- // The application takes the width of the design resolution size and modifies the height of the internal
- // canvas so that it fits the aspect ratio of the device
- // no distortion will occur however you must make sure your application works on different
- // aspect ratios
- FIXED_WIDTH:4,
-
- UNKNOWN:5
-};
-
-cc.Touches = [];
-cc.TouchesIntergerDict = {};
-
-/**
- * @class
- * @extends cc.Class
- */
-cc.EGLView = cc.Class.extend(/** @lends cc.EGLView# */{
- _delegate:null,
- // real screen size
- _screenSize:null,
- // resolution size, it is the size appropriate for the app resources.
- _designResolutionSize:null,
- // the view port size
- _viewPortRect:null,
- // the view name
- _viewName:"",
- _scaleX:1,
- _originalScaleX:1,
- _scaleY:1,
- _originalScaleY:1,
- _indexBitsUsed:0,
- _maxTouches:5,
- _resolutionPolicy:cc.RESOLUTION_POLICY.UNKNOWN,
- _initialize:false,
-
- _captured:false,
- _wnd:null,
- _hDC:null,
- _hRC:null,
- _accelerometerKeyHook:null,
- _supportTouch:false,
- _contentTranslateLeftTop:null,
-
- _menu:null,
- _wndProc:null,
- _ele:null,
- _frameZoomFactor:1.0,
- __resizeWithBrowserSize:false,
- __isAdjustSizeToBrowser:false,
-
- ctor:function () {
- this._ele = (cc.container.parentNode === document.body) ? document.documentElement : cc.container.parentNode;
- this._viewName = "Cocos2dHTML5";
-
- this._designResolutionSize = cc.SizeZero();
- this._viewPortRect = cc.RectZero();
- this._delegate = cc.Director.getInstance().getTouchDispatcher();
- this._contentTranslateLeftTop = {left:0, top:0};
- this._screenSize = cc.size(cc.canvas.width, cc.canvas.height);
-
- this._hDC = cc.canvas;
- this._hRC = cc.renderContext;
- },
-
- /**
- * init
- */
- initialize:function () {
- this._scrollToBottom();
- this._initialize = true;
- },
-
- _resizeWithBrowserSize:function(enabled){
- var adjustSize;
- if(enabled){
- //enable
- if(!this.__resizeWithBrowserSize){
- this.__resizeWithBrowserSize = true;
- adjustSize = this._adjustSizeToBrowser.bind(this);
- window.addEventListener('resize', adjustSize, false);
- }
- }else{
- //disable
- if(this.__resizeWithBrowserSize){
- this.__resizeWithBrowserSize = true;
- adjustSize = this._adjustSizeToBrowser.bind(this);
- window.removeEventListener('resize', adjustSize, false);
- }
- }
- },
-
- _scrollToBottom:function(){
- if(cc.Browser.isMobile){
- cc.canvas.height = this._ele.clientHeight + 500;
- window.location.href="#bottom";
- }
- },
-
- _initScreenSize:function(){
- var locScreenSize = this._screenSize;
- locScreenSize.width = this._ele.clientWidth;
- locScreenSize.height = this._ele.clientHeight;
- if(navigator.userAgent.match(/iPhone/i)){
- locScreenSize.height +=(locScreenSize.width/320)*60; //TODO
- }
- },
-
- _setupViewport:function(isWidth, wohValue){
- var viewportMeta, locHeadElement = document.head;
- var locMetaElements = locHeadElement.getElementsByTagName("meta");
- for(var i = 0; i < locMetaElements.length; i++){
- var selElement = locMetaElements[i];
- if(selElement.name.toLowerCase() == "viewport"){
- viewportMeta = selElement;
- break;
- }
- }
- if(!viewportMeta){
- viewportMeta = document.createElement("meta");
- viewportMeta.name = "viewport";
- locHeadElement.appendChild(viewportMeta);
- }
-
- if(isWidth)
- viewportMeta.content = "width=" + wohValue + ",user-scalable=no";
- else
- viewportMeta.content = "height=" + wohValue + ",user-scalable=no";
- },
-
- _adjustSizeToBrowser:function () {
- this.__isAdjustSizeToBrowser = true;
-
- this._scrollToBottom();
- this._initScreenSize();
-
- if (!cc.Browser.isMobile) {
- var locCanvasElement = cc.canvas;
- locCanvasElement.width = this._screenSize.width;
- locCanvasElement.height = this._screenSize.height;
-
- if (!("opengl" in sys.capabilities))
- cc.renderContext.translate(0, locCanvasElement.height);
-
- var parent = document.querySelector("#" + document['ccConfig']['tag']).parentNode;
- if (parent) {
- parent.style.width = locCanvasElement.width + "px";
- parent.style.height = locCanvasElement.height + "px";
- }
- var body = document.body;
- if (body) {
- body.style.padding = 0 + "px";
- body.style.border = 0 + "px";
- body.style.margin = 0 + "px";
- }
- }
- this.setDesignResolutionSize();
- },
-
- // hack
- _adjustSizeKeepCanvasSize:function () {
- if (!("opengl" in sys.capabilities))
- cc.renderContext.translate(0, cc.canvas.height);
- this._screenSize = cc.size(cc.canvas.width, cc.canvas.height);
- this.setDesignResolutionSize();
- },
-
- /**
- * Force destroying EGL view, subclass must implement this method.
- */
- end:function () {
- },
-
- /**
- * Get whether opengl render system is ready, subclass must implement this method.
- * @return {Boolean}
- */
- isOpenGLReady:function () {
- return (this._hDC != null && this._hRC != null);
- },
-
- /*
- * Set zoom factor for frame. This method is for debugging big resolution (e.g.new ipad) app on desktop.
- * @param {Number} zoomFactor
- */
- setFrameZoomFactor:function (zoomFactor) {
- this._frameZoomFactor = zoomFactor;
- this.centerWindow();
- cc.Director.getInstance().setProjection(cc.Director.getInstance().getProjection());
- },
-
- /**
- * Exchanges the front and back buffers, subclass must implement this method.
- */
- swapBuffers:function () {
- },
-
- /**
- * Open or close IME keyboard , subclass must implement this method.
- */
- setIMEKeyboardState:function (isOpen) {
- if (isOpen) {
- // [EAGLView sharedEGLView] becomeFirstResponder
- } else {
- // [EAGLView sharedEGLView] resignFirstResponder
- }
- },
-
- /**
- *
- * The resolution translate on EGLView
- *
- * @param {Number} offsetLeft
- * @param {Number} offsetTop
- */
- setContentTranslateLeftTop:function (offsetLeft, offsetTop) {
- this._contentTranslateLeftTop = {left:offsetLeft, top:offsetTop};
- },
-
- /**
- *
- * get the resolution translate on EGLView
- *
- * @return {cc.Size|Object}
- */
- getContentTranslateLeftTop:function () {
- return this._contentTranslateLeftTop;
- },
-
- /**
- * Get the frame size of EGL view.
- * In general, it returns the screen size since the EGL view is a fullscreen view.
- * @return {cc.Size}
- */
- getFrameSize:function () {
- return cc.size(this._screenSize.width, this._screenSize.height);
- },
-
- /**
- * Set the frame size of EGL view.
- * @param {Number} width
- * @param {Number} height
- */
- setFrameSize:function (width, height) {
- this._designResolutionSize.width = this._screenSize.width = width;
- this._designResolutionSize.height = this._screenSize.height = height;
- this.centerWindow();
- cc.Director.getInstance().setProjection(cc.Director.getInstance().getProjection());
- },
-
- centerWindow:function () {
- //do nothing
- },
-
- setAccelerometerKeyHook:function (accelerometerKeyHook) {
- this._accelerometerKeyHook = accelerometerKeyHook;
- },
-
- /**
- * Get the visible area size of opengl viewport.
- * @return {cc.Size}
- */
- getVisibleSize:function () {
- if (this._resolutionPolicy === cc.RESOLUTION_POLICY.NO_BORDER) {
- return cc.size(this._screenSize.width / this._scaleX, this._screenSize.height / this._scaleY);
- } else {
- return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
- }
- },
-
- /**
- * Get the visible origin povar of opengl viewport.
- * @return {cc.Point}
- */
- getVisibleOrigin:function () {
- if (this._resolutionPolicy === cc.RESOLUTION_POLICY.NO_BORDER) {
- return cc.p((this._designResolutionSize.width - this._screenSize.width / this._scaleX) / 2,
- (this._designResolutionSize.height - this._screenSize.height / this._scaleY) / 2);
- } else {
- return cc.p(0, 0);
- }
- },
-
- canSetContentScaleFactor:function () {
- return true;
- },
-
- /**
- * Set the design resolution size.
- * @param {Number} width Design resolution width.
- * @param {Number} height Design resolution height.
- * @param {Number} resolutionPolicy The resolution policy desired, you may choose:
- * [1] ResolutionExactFit Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio, your game view will be stretched.
- * [2] ResolutionNoBorder Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two areas of your game view will be cut.
- * [3] ResolutionShowAll Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two black borders will be shown.
- */
- setDesignResolutionSize:function (width, height, resolutionPolicy) {
- cc.Assert(resolutionPolicy !== cc.RESOLUTION_POLICY.UNKNOWN, "should set resolutionPolicy");
-
- if (width == 0 || height == 0)
- return;
-
- if ((width != null) && (height != null))
- this._designResolutionSize = cc.size(width, height);
-
- if (resolutionPolicy != null)
- this._resolutionPolicy = resolutionPolicy;
-
- if (!this._initialize) {
- this.initialize();
- }
-
- var locScreenSize = this._screenSize, locDesignResolutionSize = this._designResolutionSize;
- var locResolutionPolicy = this._resolutionPolicy;
-
- this._scaleX = locScreenSize.width / locDesignResolutionSize.width;
- this._scaleY = locScreenSize.height / locDesignResolutionSize.height;
-
- if (locResolutionPolicy === cc.RESOLUTION_POLICY.NO_BORDER)
- this._scaleX = this._scaleY = Math.max(this._scaleX, this._scaleY);
-
- if (locResolutionPolicy === cc.RESOLUTION_POLICY.SHOW_ALL)
- this._scaleX = this._scaleY = Math.min(this._scaleX, this._scaleY);
-
- if (locResolutionPolicy === cc.RESOLUTION_POLICY.FIXED_HEIGHT) {
- this._scaleX = this._scaleY;
- locDesignResolutionSize.width = Math.ceil(locScreenSize.width / this._scaleX);
- }
-
- if (locResolutionPolicy === cc.RESOLUTION_POLICY.FIXED_WIDTH) {
- this._scaleY = this._scaleX;
- locDesignResolutionSize.height = Math.ceil(locScreenSize.height / this._scaleY);
- }
-
- // calculate the rect of viewport
- var viewPortW = locDesignResolutionSize.width * this._scaleX;
- var viewPortH = locDesignResolutionSize.height * this._scaleY;
-
- this._viewPortRect = cc.rect((locScreenSize.width - viewPortW) / 2, (locScreenSize.height - viewPortH) / 2, viewPortW, viewPortH);
-
- // reset director's member variables to fit visible rect
- var director = cc.Director.getInstance();
- director._winSizeInPoints = this.getDesignResolutionSize();
-
- if (cc.renderContextType === cc.CANVAS) {
- if (locResolutionPolicy === cc.RESOLUTION_POLICY.SHOW_ALL) {
- var locHeight = Math.abs(locScreenSize.height - viewPortH) / 2;
- cc.canvas.width = viewPortW;
- cc.canvas.height = viewPortH;
- cc.container.style.textAlign = "center";
- cc.container.style.verticalAlign = "middle";
- cc.renderContext.translate(0, viewPortH);
- this._ele.style.paddingTop = locHeight + "px";
- this._ele.style.paddingBottom = locHeight + "px";
- this._viewPortRect = cc.rect(0, 0, viewPortW, viewPortH);
- } else if ((locResolutionPolicy === cc.RESOLUTION_POLICY.NO_BORDER) || (locResolutionPolicy === cc.RESOLUTION_POLICY.FIXED_WIDTH)
- || (locResolutionPolicy === cc.RESOLUTION_POLICY.FIXED_HEIGHT) || (locResolutionPolicy === cc.RESOLUTION_POLICY.EXACT_FIT)) {
- cc.canvas.width = viewPortW;
- cc.canvas.height = viewPortH;
- cc.renderContext.translate(this._viewPortRect.x, this._viewPortRect.y + this._viewPortRect.height);
- }
- } else {
- // reset director's member variables to fit visible rect
- director._createStatsLabel();
- director.setGLDefaultValues();
- }
- this._originalScaleX = this._scaleX;
- this._originalScaleY = this._scaleY;
- cc.DOM._resetEGLViewDiv();
-
- //set the viewport for mobile
- if (cc.Browser.isMobile && this.__isAdjustSizeToBrowser)
- this._calculateViewPortByPolicy();
- },
-
- _calculateViewPortByPolicy:function(){
-
- },
-
- _setScaleXYForRenderTexture:function(){
- //hack for RenderTexture on canvas mode when adapting multiple resolution resources
- var scaleFactor = cc.CONTENT_SCALE_FACTOR();
- this._scaleX = scaleFactor;
- this._scaleY = scaleFactor;
- },
-
- _resetScale:function(){
- this._scaleX = this._originalScaleX;
- this._scaleY = this._originalScaleY;
- },
- /**
- * Get design resolution size.
- * Default resolution size is the same as 'getFrameSize'.
- * @return {cc.Size}
- */
- getDesignResolutionSize:function () {
- return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
- },
-
- /**
- * set touch delegate
- * @param {cc.TouchDispatcher} delegate
- */
- setTouchDelegate:function (delegate) {
- this._delegate = delegate;
- },
-
- /**
- * Set opengl view port rectangle with points.
- * @param {Number} x
- * @param {Number} y
- * @param {Number} w width
- * @param {Number} h height
- */
- setViewPortInPoints:function (x, y, w, h) {
- var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
- cc.renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
- (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
- (w * locScaleX * locFrameZoomFactor),
- (h * locScaleY * locFrameZoomFactor));
- },
-
- /**
- * Set Scissor rectangle with points.
- * @param {Number} x
- * @param {Number} y
- * @param {Number} w
- * @param {Number} h
- */
- setScissorInPoints:function (x, y, w, h) {
- var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
- cc.renderContext.scissor((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
- (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
- (w * locScaleX * locFrameZoomFactor),
- (h * locScaleY * locFrameZoomFactor));
- },
-
- /**
- * Get whether GL_SCISSOR_TEST is enable
- */
- isScissorEnabled:function () {
- var gl = cc.renderContext;
- return gl.isEnabled(gl.SCISSOR_TEST);
- },
-
- /**
- * Get the current scissor rectangle
- * @return {cc.Rect}
- */
- getScissorRect:function () {
- var gl = cc.renderContext, scaleX = this._scaleX, scaleY = this._scaleY;
- var boxArr = gl.getParameter(gl.SCISSOR_BOX);
- return cc.rect((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / scaleY,
- boxArr[2] / scaleX, boxArr[3] / scaleY);
- },
-
- /**
- * @param {String} viewName
- */
- setViewName:function (viewName) {
- if (viewName != null && viewName.length > 0) {
- this._viewName = viewName;
- }
- },
-
- /**
- * get view name
- * @return {String}
- */
- getViewName:function () {
- return this._viewName;
- },
-
- /**
- * Get the opengl view port rectangle.
- */
- getViewPortRect:function () {
- return this._viewPortRect;
- },
-
- /**
- * Get scale factor of the horizontal direction.
- */
- getScaleX:function () {
- return this._scaleX;
- },
-
- /**
- * Get scale factor of the vertical direction.
- */
- getScaleY:function () {
- return this._scaleY;
- },
-
- /**
- * Get the real location in view
- */
- convertToLocationInView:function (tx, ty, relatedPos) {
- return {x:tx - relatedPos.left, y:relatedPos.top + relatedPos.height - ty};
- },
-
- /**
- * Touch events are handled by default; if you want to customize your handlers, please override these functions:
- * @param {Number} num
- * @param {Number} ids
- * @param {Number} xs
- * @param {Number} ys
- */
- handleTouchesBegin:function (num, ids, xs, ys) {
- var arr = [], locViewPortRect = this._viewPortRect, locScaleX = this._scaleX, locScaleY = this._scaleY;
- for (var i = 0; i < num; ++i) {
- var id = ids[i];
- var x = xs[i];
- var y = ys[i];
-
- var index = cc.TouchesIntergerDict[id];
- var unusedIndex = 0;
-
- // it is a new touch
- if (index == null) {
- unusedIndex = this._getUnUsedIndex();
-
- // The touches is more than MAX_TOUCHES ?
- if (unusedIndex == -1) {
- cc.log("The touches is more than MAX_TOUCHES, nUnusedIndex = " + unusedIndex);
- continue;
- }
-
- var touch = cc.Touches[unusedIndex] = new cc.Touch();
- touch.setTouchInfo(unusedIndex, (x - locViewPortRect.x) / locScaleX,
- (y - locViewPortRect.y) / locScaleY);
-
- //console.log("x ="+x+" y = "+y, touch.getLocation());
-
- var interObj = 0 | unusedIndex;
- cc.TouchesIntergerDict[id] = interObj;
- arr.push(touch);
- }
- }
-
- if (arr.length == 0) {
- //cc.log("touchesBegan: count = 0");
- return;
- }
- this._delegate.touchesBegan(arr, null);
- },
-
- /**
- * @param {Number} num
- * @param {Number} ids
- * @param {Number} xs
- * @param {Number} ys
- */
- handleTouchesMove:function (num, ids, xs, ys) {
- var arr = [];
- var locScaleX = this._scaleX, locScaleY = this._scaleY, locViewPortX = this._viewPortRect.x, locViewPortY = this._viewPortRect.y;
- for (var i = 0; i < num; ++i) {
- var id = ids[i];
- var x = xs[i];
- var y = ys[i];
-
- var index = cc.TouchesIntergerDict[id];
- if (index == null) {
- //cc.log("if the index doesn't exist, it is an error");
- continue;
- }
-
- var touch = cc.Touches[index];
- if (touch) {
- touch.setTouchInfo(index, (x - locViewPortX) / locScaleX,
- (y - locViewPortY) / locScaleY);
- arr.push(touch);
- }
- else {
- // It is error, should return.
- //cc.log("Moving touches with id: " + id + " error");
- return;
- }
- }
-
- if (arr.length == 0) {
- //cc.log("touchesMoved: count = 0");
- return;
- }
-
- this._delegate.touchesMoved(arr, null);
- },
-
- /**
- * @param {Number} num
- * @param {Number} ids
- * @param {Number} xs
- * @param {Number} ys
- */
- handleTouchesEnd:function (num, ids, xs, ys) {
- var arr = [];
- this.getSetOfTouchesEndOrCancel(arr, num, ids, xs, ys);
- this._delegate.touchesEnded(arr, null);
- },
-
- /**
- * @param {Number} num
- * @param {Number} ids
- * @param {Number} xs
- * @param {Number} ys
- */
- handleTouchesCancel:function (num, ids, xs, ys) {
- var arr = [];
- this.getSetOfTouchesEndOrCancel(arr, num, ids, xs, ys);
- this._delegate.touchesCancelled(arr, null);
- },
-
- /**
- * @param {Array} arr
- * @param {Number} num
- * @param {Number} ids
- * @param {Number} xs
- * @param {Number} ys
- */
- getSetOfTouchesEndOrCancel:function (arr, num, ids, xs, ys) {
- var locScaleX = this._scaleX, locScaleY = this._scaleY, locViewPortRect = this._viewPortRect;
- for (var i = 0; i < num; ++i) {
- var id = ids[i];
- var x = xs[i];
- var y = ys[i];
-
- var index = cc.TouchesIntergerDict[id];
- if (index == null) {
- //cc.log("if the index doesn't exist, it is an error");
- continue;
- }
- /* Add to the set to send to the director */
- var touch = cc.Touches[index];
- if (touch) {
- //cc.log("Ending touches with id: " + id + ", x=" + x + ", y=" + y);
- touch.setTouchInfo(index, (x - locViewPortRect.x) / locScaleX,
- (y - locViewPortRect.y) / locScaleY);
-
- arr.push(touch);
-
- // release the object
- cc.Touches[index] = null;
- this._removeUsedIndexBit(index);
-
- delete cc.TouchesIntergerDict[id];
- } else {
- //cc.log("Ending touches with id: " + id + " error");
- return;
- }
- }
-
- /*if (arr.length == 0) {
- cc.log("touchesEnded or touchesCancel: count = 0");
- }*/
- },
-
- _getUnUsedIndex:function () {
- var i;
- var temp = this._indexBitsUsed;
-
- for (i = 0; i < this._maxTouches; i++) {
- if (!(temp & 0x00000001)) {
- this._indexBitsUsed |= (1 << i);
- return i;
- }
-
- temp >>= 1;
- }
-
- // all bits are used
- return -1;
- },
-
- _removeUsedIndexBit:function (index) {
- if (index < 0 || index >= this._maxTouches) {
- return;
- }
-
- var temp = 1 << index;
- temp = ~temp;
- this._indexBitsUsed &= temp;
- },
-
- // Pass the touches to the superview
- touchesBegan:function (touches, event) {
- var ids = [];
- var xs = [];
- var ys = [];
-
- var i = 0;
- var touch;
- for (var j = 0; j < touches.length; j++) {
- touch = touches[j];
- ids[i] = touch.getId() || j;
- xs[i] = touch.getLocation().x;
- ys[i] = touch.getLocation().y;
- ++i;
- }
- this.handleTouchesBegin(i, ids, xs, ys);
- },
-
- touchesMoved:function (touches, event) {
- var ids = [];
- var xs = [];
- var ys = [];
-
- var i = 0;
- var touch;
- for (var j = 0; j < touches.length; j++) {
- touch = touches[j];
- ids[i] = touch.getId() || j;
- xs[i] = touch.getLocation().x;
- ys[i] = touch.getLocation().y;
- ++i;
- }
- this.handleTouchesMove(i, ids, xs, ys);
- },
-
- touchesEnded:function (touches, event) {
- var ids = [];
- var xs = [];
- var ys = [];
-
- var i = 0;
- var touch;
- for (var j = 0; j < touches.length; j++) {
- touch = touches[j];
- ids[i] = touch.getId() || j;
- xs[i] = touch.getLocation().x;
- ys[i] = touch.getLocation().y;
- ++i;
- }
- this.handleTouchesEnd(i, ids, xs, ys);
- },
-
- touchesCancelled:function (touches, event) {
- var ids = [];
- var xs = [];
- var ys = [];
-
- var i = 0;
- var touch;
- for (var j = 0; j < touches.length; j++) {
- touch = touches[j];
- ids[i] = touch.getId() || j;
- xs[i] = touch.getLocation().x;
- ys[i] = touch.getLocation().y;
- ++i;
- }
- this.handleTouchesCancel(i, ids, xs, ys);
- }
-});
-
-
-cc.EGLView.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.EGLView();
- }
- return this._instance;
-};
diff --git a/cocos2d/platform/CCFileUtils.js b/cocos2d/platform/CCFileUtils.js
deleted file mode 100644
index db47db057f..0000000000
--- a/cocos2d/platform/CCFileUtils.js
+++ /dev/null
@@ -1,808 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * @constant
- * @type Number
- */
-cc.SAX_NONE = 0;
-
-/**
- * @constant
- * @type Number
- */
-cc.SAX_KEY = 1;
-
-/**
- * @constant
- * @type Number
- */
-cc.SAX_DICT = 2;
-
-/**
- * @constant
- * @type Number
- */
-cc.SAX_INT = 3;
-
-/**
- * @constant
- * @type Number
- */
-cc.SAX_REAL = 4;
-
-/**
- * @constant
- * @type Number
- */
-cc.SAX_STRING = 5;
-
-/**
- * @constant
- * @type Number
- */
-cc.SAX_ARRAY = 6;
-
-//Compatibility with IE9
-var Uint8Array = Uint8Array || Array;
-
-if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
- var IEBinaryToArray_ByteStr_Script =
- "\r\n" +
- //"\r\n";
-
- // inject VBScript
- //document.write(IEBinaryToArray_ByteStr_Script);
- var myVBScript = document.createElement('script');
- myVBScript.type = "text/vbscript";
- myVBScript.textContent = IEBinaryToArray_ByteStr_Script;
- document.body.appendChild(myVBScript);
-
- // helper to convert from responseBody to a "responseText" like thing
- cc._convertResponseBodyToText = function (binary) {
- var byteMapping = {};
- for (var i = 0; i < 256; i++) {
- for (var j = 0; j < 256; j++) {
- byteMapping[ String.fromCharCode(i + j * 256) ] =
- String.fromCharCode(i) + String.fromCharCode(j);
- }
- }
- var rawBytes = IEBinaryToArray_ByteStr(binary);
- var lastChr = IEBinaryToArray_ByteStr_Last(binary);
- return rawBytes.replace(/[\s\S]/g,
- function (match) {
- return byteMapping[match];
- }) + lastChr;
- };
-}
-
-/**
- * @namespace
- */
-cc.FileUtils = cc.Class.extend({
- _fileDataCache:null,
- _textFileCache:null,
-
- _directory:null,
- _filenameLookupDict:null,
- _searchResolutionsOrderArray:null,
- _searchPathArray:null,
- _defaultResRootPath:"",
-
- ctor:function () {
- this._fileDataCache = {};
- this._textFileCache = {};
-
- this._searchPathArray = [];
- this._searchPathArray.push(this._defaultResRootPath);
-
- this._searchResolutionsOrderArray = [];
- this._searchResolutionsOrderArray.push("");
- },
-
- /**
- *
- * Purges the file searching cache.
- *
- * @note It should be invoked after the resources were updated.
- * For instance, in the CocosPlayer sample, every time you run application from CocosBuilder,
- * All the resources will be downloaded to the writable folder, before new js app launchs,
- * this method should be invoked to clean the file search cache.
- *
- */
- purgeCachedEntries:function(){
- this._searchPathArray = [];
- },
- /**
- * Get Byte Array from file
- * @function
- * @param {String} fileName The resource file name which contain the path
- * @param {String} mode mode The read mode of the file
- * @param {Number} size If get the file data succeed the it will be the data size,or it will be 0
- * @warning If you get the file data succeed,you must delete it after used.
- */
- getByteArrayFromFile:function (fileName, mode, size) {
- fileName = this.fullPathForFilename(fileName);
- if (this._fileDataCache.hasOwnProperty(fileName))
- return this._fileDataCache[fileName];
- return this._loadBinaryFileData(fileName);
- },
-
- _getXMLHttpRequest:function () {
- if (window.XMLHttpRequest) {
- return new window.XMLHttpRequest();
- } else {
- return new ActiveXObject("MSXML2.XMLHTTP");
- }
- },
-
- unloadBinaryFileData:function (fileUrl) {
- if (this._fileDataCache.hasOwnProperty(fileUrl))
- delete this._fileDataCache[fileUrl];
- },
-
- preloadBinaryFileData:function (fileUrl) {
- fileUrl = this.fullPathForFilename(fileUrl);
- var selfPointer = this;
-
- var xhr = this._getXMLHttpRequest();
- xhr.open("GET", fileUrl, true);
- if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
- // IE-specific logic here
- xhr.setRequestHeader("Accept-Charset", "x-user-defined");
- xhr.onreadystatechange = function (event) {
- if (xhr.readyState == 4) {
- if (xhr.status == 200) {
- var fileContents = cc._convertResponseBodyToText(xhr["responseBody"]);
- if (fileContents)
- selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents);
- } else {
- cc.Loader.getInstance().onResLoadingErr(fileUrl);
- }
- cc.Loader.getInstance().onResLoaded();
- }
- };
- } else {
- if (xhr.overrideMimeType)
- xhr.overrideMimeType("text\/plain; charset=x-user-defined");
-
- xhr.onload = function (e) {
- var fileContents = xhr.responseText;
- if (fileContents) {
- selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents);
- } else {
- cc.Loader.getInstance().onResLoadingErr(fileUrl);
- }
- cc.Loader.getInstance().onResLoaded();
- };
- }
- xhr.send(null);
- },
-
- _loadBinaryFileData:function (fileUrl) {
- var req = this._getXMLHttpRequest();
- req.open('GET', fileUrl, false);
- var arrayInfo = null;
- if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
- req.setRequestHeader("Accept-Charset", "x-user-defined");
- req.send(null);
- if (req.status != 200)
- return null;
-
- var fileContents = cc._convertResponseBodyToText(req["responseBody"]);
- if (fileContents) {
- arrayInfo = this._stringConvertToArray(fileContents);
- this._fileDataCache[fileUrl] = arrayInfo;
- }
- } else {
- if (req.overrideMimeType)
- req.overrideMimeType('text\/plain; charset=x-user-defined');
- req.send(null);
- if (req.status != 200)
- return null;
-
- arrayInfo = this._stringConvertToArray(req.responseText);
- this._fileDataCache[fileUrl] = arrayInfo;
- }
- return arrayInfo;
- },
-
- _stringConvertToArray:function (strData) {
- if (!strData)
- return null;
-
- var arrData = new Uint8Array(strData.length);
- for (var i = 0; i < strData.length; i++) {
- arrData[i] = strData.charCodeAt(i) & 0xff;
- }
- return arrData;
- },
-
- unloadTextFileData:function (fileUrl) {
- if (this._textFileCache.hasOwnProperty(fileUrl))
- delete this._textFileCache[fileUrl];
- },
-
- preloadTextFileData:function (fileUrl) {
- fileUrl = this.fullPathForFilename(fileUrl);
- var selfPointer = this;
-
- var xhr = this._getXMLHttpRequest();
- xhr.open("GET", fileUrl, true);
- if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
- // IE-specific logic here
- xhr.setRequestHeader("Accept-Charset", "utf-8");
- xhr.onreadystatechange = function (event) {
- if (xhr.readyState == 4) {
- if (xhr.status == 200) {
- var fileContents = xhr.responseText;
- if (fileContents)
- selfPointer._textFileCache[fileUrl] = fileContents;
- } else {
- cc.Loader.getInstance().onResLoadingErr(fileUrl);
- }
- cc.Loader.getInstance().onResLoaded();
- }
- };
- } else {
- if (xhr.overrideMimeType)
- xhr.overrideMimeType("text\/plain; charset=utf-8");
- xhr.onload = function (e) {
- if (xhr.responseText) {
- selfPointer._textFileCache[fileUrl] = xhr.responseText;
- } else {
- cc.Loader.getInstance().onResLoadingErr(fileUrl);
- }
- cc.Loader.getInstance().onResLoaded();
- };
- }
- xhr.send(null);
- },
-
- _loadTextFileData:function (fileUrl) {
- var req = this._getXMLHttpRequest();
- req.open('GET', fileUrl, false);
- var fileContents = null;
- if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
- req.setRequestHeader("Accept-Charset", "utf-8");
- } else {
- if (req.overrideMimeType)
- req.overrideMimeType('text\/plain; charset=utf-8');
- }
- req.send(null);
- if (req.status != 200)
- return null;
-
- fileContents = req.responseText;
- if (fileContents) {
- this._textFileCache[fileUrl] = fileContents;
- }
- return fileContents;
- },
-
- /**
- * Gets resource file data
- * @param {String} fileUrl The resource file name which contains the path.
- * @returns {String}
- */
- getTextFileData:function (fileUrl) {
- if (this._textFileCache.hasOwnProperty(fileUrl))
- return this._textFileCache[fileUrl];
- return this._loadTextFileData(fileUrl);
- },
-
- /**
- * Get resource file data from zip file
- * @function
- * @param {String} pszZipFilePath
- * @param {String} fileName fileName The resource file name which contain the relative path of zip file
- * @param {Number} size size If get the file data succeed the it will be the data size,or it will be 0
- * @warning If you get the file data succeed,you must delete it after used.
- * @deprecated
- */
- getFileDataFromZip:function (pszZipFilePath, fileName, size) {
- },
-
- /**
- * removes the HD suffix from a path
- * @function
- * @param {String} path
- * @deprecated
- */
- removeSuffixFromFile:function (path) {
- },
-
- //////////////////////////////////////////////////////////////////////////
- // Notification support when getByteArrayFromFile from invalid file path.
- //////////////////////////////////////////////////////////////////////////
- /**
- * Notification support when getByteArrayFromFile from invalid file path.
- * @function
- * @type {Boolean}
- */
- popupNotify:true,
-
- /**
- * Generate the absolute path of the file.
- * @function
- * @param {String} pszRelativePath
- * @return {String} The absolute path of the file.
- * @warning We only add the ResourcePath before the relative path of the file.
- * If you have not set the ResourcePath,the function add "/NEWPLUS/TDA_DATA/UserData/" as default.
- * You can set ResourcePath by function void setResourcePath(const char *resourcePath);
- */
- fullPathFromRelativePath:function (pszRelativePath) {
- return pszRelativePath;
- },
-
- /**
- *
- * Returns the fullpath for a given filename.
- * First it will try to get a new filename from the "filenameLookup" dictionary.
- * If a new filename can't be found on the dictionary, it will use the original filename.
- * Then it will try obtain the full path of the filename using the CCFileUtils search rules: resources directory and search paths.
- * The file search is based on the array element order of search paths and resolution directories.
- *
- * For instance:
- *
- * We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths,
- * and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd")
- * to resolutions vector by setSearchResolutionsOrder. The "internal_dir" is relative to "Resources/".
- *
- * If we have a file named 'sprite.png', the mapping in fileLookup dictionary contains `key: sprite.png -> value: sprite.pvr.gz`.
- * Firstly, it will replace 'sprite.png' with 'sprite.pvr.gz', then searching the file sprite.pvr.gz as follows:
- * /mnt/sdcard/resources-ipadhd/sprite.pvr.gz (if not found, search next)
- * /mnt/sdcard/resources-ipad/sprite.pvr.gz (if not found, search next)
- * /mnt/sdcard/resources-iphonehd/sprite.pvr.gz (if not found, search next)
- * /mnt/sdcard/sprite.pvr.gz (if not found, search next)
- * internal_dir/resources-ipadhd/sprite.pvr.gz (if not found, search next)
- * internal_dir/resources-ipad/sprite.pvr.gz (if not found, search next)
- * internal_dir/resources-iphonehd/sprite.pvr.gz (if not found, search next)
- * internal_dir/sprite.pvr.gz (if not found, return "sprite.png")
- *
- * If the filename contains relative path like "gamescene/uilayer/sprite.png",
- * and the mapping in fileLookup dictionary contains `key: gamescene/uilayer/sprite.png -> value: gamescene/uilayer/sprite.pvr.gz`.
- * The file search order will be:
- * /mnt/sdcard/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
- * /mnt/sdcard/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
- * /mnt/sdcard/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
- * /mnt/sdcard/gamescene/uilayer/sprite.pvr.gz (if not found, search next)
- * internal_dir/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
- * internal_dir/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
- * internal_dir/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
- * internal_dir/gamescene/uilayer/sprite.pvr.gz (if not found, return "gamescene/uilayer/sprite.png")
- *
- * If the new file can't be found on the file system, it will return the parameter pszFileName directly.
- *
- * This method was added to simplify multiplatform support. Whether you are using cocos2d-js or any cross-compilation toolchain like StellaSDK or Apportable,
- * you might need to load different resources for a given file in the different platforms.
- *
- * @param {String} filename
- * @return {String} full path for a given filename.
- */
- fullPathForFilename:function (filename) {
- var found = false;
-
- var newFileName = this._getNewFilename(filename);
- var fullPath;
-
- //if (newFileName && newFileName.length > 1)
- // return newFileName;
-
- for (var i = 0; i < this._searchPathArray.length; i++) {
- var searchPath = this._searchPathArray[i];
- for (var j = 0; j < this._searchResolutionsOrderArray.length; j++) {
- var resourceDirectory = this._searchResolutionsOrderArray[j];
- fullPath = this._getPathForFilename(newFileName, resourceDirectory, searchPath);
- if (fullPath) {
- found = true;
- break;
- }
- }
- if (found)
- break;
- }
-
- return found ? fullPath : newFileName;
- },
-
- /**
- *
- * Loads the filenameLookup dictionary from the contents of a filename.
- *
- * @note The plist file name should follow the format below:
- *
- *
- *
- *
- * filenames
- *
- * sounds/click.wav
- * sounds/click.caf
- * sounds/endgame.wav
- * sounds/endgame.caf
- * sounds/gem-0.wav
- * sounds/gem-0.caf
- *
- * metadata
- *
- * version
- * 1
- *
- *
- *
- *
- * @param {String} filename The plist file name.
- */
- loadFilenameLookup:function (filename) {
- var fullPath = this.fullPathForFilename(filename);
- if (fullPath.length > 0) {
- var dict = cc.SAXParser.getInstance().parse(fullPath);
- var metadataDict = dict["metadata"];
- var version = parseInt(metadataDict["version"]);
- if (version != 1) {
- cc.log("cocos2d: ERROR: Invalid filenameLookup dictionary version: " + version + ". Filename: " + filename);
- return;
- }
- this.setFilenameLookupDictionary(dict["filenames"]);
- }
- },
-
- /**
- * Sets the filenameLookup dictionary.
- * @param {Object} filenameLookupDict The dictionary for replacing filename.
- */
- setFilenameLookupDictionary:function (filenameLookupDict) {
- this._filenameLookupDict = filenameLookupDict;
- },
-
- /**
- * Gets full path from a file name and the path of the reletive file.
- * @param {String} filename The file name.
- * @param {String} relativeFile The path of the relative file.
- * @return {String} The full path.
- */
- fullPathFromRelativeFile:function (filename, relativeFile) {
- var tmpPath;
- if (filename) {
- tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf("/") + 1);
- return tmpPath + filename;
- }
- else {
- tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf("."));
- tmpPath = tmpPath + ".png";
- return tmpPath;
- }
- },
-
- /**
- *
- * Sets the array that contains the search order of the resources.
- *
- * @see getSearchResolutionsOrder(void), fullPathForFilename(const char*).
- * @param {Array} searchResolutionsOrder
- */
- setSearchResolutionsOrder:function (searchResolutionsOrder) {
- this._searchResolutionsOrderArray = searchResolutionsOrder;
- },
-
- /**
- * Gets the array that contains the search order of the resources.
- * @see setSearchResolutionsOrder(), fullPathForFilename(const char*).
- * @return {Array}
- */
- getSearchResolutionsOrder:function () {
- return this._searchResolutionsOrderArray;
- },
-
- /**
- *
- * Array of search paths.
- * You can use this array to modify the search path of the resources.
- * If you want to use "themes" or search resources in the "cache", you can do it easily by adding new entries in this array.
- *
- * By default it is an array with only the "" (empty string) element.
- *
- * @param {Array} searchPaths
- */
- setSearchPath:function (searchPaths) {
- this._searchPathArray = searchPaths;
- },
-
- /**
- * return Array of search paths.
- * @return {Array}
- */
- getSearchPath:function () {
- return this._searchPathArray;
- },
-
- getResourceDirectory:function () {
- return this._directory;
- },
-
-
- /**
- * Set the ResourcePath,we will find resource in this path
- * @function
- * @param {String} resourcePath The absolute resource path
- * @warning Don't call this function in android and iOS, it has not effect.
- * In android, if you want to read file other than apk, you shoud use invoke getByteArrayFromFile(), and pass the
- * absolute path.
- * @deprecated
- */
- setResourcePath:function (resourcePath) {
- },
-
- /**
- * Generate an Dictionary of object by file
- * @deprecated
- * @param fileName The file name of *.plist file
- * @return {object} The Dictionary of object generated from the file
- */
- dictionaryWithContentsOfFile:function (fileName) {
- cc.log("dictionaryWithContentsOfFile is deprecated. Use createDictionaryWithContentsOfFile instead");
- return this.createDictionaryWithContentsOfFile(fileName);
- },
-
- /**
- * Generate an Dictionary of object by file
- * @param filename The file name of *.plist file
- * @return {object} The Dictionary of object generated from the file
- */
- createDictionaryWithContentsOfFile: function(filename){
- return cc.SAXParser.getInstance().parse(filename);
- },
-
- /**
- * get string from file
- * @function
- * @param {String} fileName
- * @return {String}
- */
- getStringFromFile:function (fileName) {
- return this.getTextFileData(fileName); //cc.SAXParser.getInstance().getList(fileName);
- },
-
- /**
- * The same meaning as dictionaryWithContentsOfFile(), but it doesn't call autorelease, so the invoker should call release().
- * @function
- * @param {String} fileName
- * @return {object} The Dictionary of object generated from the file
- */
- dictionaryWithContentsOfFileThreadSafe:function (fileName) {
- return cc.SAXParser.getInstance().parse(fileName);
- },
-
- /**
- * Get the writeable path
- * @return {String} The path that can write/read file
- * @deprecated
- */
- getWritablePath:function () {
- return "";
- },
-
- /**
- * Set whether pop-up a message box when the image load failed
- * @param {Boolean} notify
- */
- setPopupNotify:function (notify) {
- cc.popupNotify = notify;
- },
-
- /**
- * Get whether pop-up a message box when the image load failed
- * @return {Boolean}
- */
- isPopupNotify:function () {
- return cc.popupNotify;
- },
-
- _resourceRootPath:"",
- getResourceRootPath:function () {
- return this._resourceRootPath;
- },
-
- setResourceRootPath:function (resourceRootPath) {
- this._resourceRootPath = resourceRootPath;
- },
-
- /**
- * Gets the new filename from the filename lookup dictionary.
- * @param {String} filename
- * @return {String|null} The new filename after searching in the filename lookup dictionary. If the original filename wasn't in the dictionary, it will return the original filename.
- * @private
- */
- _getNewFilename:function (filename) {
- var newFileName = null;
- var fileNameFound = this._filenameLookupDict ? this._filenameLookupDict[filename] : null;
- if (!fileNameFound || fileNameFound.length === 0)
- newFileName = filename;
- else {
- newFileName = fileNameFound;
- cc.log("FOUND NEW FILE NAME: " + newFileName);
- }
- return newFileName;
- },
-
- /**
- * Gets full path for filename, resolution directory and search path.
- * @param {String} filename
- * @param {String} resourceDirectory
- * @param {String} searchPath
- * @return {String} The full path of the file. It will return an empty string if the full path of the file doesn't exist.
- * @private
- */
- _getPathForFilename:function (filename, resourceDirectory, searchPath) {
- var ret;
- var resourceRootPath = this.getResourceRootPath(); //cc.Application.getInstance().getResourceRootPath();
-
- if (filename && (filename.length > 0) && (filename.indexOf('/') === 0 || filename.indexOf("\\") === 0)) {
- ret = "";
- } else if (resourceRootPath.length > 0) {
- ret = resourceRootPath;
- if (ret[ret.length - 1] != '\\' && ret[ret.length - 1] != '/')
- ret += "/";
- } else {
- ret = resourceRootPath;
- }
-
- var file = filename;
- var file_path = "";
- var pos = filename.lastIndexOf('/');
- if (pos != -1) {
- file_path = filename.substr(0, pos + 1);
- file = filename.substr(pos + 1);
- }
- var path = searchPath;
- if (path.length > 0 && path.lastIndexOf('/') !== path.length - 1)
- path += '/';
- path += file_path;
- path += resourceDirectory;
- if (path.length > 0 && path.lastIndexOf("/") !== path.length - 1)
- path += '/';
- path += file;
- ret += path;
- return ret;
- },
-
- /**
- * Gets full path for the directory and the filename.
- * @param {String} directory The directory contains the file we are looking for.
- * @param {String} fileName The name of the file.
- * @return {Boolean} The full path of the file, if the file can't be found, it will return an empty string.
- * @private
- */
- _getFullPathForDirectoryAndFilename:function(directory, fileName){
-
- },
-
- /**
- *
- * Sets the array of search paths.
- *
- * You can use this array to modify the search path of the resources.
- * If you want to use "themes" or search resources in the "cache", you can do it easily by adding new entries in this array.
- *
- * @note This method could access relative path and absolute path.
- * If the relative path was passed to the vector, CCFileUtils will add the default resource directory before the relative path.
- * For instance:
- * On Android, the default resource root path is "assets/".
- * If "/mnt/sdcard/" and "resources-large" were set to the search paths vector,
- * "resources-large" will be converted to "assets/resources-large" since it was a relative path.
- *
- * @see fullPathForFilename(const char*)
- * @param {Array} searchPaths The array contains search paths.
- */
- setSearchPaths:function (searchPaths) {
- var existDefaultRootPath = false;
-
- this._searchPathArray = [];
- for (var i = 0; i < searchPaths.length; i++) {
- var iter = searchPaths[i];
-
- var strPrefix;
- var path;
- if (!this.isAbsolutePath(iter)) { // Not an absolute path
- strPrefix = this._defaultResRootPath;
- }
- path = strPrefix + iter;
- if (path.length > 0 && path[path.length - 1] != '/') {
- path += "/";
- }
- if (!existDefaultRootPath && path == this._defaultResRootPath) {
- existDefaultRootPath = true;
- }
- this._searchPathArray.push(path);
- }
-
- if (!existDefaultRootPath) {
- //cc.log("Default root path doesn't exist, adding it.");
- this._searchPathArray.push(this._defaultResRootPath);
- }
-
- },
-
- /**
- * Add search path.
- * @param {String} path
- */
- addSearchPath:function (path) {
- var strPrefix;
- if (!this.isAbsolutePath(path)) { // Not an absolute path
- strPrefix = this._defaultResRootPath;
- }
- path = strPrefix + path;
- if (path.length > 0 && path[path.length - 1] != '/') {
- path += "/";
- }
- this._searchPathArray.push(path);
- },
-
- /**
- * Gets the array of search paths.
- * @see fullPathForFilename(const char*).
- * @return {Array} The array of search paths.
- */
- getSearchPaths:function(){
-
- },
-
- /**
- * Checks whether the path is an absolute path.
- * @param {String} strPath The path that needs to be checked.
- * @returns {boolean} true if it's an absolute path, otherwise it will return false.
- */
- isAbsolutePath:function (strPath) {
- return (strPath[0] == '/');
- }
-});
-
-cc.s_SharedFileUtils = null;
-/**
- * Gets the instance of CCFileUtils.
- * @returns {cc.FileUtils}
- */
-cc.FileUtils.getInstance = function () {
- if (cc.s_SharedFileUtils == null) {
- cc.s_SharedFileUtils = new cc.FileUtils();
- }
- return cc.s_SharedFileUtils;
-};
diff --git a/cocos2d/platform/CCImage.js b/cocos2d/platform/CCImage.js
deleted file mode 100644
index 9455779488..0000000000
--- a/cocos2d/platform/CCImage.js
+++ /dev/null
@@ -1,372 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Image Format:JPG
- * @constant
- * @type Number
- */
-cc.FMT_JPG = 0;
-
-/**
- * Image Format:PNG
- * @constant
- * @type Number
- */
-cc.FMT_PNG = 1;
-
-/**
- * Image Format:TIFF
- * @constant
- * @type Number
- */
-cc.FMT_TIFF = 2;
-
-/**
- * Image Format:RAWDATA
- * @constant
- * @type Number
- */
-cc.FMT_RAWDATA = 3;
-
-/**
- * Image Format:WEBP
- * @constant
- * @type Number
- */
-cc.FMT_WEBP = 4;
-
-/**
- * Image Format:UNKNOWN
- * @constant
- * @type Number
- */
-cc.FMT_UNKNOWN = 5;
-
-/**
- * Horizontal center and vertical center.
- * @constant
- * @type Number
- */
-cc.ALIGN_CENTER = 0x33;
-
-/**
- * Horizontal center and vertical top.
- * @constant
- * @type Number
- */
-cc.ALIGN_TOP = 0x13;
-
-/**
- * Horizontal right and vertical top.
- * @constant
- * @type Number
- */
-cc.ALIGN_TOP_RIGHT = 0x12;
-
-/**
- * Horizontal right and vertical center.
- * @constant
- * @type Number
- */
-cc.ALIGN_RIGHT = 0x32;
-
-/**
- * Horizontal right and vertical bottom.
- * @constant
- * @type Number
- */
-cc.ALIGN_BOTTOM_RIGHT = 0x22;
-
-/**
- * Horizontal center and vertical bottom.
- * @constant
- * @type Number
- */
-cc.ALIGN_BOTTOM = 0x23;
-
-/**
- * Horizontal left and vertical bottom.
- * @constant
- * @type Number
- */
-cc.ALIGN_BOTTOM_LEFT = 0x21;
-
-/**
- * Horizontal left and vertical center.
- * @constant
- * @type Number
- */
-cc.ALIGN_LEFT = 0x31;
-
-/**
- * Horizontal left and vertical top.
- * @constant
- * @type Number
- */
-cc.ALIGN_TOP_LEFT = 0x11;
-
-/**
- * premultiply alpha, or the effect will wrong when want to use other pixel format in CCTexture2D,
- * such as RGB888, RGB5A1
- * @param {Number} vr
- * @param {Number} vg
- * @param {Number} vb
- * @param {Number} va
- * @return {Number}
- * @constructor
- */
-cc.RGB_PREMULTIPLY_APLHA = function (vr, vg, vb, va) {
- return ((vr * (va + 1)) >> 8) | ((vg * (va + 1) >> 8) << 8) | ((vb * (va + 1) >> 8) << 16) | ((va) << 24)
-}
-
-/**
- * image source
- * @Class
- * @Construct
- * @param {Array||String} data
- * @param {Number} size
- * @param {Number} offset
- */
-cc.tImageSource = function (data, size, offset) {
- this.data = data;
- this.size = size || 0;
- this.offset = offset || 0;
-};
-
-cc.pngReadCallback = function (png_ptr, data, length) {
- var isource = new cc.tImageSource();
- isource = cc.png_get_io_ptr(png_ptr);
-
- if (isource.offset + length <= isource.size) {
- cc.memcpy(data, isource.data + isource.offset, length);
- isource.offset += length;
- }
- else {
- cc.png_error(png_ptr, "pngReaderCallback failed");
- }
-};
-
-cc.getImageFormatByData = function (imgData) {
- // if it is a png file buffer.
- if (imgData.length > 8) {
- if (imgData[0] == 0x89
- && imgData[1] == 0x50
- && imgData[2] == 0x4E
- && imgData[3] == 0x47
- && imgData[4] == 0x0D
- && imgData[5] == 0x0A
- && imgData[6] == 0x1A
- && imgData[7] == 0x0A) {
- return cc.FMT_PNG;
- }
- }
-
- // if it is a tiff file buffer.
- if (imgData.length > 2) {
- if ((imgData[0] == 0x49 && imgData[1] == 0x49)
- || (imgData[0] == 0x4d && imgData[1] == 0x4d)
- || (imgData[0] == 0xff && imgData[1] == 0xd8)) {
- return cc.FMT_TIFF;
- }
- }
-
- return cc.FMT_UNKNOWN;
-};
-
-/**
- * Image
- * @class
- * @extends cc.Class
- */
-cc.Image = cc.Class.extend(/** @lends cc.Image# */{
- _width: 0,
- _height: 0,
- _bitsPerComponent: 0,
- _data: 0,
- _hasAlpha: false,
- _preMulti: false,
-
- /**
- * Load the image from the specified path.
- * @param {String} strPath the absolute file path
- * @param {Number} imageType the type of image, now only support tow types.
- * @return {Boolean} true if load correctly
- */
- initWithImageFile: function (strPath, imageType) {
- var data = cc.FileUtils.getInstance().getFileData(strPath, "rb");
- var size = data.length;
- if (data != null && data.length > 0)
- return this.initWithImageData(data, data.length, imageType);
- return false;
- },
-
- /**
- * The same meaning as initWithImageFile, but it is thread safe. It is casued by loadImage() in cc.TextureCache.
- * @param {String} fullpath full path of the file
- * @param {Number} imageType the type of image, now only support tow types.
- * @return {Boolean} true if load correctly
- */
- initWithImageFileThreadSafe: function (fullpath, imageType) {
- return this.initWithImageFile(fullpath, imageType);
- },
-
- /**
- * Load image from stream buffer.
- * @warning FMT_RAWDATA only support RGBA8888
- * @param {Array} data stream buffer that hold the image data
- * @param {Number} dataLen the length of data(managed in byte)
- * @param {Number} eFmt
- * @param {Number} width
- * @param {Number} height
- * @param {Number} bitsPerComponent
- * @return {Boolean} true if load correctly
- */
- initWithImageData: function (data, dataLen, eFmt, width, height, bitsPerComponent) {
- bitsPerComponent = bitsPerComponent || 8;
- width = width || 0;
- height = height || 0;
- eFmt = eFmt || cc.FMT_UNKNOWN;
-
- if (!data || dataLen <= 0)
- return false;
-
- if (cc.FMT_PNG == eFmt)
- return this._initWithPngData(data, dataLen);
- else if (cc.FMT_JPG == eFmt)
- return this._initWithJpgData(data, dataLen);
- else if (cc.FMT_TIFF == eFmt)
- return this._initWithTiffData(data, dataLen);
- else if (cc.FMT_RAWDATA == eFmt)
- return this._initWithRawData(data, dataLen, width, height, bitsPerComponent);
- else {
- // if it is a png file buffer.
- if (dataLen > 8) {
- if (data[0] == 0x89
- && data[1] == 0x50
- && data[2] == 0x4E
- && data[3] == 0x47
- && data[4] == 0x0D
- && data[5] == 0x0A
- && data[6] == 0x1A
- && data[7] == 0x0A) {
- return this._initWithPngData(data, dataLen);
- }
- }
-
- // if it is a tiff file buffer.
- if (dataLen > 2) {
- if ((data[0] == 0x49 && data[1] == 0x49)
- || (data[0] == 0x4d && data[1] == 0x4d)) {
- return this._initWithTiffData(data, dataLen);
- } else if (data[0] == 0xff && data[1] == 0xd8) {
- return this._initWithTiffData(data, dataLen);
- }
- }
- }
- return false;
- },
-
- getData: function () {
- return this._data;
- },
-
- getDataLen: function () {
- return this._width * this._height;
- },
-
- hasAlpha: function () {
- return this._hasAlpha;
- },
-
- isPremultipliedAlpha: function () {
- return this._preMulti;
- },
-
- getWidth: function () {
- return this._width;
- },
-
- getHeight: function () {
- return this._height;
- },
-
- getBitsPerComponent: function () {
- return this._bitsPerComponent;
- },
-
- /**
- * Save the CCImage data to specified file with specified format.
- * @param {String} filePath the file's absolute path, including file subfix
- * @param {Boolean} isToRGB if the image is saved as RGB format
- * @return {Boolean}
- */
- saveToFile: function (filePath, isToRGB) {
- //
- cc.log("doesn't support saveToFile on Cocos2d-Html5");
- return false;
- },
-
- /*protected:*/
- _initWithJpgData: function (data, dataLen) {
- return false;
- },
-
- _initWithPngData: function (data, datalen) {
- return false;
- },
-
- _initWithTiffData: function (data, dataLen) {
- return false;
- },
-
- // @warning FMT_RAWDATA only support RGBA8888
- _initWithRawData: function (data, datalen, width, height, bitsPerComponent) {
- return false;
- },
-
- _saveImageToPNG: function (filePath, isToRGB) {
- return false;
- },
-
- _saveImageToJPG: function (filePath) {
- return false;
- },
-
- /**
- * Create image with specified string.
- * @param {String} text the text which the image show, nil cause init fail
- * @param {Number} width the image width, if 0, the width match the text's width
- * @param {Number} height the image height, if 0, the height match the text's height
- * @param {Number} eAlignMask the test Alignment
- * @param {String} fontName the name of the font which use to draw the text. If nil, use the default system font.
- * @param {Number} size the font size, if 0, use the system default size.
- * @return {Boolean}
- */
- initWithString: function (text, width, height, eAlignMask, fontName, size) {
- return false;
- }
-});
diff --git a/cocos2d/platform/CCMacro.js b/cocos2d/platform/CCMacro.js
deleted file mode 100644
index 79d229b0a4..0000000000
--- a/cocos2d/platform/CCMacro.js
+++ /dev/null
@@ -1,350 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * @constant
- * @type Number
- */
-cc.INVALID_INDEX = -1;
-
-/**
- * PI is the ratio of a circle's circumference to its diameter.
- * @constant
- * @type Number
- */
-cc.PI = Math.PI;
-
-/**
- * @constant
- * @type Number
- */
-cc.FLT_MAX = parseFloat('3.402823466e+38F');
-
-/**
- * @constant
- * @type Number
- */
-cc.RAD = cc.PI / 180;
-
-/**
- * @constant
- * @type Number
- */
-cc.DEG = 180 / cc.PI;
-
-/**
- * maximum unsigned int value
- * @constant
- * @type Number
- */
-cc.UINT_MAX = 0xffffffff;
-
-/**
- *
- * simple macro that swaps 2 variables
- * modified from c++ macro, you need to pass in the x and y variables names in string,
- * and then a reference to the whole object as third variable
- *
- * @param x
- * @param y
- * @param ref
- * @function
- * @deprecated
- */
-cc.SWAP = function (x, y, ref) {
- if ((typeof ref) == 'object' && (typeof ref.x) != 'undefined' && (typeof ref.y) != 'undefined') {
- var tmp = ref[x];
- ref[x] = ref[y];
- ref[y] = tmp;
- } else
- cc.Assert(false, "CC_SWAP is being modified from original macro, please check usage");
-};
-
-/**
- *
- * Linear interpolation between 2 numbers, the ratio sets how much it is biased to each end
- *
- * @param {Number} a number A
- * @param {Number} b number B
- * @param {Number} r ratio between 0 and 1
- * @function
- * @example
- * cc.lerp(2,10,0.5)//returns 6
- * cc.lerp(2,10,0.2)//returns 3.6
- */
-cc.lerp = function (a, b, r) {
- return a + (b - a) * r;
-};
-
-/**
- * returns a random float between -1 and 1
- * @return {Number}
- * @function
- */
-cc.RANDOM_MINUS1_1 = function () {
- return (Math.random() - 0.5) * 2;
-};
-
-/**
- * returns a random float between 0 and 1
- * @return {Number}
- * @function
- */
-cc.RANDOM_0_1 = function () {
- return Math.random();
-};
-
-/**
- * converts degrees to radians
- * @param {Number} angle
- * @return {Number}
- * @function
- */
-cc.DEGREES_TO_RADIANS = function (angle) {
- return angle * cc.RAD;
-};
-
-/**
- * converts radians to degrees
- * @param {Number} angle
- * @return {Number}
- * @function
- */
-cc.RADIANS_TO_DEGREES = function (angle) {
- return angle * cc.DEG;
-};
-
-/**
- * @constant
- * @type Number
- */
-cc.REPEAT_FOREVER = Number.MAX_VALUE - 1;
-
-/**
- * default gl blend src function. Compatible with premultiplied alpha images.
- * @constant
- * @type Number
- */
-cc.BLEND_SRC = cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA ? 1 : 0x0302;
-
-/**
- * default gl blend dst function. Compatible with premultiplied alpha images.
- * @constant
- * @type Number
- */
-cc.BLEND_DST = 0x0303;
-
-/**
- * Helpful macro that setups the GL server state, the correct GL program and sets the Model View Projection matrix
- * @param {cc.Node} node setup node
- * @function
- */
-cc.NODE_DRAW_SETUP = function (node) {
- //cc.glEnable(node._glServerState);
- if (node._shaderProgram) {
- //cc.renderContext.useProgram(node._shaderProgram._programObj);
- node._shaderProgram.use();
- node._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
- }
-};
-
-/**
- *
- * GL states that are enabled:
- * - GL_TEXTURE_2D
- * - GL_VERTEX_ARRAY
- * - GL_TEXTURE_COORD_ARRAY
- * - GL_COLOR_ARRAY
- *
- * @function
- */
-cc.ENABLE_DEFAULT_GL_STATES = function () {
- //TODO OPENGL STUFF
- /*
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnable(GL_TEXTURE_2D);*/
-};
-
-/**
- *
- * Disable default GL states:
- * - GL_TEXTURE_2D
- * - GL_TEXTURE_COORD_ARRAY
- * - GL_COLOR_ARRAY
- *
- * @function
- */
-cc.DISABLE_DEFAULT_GL_STATES = function () {
- //TODO OPENGL
- /*
- glDisable(GL_TEXTURE_2D);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- */
-};
-
-/**
- *
- * Increments the GL Draws counts by one.
- * The number of calls per frame are displayed on the screen when the CCDirector's stats are enabled.
- *
- * @param {Number} addNumber
- * @function
- */
-cc.INCREMENT_GL_DRAWS = function (addNumber) {
- cc.g_NumberOfDraws += addNumber;
-};
-
-/**
- * @constant
- * @type Number
- */
-cc.FLT_EPSILON = 0.0000001192092896;
-
-/**
- *
- * On Mac it returns 1;
- * On iPhone it returns 2 if RetinaDisplay is On. Otherwise it returns 1
- *
- * @function
- */
-cc.CONTENT_SCALE_FACTOR = cc.IS_RETINA_DISPLAY_SUPPORTED ? function () {
- return cc.Director.getInstance().getContentScaleFactor();
-} : function () {
- return 1;
-};
-
-/**
- * Converts a rect in points to pixels
- * @param {cc.Point} points
- * @return {cc.Point}
- * @function
- */
-cc.POINT_POINTS_TO_PIXELS = function (points) {
- return cc.p(points.x * cc.CONTENT_SCALE_FACTOR(), points.y * cc.CONTENT_SCALE_FACTOR())
-};
-
-/**
- * Converts a rect in points to pixels
- * @param {cc.Size} sizeInPoints
- * @return {cc.Size}
- * @function
- */
-cc.SIZE_POINTS_TO_PIXELS = function (sizeInPoints) {
- return cc.size(sizeInPoints.width * cc.CONTENT_SCALE_FACTOR(), sizeInPoints.height * cc.CONTENT_SCALE_FACTOR());
-};
-
-/**
- * Converts a rect in pixels to points
- * @param {cc.Size} sizeInPixels
- * @return {cc.Size}
- * @function
- */
-cc.SIZE_PIXELS_TO_POINTS = function (sizeInPixels) {
- return cc.size(sizeInPixels.width / cc.CONTENT_SCALE_FACTOR(), sizeInPixels.height / cc.CONTENT_SCALE_FACTOR());
-};
-
-/**
- * Converts a rect in pixels to points
- * @param pixels
- * @function
- */
-cc.POINT_PIXELS_TO_POINTS = function (pixels) {
- return cc.p(pixels.x / cc.CONTENT_SCALE_FACTOR(), pixels.y / cc.CONTENT_SCALE_FACTOR());
-};
-
-
-/**
- * Converts a rect in pixels to points
- * @param {cc.Rect} pixel
- * @function
- */
-cc.RECT_PIXELS_TO_POINTS = cc.IS_RETINA_DISPLAY_SUPPORTED ? function (pixel) {
- return cc.rect(pixel.x / cc.CONTENT_SCALE_FACTOR(), pixel.y / cc.CONTENT_SCALE_FACTOR(),
- pixel.width / cc.CONTENT_SCALE_FACTOR(), pixel.height / cc.CONTENT_SCALE_FACTOR());
-} : function (p) {
- return p;
-};
-
-/**
- * Converts a rect in points to pixels
- * @param {cc.Rect} point
- * @function
- */
-cc.RECT_POINTS_TO_PIXELS = cc.IS_RETINA_DISPLAY_SUPPORTED ? function (point) {
- return cc.rect(point.x * cc.CONTENT_SCALE_FACTOR(), point.y * cc.CONTENT_SCALE_FACTOR(),
- point.width * cc.CONTENT_SCALE_FACTOR(), point.height * cc.CONTENT_SCALE_FACTOR());
-} : function (p) {
- return p;
-};
-
-if (!cc.Browser.supportWebGL) {
- /**
- * WebGL constants
- * @type {object}
- */
- var gl = gl || {};
-
- /**
- * @constant
- * @type Number
- */
- gl.ONE = 1;
-
- /**
- * @constant
- * @type Number
- */
- gl.ZERO = 0;
-
- /**
- * @constant
- * @type Number
- */
- gl.SRC_ALPHA = 0x0302;
-
- /**
- * @constant
- * @type Number
- */
- gl.ONE_MINUS_SRC_ALPHA = 0x0303;
-
- /**
- * @constant
- * @type Number
- */
- gl.ONE_MINUS_DST_COLOR = 0x0307;
-}
-
-cc.CHECK_GL_ERROR_DEBUG = function () {
- var _error = cc.renderContext.getError();
- if (_error) {
- cc.log("WebGL error " + _error);
- }
-};
diff --git a/cocos2d/platform/CCSAXParser.js b/cocos2d/platform/CCSAXParser.js
deleted file mode 100644
index 19392b9158..0000000000
--- a/cocos2d/platform/CCSAXParser.js
+++ /dev/null
@@ -1,258 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * a SAX Parser
- * @class
- * @extends cc.Class
- */
-cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{
- xmlDoc: null,
- _parser: null,
- _xmlDict: null,
- _isSupportDOMParser: null,
-
- ctor: function () {
- this._xmlDict = {};
-
- if (window.DOMParser) {
- this._isSupportDOMParser = true;
- this._parser = new DOMParser();
- } else {
- this._isSupportDOMParser = false;
- }
- },
-
- /**
- * parse a xml from a string (xmlhttpObj.responseText)
- * @param {String} textxml plist xml contents
- * @return {Array} plist object array
- */
- parse: function (textxml) {
- var path = textxml;
- textxml = this.getList(textxml);
-
- var xmlDoc = this._parserXML(textxml, path);
-
- var plist = xmlDoc.documentElement;
- if (plist.tagName != 'plist')
- throw "cocos2d: " + path + " is not a plist file";
-
- // Get first real node
- var node = null;
- for (var i = 0, len = plist.childNodes.length; i < len; i++) {
- node = plist.childNodes[i];
- if (node.nodeType == 1)
- break
- }
- xmlDoc = null;
-
- return this._parseNode(node);
- },
-
- /**
- * parse a tilemap xml from a string (xmlhttpObj.responseText)
- * @param {String} textxml tilemap xml content
- * @return {Document} xml document
- */
- tmxParse: function (textxml, isXMLString) {
- if ((isXMLString == null) || (isXMLString === false))
- textxml = this.getList(textxml);
-
- return this._parserXML(textxml);
- },
-
- _parserXML: function (textxml, path) {
- // get a reference to the requested corresponding xml file
- var xmlDoc;
- if (this._isSupportDOMParser) {
- xmlDoc = this._parser.parseFromString(textxml, "text/xml");
- } else {
- // Internet Explorer (untested!)
- xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
- xmlDoc.async = "false";
- xmlDoc.loadXML(textxml);
- }
-
- if (xmlDoc == null)
- cc.log("cocos2d:xml " + path + " not found!");
-
- return xmlDoc;
- },
-
- _parseNode: function (node) {
- var data = null;
- switch (node.tagName) {
- case 'dict':
- data = this._parseDict(node);
- break;
- case 'array':
- data = this._parseArray(node);
- break;
- case 'string':
- if (node.childNodes.length == 1)
- data = node.firstChild.nodeValue;
- else {
- //handle Firefox's 4KB nodeValue limit
- data = "";
- for (var i = 0; i < node.childNodes.length; i++)
- data += node.childNodes[i].nodeValue;
- }
- break;
- case 'false':
- data = false;
- break;
- case 'true':
- data = true;
- break;
- case 'real':
- data = parseFloat(node.firstChild.nodeValue);
- break;
- case 'integer':
- data = parseInt(node.firstChild.nodeValue, 10);
- break;
- }
-
- return data;
- },
-
- _parseArray: function (node) {
- var data = [];
- for (var i = 0, len = node.childNodes.length; i < len; i++) {
- var child = node.childNodes[i];
- if (child.nodeType != 1)
- continue;
- data.push(this._parseNode(child));
- }
- return data;
- },
-
- _parseDict: function (node) {
- var data = {};
-
- var key = null;
- for (var i = 0, len = node.childNodes.length; i < len; i++) {
- var child = node.childNodes[i];
- if (child.nodeType != 1)
- continue;
-
- // Grab the key, next noe should be the value
- if (child.tagName == 'key')
- key = child.firstChild.nodeValue;
- else
- data[key] = this._parseNode(child); // Parse the value node
- }
- return data;
- },
-
- /**
- * Preload plist file
- * @param {String} filePath
- */
- preloadPlist: function (filePath) {
- filePath = cc.FileUtils.getInstance().fullPathForFilename(filePath);
-
- if (window.XMLHttpRequest) {
- var xmlhttp = new XMLHttpRequest();
- if (xmlhttp.overrideMimeType)
- xmlhttp.overrideMimeType('text/xml');
- }
-
- if (xmlhttp != null) {
- var that = this;
- xmlhttp.onreadystatechange = function () {
- if (xmlhttp.readyState == 4) {
- if (xmlhttp.responseText) {
- cc.Loader.getInstance().onResLoaded();
- that._xmlDict[filePath] = xmlhttp.responseText;
- xmlhttp = null;
- } else
- cc.Assert("cocos2d:There was a problem retrieving the xml data:" + xmlhttp.statusText);
- }
- };
- // load xml
- xmlhttp.open("GET", filePath, true);
- xmlhttp.send(null);
- } else
- cc.Assert("cocos2d:Your browser does not support XMLHTTP.");
- },
-
- /**
- * Unload the preloaded plist from xmlList
- * @param {String} filePath
- */
- unloadPlist: function (filePath) {
- if (this._xmlDict.hasOwnProperty(filePath))
- delete this._xmlDict[filePath];
- },
-
- /**
- * get filename from filepath
- * @param {String} filePath
- * @return {String}
- */
- getName: function (filePath) {
- var startPos = filePath.lastIndexOf("/", filePath.length) + 1;
- var endPos = filePath.lastIndexOf(".", filePath.length);
- return filePath.substring(startPos, endPos);
- },
-
- /**
- * get file extension name from filepath
- * @param {String} filePath
- * @return {String}
- */
- getExt: function (filePath) {
- var startPos = filePath.lastIndexOf(".", filePath.length) + 1;
- return filePath.substring(startPos, filePath.length);
- },
-
- /**
- * get value by key from xmlList
- * @param {String} key
- * @return {String} xml content
- */
- getList: function (key) {
- if (this._xmlDict != null) {
- return this._xmlDict[key];
- }
- return null;
- }
-});
-
-/**
- * get a singleton SAX parser
- * @function
- * @return {cc.SAXParser}
- */
-cc.SAXParser.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.SAXParser();
- }
- return this._instance;
-};
-
-cc.SAXParser._instance = null;
\ No newline at end of file
diff --git a/cocos2d/platform/CCTypes.js b/cocos2d/platform/CCTypes.js
deleted file mode 100644
index 8ab9dff686..0000000000
--- a/cocos2d/platform/CCTypes.js
+++ /dev/null
@@ -1,1396 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * RGB color composed of bytes 3 bytes
- * @Class
- * @Construct
- * @param {Number | cc.Color3B} r1 red value (0 to 255) or destination color of new color
- * @param {Number} g1 green value (0 to 255)
- * @param {Number} b1 blue value (0 to 255)
- * @example
- * //create an empty color
- * var color1 = new cc.Color3B();
- *
- * //create a red color
- * var redColor = new cc.Color3B(255,0,0);
- *
- * //create a new color with color
- * var newColor = new cc.Color3B(redColor);
- */
-cc.Color3B = function (r1, g1, b1) {
- switch (arguments.length) {
- case 0:
- this.r = 0;
- this.g = 0;
- this.b = 0;
- break;
- case 1:
- if (r1 && r1 instanceof cc.Color3B) {
- this.r = (0 | r1.r) || 0;
- this.g = (0 | r1.g) || 0;
- this.b = (0 | r1.b) || 0;
- } else {
- this.r = 0;
- this.g = 0;
- this.b = 0;
- }
- break;
- case 3:
- this.r = (0 | r1) || 0;
- this.g = (0 | g1) || 0;
- this.b = (0 | b1) || 0;
- break;
- default:
- throw "unknown argument type";
- break;
- }
-};
-
-/**
- * helper macro that creates an ccColor3B type
- * @function
- * @param {Number} r red value (0 to 255)
- * @param {Number} g green value (0 to 255)
- * @param {Number} b blue value (0 to 255)
- * @return {Number,Number,Number}
- */
-cc.c3b = function (r, g, b) {
- return new cc.Color3B(r, g, b);
-};
-
-cc.integerToColor3B = function (intValue) {
- intValue = intValue || 0;
-
- var offset = 0xff;
- var retColor = new cc.Color3B();
- retColor.r = intValue & (offset);
- retColor.g = (intValue >> 8) & offset;
- retColor.b = (intValue >> 16) & offset;
- return retColor;
-};
-
-// compatibility
-cc.c3 = cc.c3b;
-
-/**
- * returns true if both ccColor3B are equal. Otherwise it returns false.
- * @param {cc.Color3B} color1
- * @param {cc.Color3B} color2
- * @return {Boolean} true if both ccColor3B are equal. Otherwise it returns false.
- */
-cc.c3BEqual = function(color1, color2){
- return color1.r === color2.r && color1.g === color2.g && color1.b === color2.b;
-};
-
-//ccColor3B predefined colors
-Object.defineProperties(cc, {
- WHITE: {
- get: function () {
- return cc.c3b(255, 255, 255);
- }
- },
- YELLOW: {
- get: function () {
- return cc.c3b(255, 255, 0);
- }
- },
- BLUE: {
- get: function () {
- return cc.c3b(0, 0, 255);
- }
- },
- GREEN: {
- get: function () {
- return cc.c3b(0, 255, 0);
- }
- },
- RED: {
- get: function () {
- return cc.c3b(255, 0, 0);
- }
- },
- MAGENTA: {
- get: function () {
- return cc.c3b(255, 0, 255);
- }
- },
- BLACK: {
- get: function () {
- return cc.c3b(0, 0, 0);
- }
- },
- ORANGE: {
- get: function () {
- return cc.c3b(255, 127, 0);
- }
- },
- GRAY: {
- get: function () {
- return cc.c3b(166, 166, 166);
- }
- }
-});
-
-/**
- * White color (255,255,255)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.white = function () {
- return new cc.Color3B(255, 255, 255);
-};
-
-/**
- * Yellow color (255,255,0)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.yellow = function () {
- return new cc.Color3B(255, 255, 0);
-};
-
-/**
- * Blue color (0,0,255)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.blue = function () {
- return new cc.Color3B(0, 0, 255);
-};
-
-/**
- * Green Color (0,255,0)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.green = function () {
- return new cc.Color3B(0, 255, 0);
-};
-
-/**
- * Red Color (255,0,0,)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.red = function () {
- return new cc.Color3B(255, 0, 0);
-};
-
-/**
- * Magenta Color (255,0,255)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.magenta = function () {
- return new cc.Color3B(255, 0, 255);
-};
-
-/**
- * Black Color (0,0,0)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.black = function () {
- return new cc.Color3B(0, 0, 0);
-};
-
-/**
- * Orange Color (255,127,0)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.orange = function () {
- return new cc.Color3B(255, 127, 0);
-};
-
-/**
- * Gray Color (166,166,166)
- * @constant
- * @type {Number,Number,Number}
- */
-cc.gray = function () {
- return new cc.Color3B(166, 166, 166);
-};
-
-/**
- * RGBA color composed of 4 bytes
- * @Class
- * @Construct
- * @param {Number} r1 red value (0 to 255)
- * @param {Number} g1 green value (0 to 255)
- * @param {Number} b1 blue value (0 to 255)
- * @param {Number} a1 Alpha value (0 to 255)
- * @example
- * //create a red color
- * var redColor = new cc.Color4B(255,0,0,255);
- */
-cc.Color4B = function (r1, g1, b1, a1) {
- this.r = 0 | r1;
- this.g = 0 | g1;
- this.b = 0 | b1;
- this.a = 0 | a1;
-};
-
-/**
- * helper macro that creates an ccColor4B type
- * @function
- * @param {Number} r red value (0 to 255)
- * @param {Number} g green value (0 to 255)
- * @param {Number} b blue value (0 to 255)
- * @param {Number} a Alpha value (0 to 255)
- * @return {Number,Number,Number,Number}
- */
-cc.c4b = function (r, g, b, a) {
- return new cc.Color4B(r, g, b, a);
-};
-
-// backwards compatibility
-cc.c4 = cc.c4b;
-
-/**
- * RGBA color composed of 4 floats
- * @Class
- * @Construct
- * @param {Number} r1 red value (0 to 1)
- * @param {Number} g1 green value (0 to 1)
- * @param {Number} b1 blue value (0 to 1)
- * @param {Number} a1 Alpha value (0 to 1)
- * @example
- * //create a red color
- * var redColor = new cc.Color4F(1,0,0,1);
- */
-cc.Color4F = function (r1, g1, b1, a1) {
- this.r = r1;
- this.g = g1;
- this.b = b1;
- this.a = a1;
-};
-
-
-/**
- * helper macro that creates an ccColor4F type
- * @Class
- * @Construct
- * @param {Number} r red value (0 to 1)
- * @param {Number} g green value (0 to 1)
- * @param {Number} b blue value (0 to 1)
- * @param {Number} a Alpha value (0 to 1)
- * @example
- * //create a red color
- * var redColor = cc.c4f(1,0,0,1);
- */
-cc.c4f = function (r, g, b, a) {
- return new cc.Color4F(r, g, b, a);
-};
-
-/**
- * Returns a cc.Color4F from a cc.Color3B. Alpha will be 1.
- * @function
- * @param {cc.Color3B} c color
- * @return {cc.Color4F}
- */
-cc.c4FFromccc3B = function (c) {
- return new cc.Color4F(c.r / 255.0, c.g / 255.0, c.b / 255.0, 1.0);
-};
-
-/**
- * Returns a cc.Color4F from a cc.Color4B.
- * @function
- * @param {cc.Color4B} c Color
- * @return {cc.Color4F}
- */
-cc.c4FFromccc4B = function (c) {
- return new cc.Color4F(c.r / 255.0, c.g / 255.0, c.b / 255.0, c.a / 255.0);
-};
-
-/**
- * Returns a cc.Color4B from a cc.Color4F.
- * @param {cc.Color4F} c
- * @return {cc.Color4B}
- */
-cc.c4BFromccc4F = function (c) {
- return new cc.Color4B(0 | (c.r * 255), 0 | (c.g * 255), 0 | (c.b * 255), 0 | (c.a * 255));
-};
-
-/**
- * returns YES if both cc.Color4F are equal. Otherwise it returns NO.
- * @param {cc.Color4F} a color1
- * @param {cc.Color4F} b color2
- * @return {Boolean}
- */
-cc.c4FEqual = function (a, b) {
- return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
-};
-
-/**
- * A vertex composed of 2 floats: x, y
- * @Class
- * @Construct
- * @param {Number} x1
- * @param {Number} y1
- */
-cc.Vertex2F = function (x1, y1) {
- this.x = x1 || 0;
- this.y = y1 || 0;
-};
-
-/**
- * helper macro that creates an Vertex2F type
- * @function
- * @param {Number} x
- * @param {Number} y
- * @return {cc.Vertex2F}
- */
-cc.Vertex2 = function (x, y) {
- return new cc.Vertex2F(x, y);
-};
-
-/**
- * A vertex composed of 3 floats: x, y, z
- * @Class
- * @Construct
- * @param {Number} x1
- * @param {Number} y1
- * @param {Number} z1
- */
-cc.Vertex3F = function (x1, y1, z1) {
- this.x = x1 || 0;
- this.y = y1 || 0;
- this.z = z1 || 0;
-};
-
-/**
- * helper macro that creates an Vertex3F type
- * @function
- * @param {Number} x
- * @param {Number} y
- * @param {Number} z
- * @return {cc.Vertex3F}
- */
-cc.vertex3 = function (x, y, z) {
- return new cc.Vertex3F(x, y, z);
-};
-
-/**
- * A texcoord composed of 2 floats: u, y
- * @Class
- * @Construct
- * @param {Number} u1
- * @param {Number} v1
- */
-cc.Tex2F = function (u1, v1) {
- this.u = u1 || 0;
- this.v = v1 || 0;
-};
-
-/**
- * helper macro that creates an Tex2F type
- * @function
- * @param {Number} u
- * @param {Number} v
- * @return {cc.Tex2F}
- */
-cc.tex2 = function (u, v) {
- return new cc.Tex2F(u, v);
-};
-
-/**
- * Point Sprite component
- * @Class
- * @Construct
- * @param {cc.Vertex2F} pos1
- * @param {cc.Color4B} color1
- * @param {Number} size1
- */
-cc.PointSprite = function (pos1, color1, size1) {
- this.pos = pos1 || new cc.Vertex2F(0, 0);
- this.color = color1 || new cc.Color4B(0, 0, 0, 0);
- this.size = size1 || 0;
-};
-
-/**
- * A 2D Quad. 4 * 2 floats
- * @Class
- * @Construct
- * @param {cc.Vertex2F} tl1
- * @param {cc.Vertex2F} tr1
- * @param {cc.Vertex2F} bl1
- * @param {cc.Vertex2F} br1
- */
-cc.Quad2 = function (tl1, tr1, bl1, br1) {
- this.tl = tl1 || new cc.Vertex2F(0, 0);
- this.tr = tr1 || new cc.Vertex2F(0, 0);
- this.bl = bl1 || new cc.Vertex2F(0, 0);
- this.br = br1 || new cc.Vertex2F(0, 0);
-};
-
-/**
- * A 3D Quad. 4 * 3 floats
- * @Class
- * @Construct
- * @param {cc.Vertex3F} bl1
- * @param {cc.Vertex3F} br1
- * @param {cc.Vertex3F} tl1
- * @param {cc.Vertex3F} tr1
- */
-cc.Quad3 = function (bl1, br1, tl1, tr1) {
- this.bl = bl1 || new cc.Vertex3F(0, 0, 0);
- this.br = br1 || new cc.Vertex3F(0, 0, 0);
- this.tl = tl1 || new cc.Vertex3F(0, 0, 0);
- this.tr = tr1 || new cc.Vertex3F(0, 0, 0);
-};
-
-/**
- * A 2D grid size
- * @Class
- * @Construct
- * @param {Number} x1
- * @param {Number} y1
- * @deprecated
- */
-cc.GridSize = function (x1, y1) {
- this.x = x1;
- this.y = y1;
-};
-
-/**
- * helper function to create a cc.GridSize
- * @function
- * @param {Number} x
- * @param {Number} y
- * @return {cc.GridSize}
- * @deprecated
- */
-cc.g = function (x, y) {
- return new cc.GridSize(x, y);
-};
-
-/**
- * a Point with a vertex point, a tex coord point and a color 4B
- * @Class
- * @Construct
- * @param {cc.Vertex2F} vertices1
- * @param {cc.Color4B} colors1
- * @param {cc.Tex2F} texCoords1
- */
-cc.V2F_C4B_T2F = function (vertices1, colors1, texCoords1) {
- this.vertices = vertices1 || new cc.Vertex2F(0, 0);
- this.colors = colors1 || new cc.Color4B(0, 0, 0, 0);
- this.texCoords = texCoords1 || new cc.Tex2F(0, 0);
-};
-
-/**
- * a Point with a vertex point, a tex coord point and a color 4F
- * @Class
- * @Construct
- * @param {cc.Vertex2F} vertices1
- * @param {cc.Color4F} colors1
- * @param {cc.Tex2F} texCoords1
- */
-cc.V2F_C4F_T2F = function (vertices1, colors1, texCoords1) {
- this.vertices = vertices1 || new cc.Vertex2F(0, 0);
- this.colors = colors1 || new cc.Color4F(0, 0, 0, 0);
- this.texCoords = texCoords1 || new cc.Tex2F(0, 0);
-};
-
-/**
- * a Point with a vertex point, a tex coord point and a color 4B
- * @Class
- * @Construct
- * @param {cc.Vertex3F} vertices1
- * @param {cc.Color4B} colors1
- * @param {cc.Tex2F} texCoords1
- */
-cc.V3F_C4B_T2F = function (vertices1, colors1, texCoords1) {
- this.vertices = vertices1 || new cc.Vertex3F(0, 0, 0);
- this.colors = colors1 || new cc.Color4B(0, 0, 0, 0);
- this.texCoords = texCoords1 || new cc.Tex2F(0, 0);
-};
-
-/**
- * A Triangle of ccV2F_C4B_T2F
- * @Class
- * @Construct
- * @param {cc.V2F_C4B_T2F} a
- * @param {cc.V2F_C4B_T2F} b
- * @param {cc.V2F_C4B_T2F} c
- */
-cc.V2F_C4B_T2F_Triangle = function (a, b, c) {
- this.a = a || new cc.V2F_C4B_T2F();
- this.b = b || new cc.V2F_C4B_T2F();
- this.c = c || new cc.V2F_C4B_T2F();
-};
-
-/**
- * 4 ccVertex2FTex2FColor4B Quad
- * @Class
- * @Construct
- * @param {cc.V2F_C4B_T2F} bl1 bottom left
- * @param {cc.V2F_C4B_T2F} br1 bottom right
- * @param {cc.V2F_C4B_T2F} tl1 top left
- * @param {cc.V2F_C4B_T2F} tr1 top right
- */
-cc.V2F_C4B_T2F_Quad = function (bl1, br1, tl1, tr1) {
- this.bl = bl1 || new cc.V2F_C4B_T2F();
- this.br = br1 || new cc.V2F_C4B_T2F();
- this.tl = tl1 || new cc.V2F_C4B_T2F();
- this.tr = tr1 || new cc.V2F_C4B_T2F();
-};
-
-/**
- * helper function to create a cc.V2F_C4B_T2F_Quad
- * @function
- * @return {cc.V2F_C4B_T2F_Quad}
- */
-cc.V2F_C4B_T2F_QuadZero = function () {
- return new cc.V2F_C4B_T2F_Quad(
- new cc.V2F_C4B_T2F(new cc.Vertex2F(0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0)),
- new cc.V2F_C4B_T2F(new cc.Vertex2F(0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0)),
- new cc.V2F_C4B_T2F(new cc.Vertex2F(0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0)),
- new cc.V2F_C4B_T2F(new cc.Vertex2F(0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0))
- );
-};
-
-/**
- * 4 ccVertex3FTex2FColor4B
- * @Class
- * @Construct
- * @param {cc.V3F_C4B_T2F} tl1 top left
- * @param {cc.V3F_C4B_T2F} bl1 bottom left
- * @param {cc.V3F_C4B_T2F} tr1 top right
- * @param {cc.V3F_C4B_T2F} br1 bottom right
- */
-cc.V3F_C4B_T2F_Quad = function (tl1, bl1, tr1, br1) {
- this.tl = tl1 || new cc.V3F_C4B_T2F();
- this.bl = bl1 || new cc.V3F_C4B_T2F();
- this.tr = tr1 || new cc.V3F_C4B_T2F();
- this.br = br1 || new cc.V3F_C4B_T2F();
-};
-
-/**
- * helper function to create a cc.V3F_C4B_T2F_Quad
- * @function
- * @return {cc.V3F_C4B_T2F_Quad}
- */
-cc.V3F_C4B_T2F_QuadZero = function () {
- return new cc.V3F_C4B_T2F_Quad(
- new cc.V3F_C4B_T2F(new cc.Vertex3F(0, 0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0)),
- new cc.V3F_C4B_T2F(new cc.Vertex3F(0, 0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0)),
- new cc.V3F_C4B_T2F(new cc.Vertex3F(0, 0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0)),
- new cc.V3F_C4B_T2F(new cc.Vertex3F(0, 0, 0), new cc.Color4B(0, 0, 0, 255), new cc.Tex2F(0, 0)));
-};
-
-cc.V3F_C4B_T2F_QuadCopy = function (sourceQuad) {
- if (!sourceQuad)
- return cc.V3F_C4B_T2F_QuadZero();
- var tl = sourceQuad.tl, bl = sourceQuad.bl, tr = sourceQuad.tr, br = sourceQuad.br;
- return new cc.V3F_C4B_T2F_Quad(
- new cc.V3F_C4B_T2F(new cc.Vertex3F(sourceQuad.tl.vertices.x, sourceQuad.tl.vertices.y, sourceQuad.tl.vertices.z),
- new cc.Color4B(sourceQuad.tl.colors.r, sourceQuad.tl.colors.g, sourceQuad.tl.colors.b, sourceQuad.tl.colors.a),
- new cc.Tex2F(sourceQuad.tl.texCoords.u, sourceQuad.tl.texCoords.v)),
- new cc.V3F_C4B_T2F(new cc.Vertex3F(sourceQuad.bl.vertices.x, sourceQuad.bl.vertices.y, sourceQuad.bl.vertices.z),
- new cc.Color4B(sourceQuad.bl.colors.r, sourceQuad.bl.colors.g, sourceQuad.bl.colors.b, sourceQuad.bl.colors.a),
- new cc.Tex2F(sourceQuad.bl.texCoords.u, sourceQuad.bl.texCoords.v)),
- new cc.V3F_C4B_T2F(new cc.Vertex3F(sourceQuad.tr.vertices.x, sourceQuad.tr.vertices.y, sourceQuad.tr.vertices.z),
- new cc.Color4B(sourceQuad.tr.colors.r, sourceQuad.tr.colors.g, sourceQuad.tr.colors.b, sourceQuad.tr.colors.a),
- new cc.Tex2F(sourceQuad.tr.texCoords.u, sourceQuad.tr.texCoords.v)),
- new cc.V3F_C4B_T2F(new cc.Vertex3F(sourceQuad.br.vertices.x, sourceQuad.br.vertices.y, sourceQuad.br.vertices.z),
- new cc.Color4B(sourceQuad.br.colors.r, sourceQuad.br.colors.g, sourceQuad.br.colors.b, sourceQuad.br.colors.a),
- new cc.Tex2F(sourceQuad.br.texCoords.u, sourceQuad.br.texCoords.v)));
-};
-
-cc.V3F_C4B_T2F_QuadsCopy = function (sourceQuads) {
- if (!sourceQuads)
- return [];
-
- var retArr = [];
- for (var i = 0; i < sourceQuads.length; i++) {
- retArr.push(cc.V3F_C4B_T2F_QuadCopy(sourceQuads[i]));
- }
- return retArr;
-};
-
-/**
- * 4 ccVertex2FTex2FColor4F Quad
- * @Class
- * @Construct
- * @param {cc.V2F_C4F_T2F} bl1 bottom left
- * @param {cc.V2F_C4F_T2F} br1 bottom right
- * @param {cc.V2F_C4F_T2F} tl1 top left
- * @param {cc.V2F_C4F_T2F} tr1 top right
- * Constructor
- */
-cc.V2F_C4F_T2F_Quad = function (bl1, br1, tl1, tr1) {
- this.bl = bl1 || new cc.V2F_C4F_T2F();
- this.br = br1 || new cc.V2F_C4F_T2F();
- this.tl = tl1 || new cc.V2F_C4F_T2F();
- this.tr = tr1 || new cc.V2F_C4F_T2F();
-};
-
-/**
- * Blend Function used for textures
- * @Class
- * @Construct
- * @param {Number} src1 source blend function
- * @param {Number} dst1 destination blend function
- */
-cc.BlendFunc = function (src1, dst1) {
- this.src = src1;
- this.dst = dst1;
-};
-
-cc.BlendFuncDisable = function () {
- return new cc.BlendFunc(gl.ONE, gl.ZERO);
-};
-
-/**
- * texture coordinates for a quad
- * @param {cc.Tex2F} bl
- * @param {cc.Tex2F} br
- * @param {cc.Tex2F} tl
- * @param {cc.Tex2F} tr
- * @constructor
- */
-cc.T2F_Quad = function(bl, br, tl, tr){
- this.bl = bl;
- this.br = br;
- this.tl = tl;
- this.tr = tr;
-};
-
-/**
- * struct that holds the size in pixels, texture coordinates and delays for animated cc.ParticleSystem
- * @param {cc.T2F_Quad} texCoords
- * @param delay
- * @param size
- * @constructor
- */
-cc.AnimationFrameData = function(texCoords, delay, size){
- this.texCoords = texCoords;
- this.delay = delay;
- this.size = size;
-};
-
-/**
- * convert Color3B to a string of color for style.
- * e.g. Color3B(255,6,255) to : "#ff06ff"
- * @param clr
- * @return {String}
- */
-cc.convertColor3BtoHexString = function (clr) {
- var hR = clr.r.toString(16);
- var hG = clr.g.toString(16);
- var hB = clr.b.toString(16);
- var stClr = "#" + (clr.r < 16 ? ("0" + hR) : hR) + (clr.g < 16 ? ("0" + hG) : hG) + (clr.b < 16 ? ("0" + hB) : hB);
- return stClr;
-};
-
-if(cc.Browser.supportWebGL){
- //redefine some types with ArrayBuffer for WebGL
-
- //redefine cc.Color4B
- cc.Color4B = function (r, g, b, a, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Color4B.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = Uint8Array.BYTES_PER_ELEMENT;
- this._rU8 = new Uint8Array(locArrayBuffer, locOffset, 1);
- this._gU8 = new Uint8Array(locArrayBuffer, locOffset + locElementLen, 1);
- this._bU8 = new Uint8Array(locArrayBuffer, locOffset + locElementLen * 2, 1);
- this._aU8 = new Uint8Array(locArrayBuffer, locOffset + locElementLen * 3, 1);
-
- this._rU8[0] = r || 0;
- this._gU8[0] = g || 0;
- this._bU8[0] = b || 0;
- this._aU8[0] = a || 0;
- };
- cc.Color4B.BYTES_PER_ELEMENT = 4;
- Object.defineProperties(cc.Color4B.prototype, {
- r: {
- get: function () {
- return this._rU8[0];
- },
- set: function (xValue) {
- this._rU8[0] = xValue;
- },
- enumerable: true
- },
- g: {
- get: function () {
- return this._gU8[0];
- },
- set: function (yValue) {
- this._gU8[0]= yValue;
- },
- enumerable: true
- },
- b: {
- get: function () {
- return this._bU8[0];
- },
- set: function (xValue) {
- this._bU8[0] = xValue;
- },
- enumerable: true
- },
- a: {
- get: function () {
- return this._aU8[0];
- },
- set: function (yValue) {
- this._aU8[0] = yValue;
- },
- enumerable: true
- }
- });
-
- //redefine cc.Color4F
- cc.Color4F = function (r, g, b, a, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Color4F.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = Float32Array.BYTES_PER_ELEMENT;
- this._rF32 = new Float32Array(locArrayBuffer, locOffset, 1);
- this._rF32[0] = r || 0;
- this._gF32 = new Float32Array(locArrayBuffer, locOffset + locElementLen, 1);
- this._gF32[0] = g || 0;
- this._bF32 = new Float32Array(locArrayBuffer, locOffset + locElementLen * 2, 1);
- this._bF32[0] = b || 0;
- this._aF32 = new Float32Array(locArrayBuffer, locOffset + locElementLen * 3, 1);
- this._aF32[0] = a || 0;
- };
- cc.Color4F.BYTES_PER_ELEMENT = 16;
- Object.defineProperties(cc.Color4F.prototype, {
- r: {
- get: function () {
- return this._rF32[0];
- },
- set: function (rValue) {
- this._rF32[0] = rValue;
- },
- enumerable: true
- },
- g: {
- get: function () {
- return this._gF32[0];
- },
- set: function (rValue) {
- this._gF32[0] = rValue;
- },
- enumerable: true
- },
- b: {
- get: function () {
- return this._bF32[0];
- },
- set: function (rValue) {
- this._bF32[0] = rValue;
- },
- enumerable: true
- },
- a: {
- get: function () {
- return this._aF32[0];
- },
- set: function (rValue) {
- this._aF32[0] = rValue;
- },
- enumerable: true
- }
- });
-
- //redefine cc.Vertex2F
- cc.Vertex2F = function (x, y, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Vertex2F.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- this._xF32 = new Float32Array(this._arrayBuffer, this._offset, 1);
- this._yF32 = new Float32Array(this._arrayBuffer, this._offset + 4, 1);
- this._xF32[0] = x || 0;
- this._yF32[0] = y || 0;
- };
- cc.Vertex2F.BYTES_PER_ELEMENT = 8;
- Object.defineProperties(cc.Vertex2F.prototype, {
- x: {
- get: function () {
- return this._xF32[0];
- },
- set: function (xValue) {
- this._xF32[0] = xValue;
- },
- enumerable: true
- },
- y: {
- get: function () {
- return this._yF32[0];
- },
- set: function (yValue) {
- this._yF32[0] = yValue;
- },
- enumerable: true
- }
- });
-
- // redefine cc.Vertex3F
- cc.Vertex3F = function (x, y, z, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Vertex3F.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locOffset = this._offset;
- this._xF32 = new Float32Array(locArrayBuffer, locOffset, 1);
- this._xF32[0] = x || 0;
- this._yF32 = new Float32Array(locArrayBuffer, locOffset + Float32Array.BYTES_PER_ELEMENT, 1);
- this._yF32[0] = y || 0;
- this._zF32 = new Float32Array(locArrayBuffer, locOffset + Float32Array.BYTES_PER_ELEMENT * 2, 1);
- this._zF32[0] = z || 0;
- };
- cc.Vertex3F.BYTES_PER_ELEMENT = 12;
- Object.defineProperties(cc.Vertex3F.prototype, {
- x: {
- get: function () {
- return this._xF32[0];
- },
- set: function (xValue) {
- this._xF32[0] = xValue;
- },
- enumerable: true
- },
- y: {
- get: function () {
- return this._yF32[0];
- },
- set: function (yValue) {
- this._yF32[0] = yValue;
- },
- enumerable: true
- },
- z: {
- get: function () {
- return this._zF32[0];
- },
- set: function (zValue) {
- this._zF32[0] = zValue;
- },
- enumerable: true
- }
- });
-
- // redefine cc.Tex2F
- cc.Tex2F = function (u, v, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Tex2F.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- this._uF32 = new Float32Array(this._arrayBuffer, this._offset, 1);
- this._vF32 = new Float32Array(this._arrayBuffer, this._offset + 4, 1);
- this._uF32[0] = u || 0;
- this._vF32[0] = v || 0;
- };
- cc.Tex2F.BYTES_PER_ELEMENT = 8;
- Object.defineProperties(cc.Tex2F.prototype, {
- u: {
- get: function () {
- return this._uF32[0];
- },
- set: function (xValue) {
- this._uF32[0] = xValue;
- },
- enumerable: true
- },
- v: {
- get: function () {
- return this._vF32[0];
- },
- set: function (yValue) {
- this._vF32[0] = yValue;
- },
- enumerable: true
- }
- });
-
- //redefine cc.Quad2
- cc.Quad2 = function (tl, tr, bl, br, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Quad2.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locElementLen = cc.Vertex2F.BYTES_PER_ELEMENT;
- this._tl = tl ? new cc.Vertex2F(tl.x, tl.y, locArrayBuffer, 0) : new cc.Vertex2F(0, 0, locArrayBuffer, 0);
- this._tr = tr ? new cc.Vertex2F(tr.x, tr.y, locArrayBuffer, locElementLen) : new cc.Vertex2F(0, 0, locArrayBuffer, locElementLen);
- this._bl = bl ? new cc.Vertex2F(bl.x, bl.y, locArrayBuffer, locElementLen * 2) : new cc.Vertex2F(0, 0, locArrayBuffer, locElementLen * 2);
- this._br = br ? new cc.Vertex2F(br.x, br.y, locArrayBuffer, locElementLen * 3) : new cc.Vertex2F(0, 0, locArrayBuffer, locElementLen * 3);
- };
- cc.Quad2.BYTES_PER_ELEMENT = 32;
- Object.defineProperties(cc.Quad2.prototype, {
- tl: {
- get: function () {
- return this._tl;
- },
- set: function (tlValue) {
- this._tl.x = tlValue.x;
- this._tl.y = tlValue.y;
- },
- enumerable: true
- },
- tr: {
- get: function () {
- return this._tr;
- },
- set: function (trValue) {
- this._tr.x = trValue.x;
- this._tr.y = trValue.y;
- },
- enumerable: true
- },
- bl: {
- get: function () {
- return this._bl;
- },
- set: function (blValue) {
- this._bl.x = blValue.x;
- this._bl.y = blValue.y;
- },
- enumerable: true
- },
- br: {
- get: function () {
- return this._br;
- },
- set: function (brValue) {
- this._br.x = brValue.x;
- this._br.y = brValue.y;
- },
- enumerable: true
- }
- });
-
- //redefine cc.V3F_C4B_T2F
- cc.V3F_C4B_T2F = function (vertices, colors, texCoords, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex3F.BYTES_PER_ELEMENT;
- this._vertices = vertices ? new cc.Vertex3F(vertices.x, vertices.y, vertices.z, locArrayBuffer, locOffset) :
- new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset);
- this._colors = colors ? new cc.Color4B(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset + locElementLen) :
- new cc.Color4B(0, 0, 0, 0, locArrayBuffer, locOffset + locElementLen);
- this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT) :
- new cc.Tex2F(0, 0, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT);
- };
- cc.V3F_C4B_T2F.BYTES_PER_ELEMENT = 24;
- Object.defineProperties(cc.V3F_C4B_T2F.prototype, {
- vertices: {
- get: function () {
- return this._vertices;
- },
- set: function (verticesValue) {
- var locVertices = this._vertices;
- locVertices.x = verticesValue.x;
- locVertices.y = verticesValue.y;
- locVertices.z = verticesValue.z;
- },
- enumerable: true
- },
- colors: {
- get: function () {
- return this._colors;
- },
- set: function (colorValue) {
- var locColors = this._colors;
- locColors.r = colorValue.r;
- locColors.g = colorValue.g;
- locColors.b = colorValue.b;
- locColors.a = colorValue.a;
- },
- enumerable: true
- },
- texCoords: {
- get: function () {
- return this._texCoords;
- },
- set: function (texValue) {
- this._texCoords.u = texValue.u;
- this._texCoords.v = texValue.v;
- },
- enumerable: true
- }
- });
-
- //redefine cc.V3F_C4B_T2F_Quad
- cc.V3F_C4B_T2F_Quad = function (tl, bl, tr, br, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT;
- this._tl = tl ? new cc.V3F_C4B_T2F(tl.vertices, tl.colors, tl.texCoords, locArrayBuffer, locOffset) :
- new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
- this._bl = bl ? new cc.V3F_C4B_T2F(bl.vertices, bl.colors, bl.texCoords, locArrayBuffer, locOffset + locElementLen) :
- new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen);
- this._tr = tr ? new cc.V3F_C4B_T2F(tr.vertices, tr.colors, tr.texCoords, locArrayBuffer, locOffset + locElementLen * 2) :
- new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen * 2);
- this._br = br ? new cc.V3F_C4B_T2F(br.vertices, br.colors, br.texCoords, locArrayBuffer, locOffset + locElementLen * 3) :
- new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen * 3);
- };
- cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT = 96;
- Object.defineProperties(cc.V3F_C4B_T2F_Quad.prototype, {
- tl:{
- get: function () {
- return this._tl;
- },
- set: function (tlValue) {
- var locTl = this._tl;
- locTl.vertices = tlValue.vertices;
- locTl.colors = tlValue.colors;
- locTl.texCoords = tlValue.texCoords;
- },
- enumerable: true
- },
- bl:{
- get: function () {
- return this._bl;
- },
- set: function (blValue) {
- var locBl = this._bl;
- locBl.vertices = blValue.vertices;
- locBl.colors = blValue.colors;
- locBl.texCoords = blValue.texCoords;
- },
- enumerable: true
- },
- tr:{
- get: function () {
- return this._tr;
- },
- set: function (trValue) {
- var locTr = this._tr;
- locTr.vertices = trValue.vertices;
- locTr.colors = trValue.colors;
- locTr.texCoords = trValue.texCoords;
- },
- enumerable: true
- },
- br:{
- get: function () {
- return this._br;
- },
- set: function (brValue) {
- var locBr = this._br;
- locBr.vertices = brValue.vertices;
- locBr.colors = brValue.colors;
- locBr.texCoords = brValue.texCoords;
- },
- enumerable: true
- },
- arrayBuffer:{
- get: function () {
- return this._arrayBuffer;
- },
- enumerable: true
- }
- });
- cc.V3F_C4B_T2F_QuadZero = function(){
- return new cc.V3F_C4B_T2F_Quad();
- };
-
- cc.V3F_C4B_T2F_QuadCopy = function (sourceQuad) {
- if (!sourceQuad)
- return cc.V3F_C4B_T2F_QuadZero();
-
- //return new cc.V3F_C4B_T2F_Quad(sourceQuad,tl,sourceQuad,bl,sourceQuad.tr,sourceQuad.br,null,0);
- var srcTL = sourceQuad.tl, srcBL = sourceQuad.bl, srcTR = sourceQuad.tr, srcBR = sourceQuad.br;
- return {
- tl: {vertices: {x: srcTL.vertices.x, y: srcTL.vertices.y, z: srcTL.vertices.z},
- colors: {r: srcTL.colors.r, g: srcTL.colors.g, b: srcTL.colors.b, a: srcTL.colors.a},
- texCoords: {u: srcTL.texCoords.u, v: srcTL.texCoords.v}},
- bl: {vertices: {x: srcBL.vertices.x, y: srcBL.vertices.y, z: srcBL.vertices.z},
- colors: {r: srcBL.colors.r, g: srcBL.colors.g, b: srcBL.colors.b, a: srcBL.colors.a},
- texCoords: {u: srcBL.texCoords.u, v: srcBL.texCoords.v}},
- tr: {vertices: {x: srcTR.vertices.x, y: srcTR.vertices.y, z: srcTR.vertices.z},
- colors: {r: srcTR.colors.r, g: srcTR.colors.g, b: srcTR.colors.b, a: srcTR.colors.a},
- texCoords: {u: srcTR.texCoords.u, v: srcTR.texCoords.v}},
- br: {vertices: {x: srcBR.vertices.x, y: srcBR.vertices.y, z: srcBR.vertices.z},
- colors: {r: srcBR.colors.r, g: srcBR.colors.g, b: srcBR.colors.b, a: srcBR.colors.a},
- texCoords: {u: srcBR.texCoords.u, v: srcBR.texCoords.v}}
- };
- };
-
- //redefine cc.V2F_C4B_T2F
- cc.V2F_C4B_T2F = function (vertices, colors, texCoords, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex2F.BYTES_PER_ELEMENT;
- this._vertices = vertices ? new cc.Vertex2F(vertices.x, vertices.y, locArrayBuffer, locOffset) :
- new cc.Vertex2F(0, 0, locArrayBuffer, locOffset);
- this._colors = colors ? new cc.Color4B(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset + locElementLen) :
- new cc.Color4B(0, 0, 0, 0, locArrayBuffer, locOffset + locElementLen);
- this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT) :
- new cc.Tex2F(0, 0, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT);
- };
- cc.V2F_C4B_T2F.BYTES_PER_ELEMENT = 20;
- Object.defineProperties(cc.V2F_C4B_T2F.prototype, {
- vertices: {
- get: function () {
- return this._vertices;
- },
- set: function (verticesValue) {
- this._vertices.x = verticesValue.x;
- this._vertices.y = verticesValue.y;
- },
- enumerable: true
- },
- colors: {
- get: function () {
- return this._colors;
- },
- set: function (colorValue) {
- var locColors = this._colors;
- locColors.r = colorValue.r;
- locColors.g = colorValue.g;
- locColors.b = colorValue.b;
- locColors.a = colorValue.a;
- },
- enumerable: true
- },
- texCoords: {
- get: function () {
- return this._texCoords;
- },
- set: function (texValue) {
- this._texCoords.u = texValue.u;
- this._texCoords.v = texValue.v;
- },
- enumerable: true
- }
- });
-
- //redefine cc.V2F_C4B_T2F_Triangle
- cc.V2F_C4B_T2F_Triangle = function (a, b, c, arrayBuffer, offset) {
- this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT);
- this._offset = offset || 0;
-
- var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
- this._a = a ? new cc.V2F_C4B_T2F(a.vertices, a.colors, a.texCoords, locArrayBuffer, locOffset) :
- new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset);
- this._b = b ? new cc.V2F_C4B_T2F(b.vertices, b.colors, b.texCoords, locArrayBuffer, locOffset + locElementLen) :
- new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen);
- this._c = c ? new cc.V2F_C4B_T2F(c.vertices, c.colors, c.texCoords, locArrayBuffer, locOffset + locElementLen * 2) :
- new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen * 2);
- };
- cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT = 60;
- Object.defineProperties(cc.V2F_C4B_T2F_Triangle.prototype, {
- a:{
- get: function () {
- return this._a;
- },
- set: function (aValue) {
- var locA = this._a;
- locA.vertices = aValue.vertices;
- locA.colors = aValue.colors;
- locA.texCoords = aValue.texCoords;
- },
- enumerable: true
- },
- b:{
- get: function () {
- return this._b;
- },
- set: function (bValue) {
- var locB = this._b;
- locB.vertices = bValue.vertices;
- locB.colors = bValue.colors;
- locB.texCoords = bValue.texCoords;
- },
- enumerable: true
- },
- c:{
- get: function () {
- return this._c;
- },
- set: function (cValue) {
- var locC = this._c;
- locC.vertices = cValue.vertices;
- locC.colors = cValue.colors;
- locC.texCoords = cValue.texCoords;
- },
- enumerable: true
- }
- });
-}
-
-/**
- * convert a string of color for style to Color3B.
- * e.g. "#ff06ff" to : Color3B(255,6,255)
- * @param {String} clrSt
- * @return {cc.Color3B}
- */
-cc.convertHexNumToColor3B = function (clrSt) {
- var nAr = clrSt.substr(1).split("");
- var r = parseInt("0x" + nAr[0] + nAr[1]);
- var g = parseInt("0x" + nAr[2] + nAr[3]);
- var b = parseInt("0x" + nAr[4] + nAr[5]);
- return new cc.Color3B(r, g, b);
-};
-
-
-/**
- * text alignment : left
- * @constant
- * @type Number
- */
-cc.TEXT_ALIGNMENT_LEFT = 0;
-
-/**
- * text alignment : center
- * @constant
- * @type Number
- */
-cc.TEXT_ALIGNMENT_CENTER = 1;
-
-/**
- * text alignment : right
- * @constant
- * @type Number
- */
-cc.TEXT_ALIGNMENT_RIGHT = 2;
-
-/**
- * text alignment : top
- * @constant
- * @type Number
- */
-cc.VERTICAL_TEXT_ALIGNMENT_TOP = 0;
-
-/**
- * text alignment : center
- * @constant
- * @type Number
- */
-cc.VERTICAL_TEXT_ALIGNMENT_CENTER = 1;
-
-/**
- * text alignment : bottom
- * @constant
- * @type Number
- */
-cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM = 2;
-
-cc._Dictionary = cc.Class.extend({
- _keyMapTb: null,
- _valueMapTb: null,
- __currId: 0,
-
- ctor: function () {
- this._keyMapTb = {};
- this._valueMapTb = {};
- this.__currId = 2 << (0 | (Math.random() * 10));
- },
-
- __getKey: function () {
- this.__currId++;
- return "key_" + this.__currId;
- },
-
- setObject: function (value, key) {
- if (key == null)
- return;
-
- var keyId = this.__getKey();
- this._keyMapTb[keyId] = key;
- this._valueMapTb[keyId] = value;
- },
-
- objectForKey: function (key) {
- if (key == null)
- return null;
-
- var locKeyMapTb = this._keyMapTb;
- for (var keyId in locKeyMapTb) {
- if (locKeyMapTb[keyId] === key)
- return this._valueMapTb[keyId];
- }
- return null;
- },
-
- valueForKey: function (key) {
- return this.objectForKey(key);
- },
-
- removeObjectForKey: function (key) {
- if (key == null)
- return;
-
- var locKeyMapTb = this._keyMapTb;
- for (var keyId in locKeyMapTb) {
- if (locKeyMapTb[keyId] === key) {
- delete this._valueMapTb[keyId];
- delete locKeyMapTb[keyId];
- return;
- }
- }
- },
-
- removeObjectsForKeys: function (keys) {
- if (keys == null)
- return;
-
- for (var i = 0; i < keys.length; i++)
- this.removeObjectForKey(keys[i]);
- },
-
- allKeys: function () {
- var keyArr = [], locKeyMapTb = this._keyMapTb;
- for (var key in locKeyMapTb)
- keyArr.push(locKeyMapTb[key]);
- return keyArr;
- },
-
- removeAllObjects: function () {
- this._keyMapTb = {};
- this._valueMapTb = {};
- },
-
- count: function() {
- return this.allKeys().length;
- }
-});
-
-cc.FontDefinition = function(){
- this.fontName = "Arial";
- this.fontSize = 12;
- this.fontAlignmentH = cc.TEXT_ALIGNMENT_CENTER;
- this.fontAlignmentV = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
- this.fontFillColor = cc.WHITE;
- this.fontDimensions = cc.size(0,0);
-
- this.strokeEnabled = false;
- this.strokeColor = cc.WHITE;
- this.strokeSize = 1;
-
- this.shadowEnabled = false;
- this.shadowOffset = cc.size(0,0);
- this.shadowBlur = 0;
- this.shadowOpacity = 1.0;
-};
diff --git a/cocos2d/platform/Sys.js b/cocos2d/platform/Sys.js
deleted file mode 100644
index e3bc7431de..0000000000
--- a/cocos2d/platform/Sys.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-
- http://www.cocos2d-html5.org
- http://www.cocos2d-iphone.org
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-var sys = sys || {};
-
-/** LocalStorage is a local storage component.
-*/
-try{
- sys.localStorage = window.localStorage;
-
-}catch(e){
-
- if( e.name === "SECURITY_ERR" ) {
- cc.log("Warning: localStorage isn't enabled. Please confirm browser cookie or privacy option");
- }
- sys.localStorage = function(){};
-}
-
-/** Capabilities
-*/
-Object.defineProperties(sys,
-{
- capabilities : {
- get : function(){
- var capabilities = {"canvas":true};
-
- // if (window.DeviceOrientationEvent!==undefined || window.OrientationEvent!==undefined)
- // capabilities["accelerometer"] = true;
- if(cc.Browser.supportWebGL)
- capabilities["opengl"] = true;
-
- if( 'ontouchstart' in document.documentElement || window.navigator.msPointerEnabled)
- capabilities["touches"] = true;
-
- else if( 'onmouseup' in document.documentElement )
- capabilities["mouse"] = true;
-
- if( 'onkeyup' in document.documentElement )
- capabilities["keyboard"] = true;
-
- if(window.DeviceMotionEvent || window.DeviceOrientationEvent)
- capabilities["accelerometer"] = true;
-
- return capabilities;
- },
- enumerable : true,
- configurable : true
- },
- os : {
- get : function() {
- var iOS = ( navigator.userAgent.match(/(iPad|iPhone|iPod)/i) ? true : false );
- var isAndroid = navigator.userAgent.match(/android/i) || navigator.platform.match(/android/i) ? true : false;
- var OSName=navigator.appVersion;
- if (navigator.appVersion.indexOf("Win")!=-1)
- OSName="Windows";
- else if (navigator.appVersion.indexOf("Mac")!=-1)
- OSName="OS X";
- else if (navigator.appVersion.indexOf("X11")!=-1)
- OSName="UNIX";
- else if (navigator.appVersion.indexOf("Linux")!=-1)
- OSName="Linux";
- else if( iOS )
- OSName = "iOS";
- else if( isAndroid )
- OSName = "Android";
- return OSName;
- },
- enumerable : true,
- configurable : true
- },
- platform : {
- get : function(){
- return "browser";
- },
- enumerable : true,
- configurable : true
- },
- version : {
- get : function(){
- return cc.ENGINE_VERSION;
- },
- enumerable : true,
- configurable : true
- }
-});
-
-// Forces the garbage collector
-sys.garbageCollect = function() {
- // N/A in cocos2d-html5
-};
-
-// Dumps rooted objects
-sys.dumpRoot = function() {
- // N/A in cocos2d-html5
-};
-
-// restarts the JS VM
-sys.restartVM = function() {
- // N/A in cocos2d-html5
-};
diff --git a/cocos2d/platform/jsloader.js b/cocos2d/platform/jsloader.js
deleted file mode 100644
index ddc51a07c7..0000000000
--- a/cocos2d/platform/jsloader.js
+++ /dev/null
@@ -1,344 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
-
- 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.
- ****************************************************************************/
-(function () {
- var engine = [
- 'platform/CCClass.js',
- 'cocoa/CCGeometry.js',
- 'platform/Sys.js',
- 'platform/CCConfig.js',
- 'platform/miniFramework.js',
- 'platform/CCCommon.js',
- 'platform/ZipUtils.js',
- 'platform/base64.js',
- 'platform/gzip.js',
- 'platform/CCMacro.js',
- 'platform/CCFileUtils.js',
- 'platform/CCTypes.js',
- 'platform/CCAccelerometer.js',
- 'platform/zlib.min.js',
- 'platform/CCEGLView.js',
- 'platform/CCImage.js',
- 'kazmath/utility.js',
- 'kazmath/vec2.js',
- 'kazmath/vec3.js',
- 'kazmath/vec4.js',
- 'kazmath/ray2.js',
- 'kazmath/mat3.js',
- 'kazmath/mat4.js',
- 'kazmath/plane.js',
- 'kazmath/quaternion.js',
- 'kazmath/aabb.js',
- 'kazmath/GL/mat4stack.js',
- 'kazmath/GL/matrix.js',
- 'cocoa/CCSet.js',
- 'cocoa/CCNS.js',
- 'cocoa/CCAffineTransform.js',
- 'support/CCPointExtension.js',
- 'support/CCUserDefault.js',
- 'support/CCVertex.js',
- 'support/TransformUtils.js',
- 'support/CCTGAlib.js',
- 'support/CCPNGReader.js',
- 'support/CCTIFFReader.js',
- 'support/component/CCComponent.js',
- 'support/component/CCComponentContainer.js',
- 'shaders/CCShaders.js',
- 'shaders/CCShaderCache.js',
- 'shaders/CCGLProgram.js',
- 'shaders/CCGLStateCache.js',
- 'base_nodes/CCNode.js',
- 'base_nodes/CCAtlasNode.js',
- 'textures/CCTexture2D.js',
- 'textures/CCTextureCache.js',
- 'textures/CCTextureAtlas.js',
- 'misc_nodes/CCRenderTexture.js',
- 'misc_nodes/CCProgressTimer.js',
- 'misc_nodes/CCMotionStreak.js',
- 'misc_nodes/CCClippingNode.js',
- 'effects/CCGrid.js',
- 'effects/CCGrabber.js',
- 'draw_nodes/CCDrawNode.js',
- 'actions/CCAction.js',
- 'actions/CCActionInterval.js',
- 'actions/CCActionInstant.js',
- 'actions/CCActionManager.js',
- 'actions/CCActionProgressTimer.js',
- 'actions/CCActionCamera.js',
- 'actions/CCActionEase.js',
- 'actions/CCActionGrid.js',
- 'actions/CCActionGrid3D.js',
- 'actions/CCActionTiledGrid.js',
- 'actions/CCActionCatmullRom.js',
- 'actions/CCActionPageTurn3D.js',
- 'actions/CCActionTween.js',
- 'layers_scenes_transitions_nodes/CCScene.js',
- 'layers_scenes_transitions_nodes/CCLayer.js',
- 'layers_scenes_transitions_nodes/CCTransition.js',
- 'layers_scenes_transitions_nodes/CCTransitionProgress.js',
- 'layers_scenes_transitions_nodes/CCTransitionPageTurn.js',
- 'sprite_nodes/CCSprite.js',
- 'sprite_nodes/CCAnimation.js',
- 'sprite_nodes/CCAnimationCache.js',
- 'sprite_nodes/CCSpriteFrame.js',
- 'sprite_nodes/CCSpriteFrameCache.js',
- 'sprite_nodes/CCSpriteBatchNode.js',
- 'label_nodes/CCLabelAtlas.js',
- 'label_nodes/CCLabelTTF.js',
- 'label_nodes/CCLabelBMFont.js',
- 'particle_nodes/CCParticleSystem.js',
- 'particle_nodes/CCParticleExamples.js',
- 'particle_nodes/CCParticleBatchNode.js',
- 'touch_dispatcher/CCTouchDelegateProtocol.js',
- 'touch_dispatcher/CCTouchHandler.js',
- 'touch_dispatcher/CCTouchDispatcher.js',
- 'touch_dispatcher/CCMouseDispatcher.js',
- 'keyboard_dispatcher/CCKeyboardDelegate.js',
- 'keyboard_dispatcher/CCKeyboardDispatcher.js',
- 'text_input_node/CCIMEDispatcher.js',
- 'text_input_node/CCTextFieldTTF.js',
- 'CCConfiguration.js',
- 'CCDirector.js',
- 'CCCamera.js',
- 'CCScheduler.js',
- 'CCLoader.js',
- 'CCDrawingPrimitives.js',
- 'platform/CCApplication.js',
- 'platform/CCSAXParser.js',
- 'platform/AppControl.js',
- 'menu_nodes/CCMenuItem.js',
- 'menu_nodes/CCMenu.js',
- 'tileMap_parallax_nodes/CCTMXTiledMap.js',
- 'tileMap_parallax_nodes/CCTMXXMLParser.js',
- 'tileMap_parallax_nodes/CCTMXObjectGroup.js',
- 'tileMap_parallax_nodes/CCTMXLayer.js',
- 'tileMap_parallax_nodes/CCParallaxNode.js',
- 'base_nodes/CCdomNode.js',
- '../CocosDenshion/SimpleAudioEngine.js'
- ];
-
- var d = document;
- var c = d["ccConfig"];
-
- if (c.loadExtension != null && c.loadExtension == true) {
- engine = engine.concat([
- '../extensions/GUI/CCControlExtension/CCControl.js',
- '../extensions/GUI/CCControlExtension/CCControlButton.js',
- '../extensions/GUI/CCControlExtension/CCControlUtils.js',
- '../extensions/GUI/CCControlExtension/CCInvocation.js',
- '../extensions/GUI/CCControlExtension/CCScale9Sprite.js',
- '../extensions/GUI/CCControlExtension/CCMenuPassive.js',
- '../extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js',
- '../extensions/GUI/CCControlExtension/CCControlHuePicker.js',
- '../extensions/GUI/CCControlExtension/CCControlColourPicker.js',
- '../extensions/GUI/CCControlExtension/CCControlSlider.js',
- '../extensions/GUI/CCControlExtension/CCControlSwitch.js',
- '../extensions/GUI/CCControlExtension/CCControlStepper.js',
- '../extensions/GUI/CCControlExtension/CCControlPotentiometer.js',
- '../extensions/GUI/CCScrollView/CCScrollView.js',
- '../extensions/GUI/CCScrollView/CCSorting.js',
- '../extensions/GUI/CCScrollView/CCTableView.js',
- '../extensions/CCBReader/CCNodeLoader.js',
- '../extensions/CCBReader/CCBReaderUtil.js',
- '../extensions/CCBReader/CCControlLoader.js',
- '../extensions/CCBReader/CCSpriteLoader.js',
- '../extensions/CCBReader/CCNodeLoaderLibrary.js',
- '../extensions/CCBReader/CCBReader.js',
- '../extensions/CCBReader/CCBValue.js',
- '../extensions/CCBReader/CCBKeyframe.js',
- '../extensions/CCBReader/CCBSequence.js',
- '../extensions/CCBReader/CCBRelativePositioning.js',
- '../extensions/CCBReader/CCBAnimationManager.js',
- '../extensions/CCEditBox.js',
- // CocoStudio Armature
- '../extensions/CocoStudio/Armature/utils/CCArmatureDefine.js',
- '../extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js',
- '../extensions/CocoStudio/Armature/utils/CCSpriteFrameCacheHelper.js',
- '../extensions/CocoStudio/Armature/utils/CCTransformHelp.js',
- '../extensions/CocoStudio/Armature/utils/CCTweenFunction.js',
- '../extensions/CocoStudio/Armature/utils/CCUtilMath.js',
- '../extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js',
- '../extensions/CocoStudio/Armature/datas/CCDatas.js',
- '../extensions/CocoStudio/Armature/display/CCBatchNode.js',
- '../extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js',
- '../extensions/CocoStudio/Armature/display/CCDisplayFactory.js',
- '../extensions/CocoStudio/Armature/display/CCDisplayManager.js',
- '../extensions/CocoStudio/Armature/display/CCSkin.js',
- '../extensions/CocoStudio/Armature/animation/CCProcessBase.js',
- '../extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js',
- '../extensions/CocoStudio/Armature/animation/CCTween.js',
- '../extensions/CocoStudio/Armature/physics/CCColliderDetector.js',
- '../extensions/CocoStudio/Armature/CCArmature.js',
- '../extensions/CocoStudio/Armature/CCBone.js',
- // CocoStudio Action
- '../extensions/CocoStudio/Action/CCActionFrame.js',
- '../extensions/CocoStudio/Action/CCActionManager.js',
- '../extensions/CocoStudio/Action/CCActionNode.js',
- '../extensions/CocoStudio/Action/CCActionObject.js',
- // CocoStudio Components
- '../extensions/CocoStudio/Components/CCComAttribute.js',
- '../extensions/CocoStudio/Components/CCComAudio.js',
- '../extensions/CocoStudio/Components/CCComController.js',
- '../extensions/CocoStudio/Components/CCComRender.js',
- // CocoStudio GUI
- '../extensions/CocoStudio/GUI/BaseClasses/UIWidget.js',
- '../extensions/CocoStudio/GUI/Layouts/Layout.js',
- '../extensions/CocoStudio/GUI/BaseClasses/UIRootWidget.js',
- '../extensions/CocoStudio/GUI/Layouts/LayoutParameter.js',
- '../extensions/CocoStudio/GUI/Layouts/UILayoutDefine.js',
- '../extensions/CocoStudio/GUI/System/CocosGUI.js',
- '../extensions/CocoStudio/GUI/System/UIHelper.js',
- '../extensions/CocoStudio/GUI/System/UIInputManager.js',
- '../extensions/CocoStudio/GUI/System/UILayer.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UIButton.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UICheckBox.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UIImageView.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UILabel.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UILabelAtlas.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UILabelBMFont.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UILoadingBar.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UISlider.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UISwitch.js',
- '../extensions/CocoStudio/GUI/UIWidgets/UITextField.js',
- '../extensions/CocoStudio/GUI/UIWidgets/Compatible/CompatibleClasses.js',
- '../extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIDragPanel.js',
- '../extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIListView.js',
- '../extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIPageView.js',
- '../extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollInterface.js',
- '../extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollView.js',
- '../extensions/CocoStudio/Reader/CCSGUIReader.js',
- '../extensions/CocoStudio/Reader/CCSSceneReader.js'
-
- ]);
- }
-
- if (c.loadPluginx != null && c.loadPluginx == true) {
- engine = engine.concat([
- //protocols
- '../extensions/PluginX/protocols/Config.js',
- '../extensions/PluginX/protocols/PluginUtils.js',
- '../extensions/PluginX/protocols/PluginProtocol.js',
- '../extensions/PluginX/protocols/ProtocolSocial.js',
- //'../extensions/PluginX/protocols/ProtocolAds.js',
- //'../extensions/PluginX/protocols/ProtocolAnalytics.js',
- //'../extensions/PluginX/protocols/ProtocolIAP.js',
- '../extensions/PluginX/protocols/PluginFactory.js',
- '../extensions/PluginX/protocols/PluginManager.js',
-
- //plugins
- '../extensions/PluginX/plugins/SocialWeibo.js',
- '../extensions/PluginX/plugins/SocialQQWeibo.js',
- '../extensions/PluginX/plugins/SocialQzone.js',
- '../extensions/PluginX/plugins/SocialTwitter.js',
- '../extensions/PluginX/plugins/SocialFacebook.js'
- //'../extensions/PluginX/plugins/AdsGoogle.js'
- ]);
- }
-
- if (!c.engineDir) {
- engine = [];
- }
- else {
- if(c.box2d || c.chipmunk){
- engine.push('physics_nodes/CCPhysicsSprite.js');
- engine.push('physics_nodes/CCPhysicsDebugNode.js');
- if (c.box2d === true)
- engine.push('../box2d/box2d.js');
- if (c.chipmunk === true)
- engine.push('../chipmunk/chipmunk.js');
- }
- engine.forEach(function (e, i) {
- engine[i] = c.engineDir + e;
- });
- if(typeof c.box2d === "string")
- {
- engine.push(c.box2d);
- }
- if(typeof c.chipmunk === "string")
- {
- engine.push(c.chipmunk);
- }
-
- }
-
- var loadJsImg = document.getElementById("cocos2d_loadJsImg");
- if(!loadJsImg){
- loadJsImg = document.createElement('img');
- loadJsImg.src = "data:image/gif;base64,R0lGODlhEAAQALMNAD8/P7+/vyoqKlVVVX9/fxUVFUBAQGBgYMDAwC8vL5CQkP///wAAAP///wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAANACwAAAAAEAAQAAAEO5DJSau9OOvNex0IMnDIsiCkiW6g6BmKYlBFkhSUEgQKlQCARG6nEBwOgl+QApMdCIRD7YZ5RjlGpCUCACH5BAUAAA0ALAAAAgAOAA4AAAQ6kLGB0JA4M7QW0hrngRllkYyhKAYqKUGguAws0ypLS8JxCLQDgXAIDg+FRKIA6v0SAECCBpXSkstMBAAh+QQFAAANACwAAAAACgAQAAAEOJDJORAac6K1kDSKYmydpASBUl0mqmRfaGTCcQgwcxDEke+9XO2WkxQSiUIuAQAkls0n7JgsWq8RACH5BAUAAA0ALAAAAAAOAA4AAAQ6kMlplDIzTxWC0oxwHALnDQgySAdBHNWFLAvCukc215JIZihVIZEogDIJACBxnCSXTcmwGK1ar1hrBAAh+QQFAAANACwAAAAAEAAKAAAEN5DJKc4RM+tDyNFTkSQF5xmKYmQJACTVpQSBwrpJNteZSGYoFWjIGCAQA2IGsVgglBOmEyoxIiMAIfkEBQAADQAsAgAAAA4ADgAABDmQSVZSKjPPBEDSGucJxyGA1XUQxAFma/tOpDlnhqIYN6MEAUXvF+zldrMBAjHoIRYLhBMqvSmZkggAIfkEBQAADQAsBgAAAAoAEAAABDeQyUmrnSWlYhMASfeFVbZdjHAcgnUQxOHCcqWylKEohqUEAYVkgEAMfkEJYrFA6HhKJsJCNFoiACH5BAUAAA0ALAIAAgAOAA4AAAQ3kMlJq704611SKloCAEk4lln3DQgyUMJxCBKyLAh1EMRR3wiDQmHY9SQslyIQUMRmlmVTIyRaIgA7";
-
- var canvasNode = document.getElementById(c.tag);
- canvasNode.style.backgroundColor = "black";
- canvasNode.parentNode.appendChild(loadJsImg);
-
- var canvasStyle = getComputedStyle?getComputedStyle(canvasNode):canvasNode.currentStyle;
- loadJsImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - loadJsImg.width)/2 + "px";
- loadJsImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - loadJsImg.height)/2 + "px";
- loadJsImg.style.position = "absolute";
- }
-
- var updateLoading = function(p){
- if(p>=1) {
- loadJsImg.parentNode.removeChild(loadJsImg);
- }
- };
-
- var loaded = 0;
- var que = engine.concat(c.appFiles);
- que.push('main.js');
-
- if (navigator.userAgent.indexOf("Trident/5") > -1) {
- //ie9
- var i = -1;
- var loadNext = function () {
- i++;
- if (i < que.length) {
- var f = d.createElement('script');
- f.src = que[i];
- f.addEventListener('load',function(){
- loadNext();
- updateLoading(loaded / que.length);
- this.removeEventListener('load', arguments.callee, false);
- },false);
- d.body.appendChild(f);
- }
- updateLoading(i / (que.length - 1));
- };
- loadNext();
- }
- else {
- que.forEach(function (f, i) {
- var s = d.createElement('script');
- s.async = false;
- s.src = f;
- s.addEventListener('load',function(){
- loaded++;
- updateLoading(loaded / que.length);
- this.removeEventListener('load', arguments.callee, false);
- },false);
- d.body.appendChild(s);
- });
- }
-})();
diff --git a/cocos2d/platform/miniFramework.js b/cocos2d/platform/miniFramework.js
deleted file mode 100644
index ada9ddcfd7..0000000000
--- a/cocos2d/platform/miniFramework.js
+++ /dev/null
@@ -1,375 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * create a webgl context
- * @param {HTMLCanvasElement} canvas
- * @param {Object} opt_attribs
- * @return {WebGLRenderingContext}
- */
-cc.create3DContext = function (canvas, opt_attribs) {
- var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
- var context = null;
- for (var ii = 0; ii < names.length; ++ii) {
- try {
- context = canvas.getContext(names[ii], opt_attribs);
- } catch (e) {
- }
- if (context) {
- break;
- }
- }
- return context;
-};
-
-/**
- * Browser detection, based on mootools
- * platform will print out win32, mac, etc
- * type is the browser type, chrome, firefox etc
- * @type {Object}
- */
-cc.Browser = {};
-(function () {
- var ua = navigator.userAgent;
- cc.Browser.ua = ua.toLowerCase();
- cc.Browser.platform = navigator.platform.toLowerCase();
- cc.Browser.isMobile = (cc.Browser.ua.indexOf('mobile') != -1 || cc.Browser.ua.indexOf('android') != -1);
- cc.Browser.type = (function () {
- var browserTypes = cc.Browser.ua.match(/micromessenger|qqbrowser|mqqbrowser|ucbrowser|360browser|baidubrowser|maxthon|ie|opera|firefox/) || cc.Browser.ua.match(/chrome|safari/);
- if (browserTypes && browserTypes.length > 0) {
- var el = browserTypes[0];
- if (el == 'micromessenger') {
- return 'wechat';
- }
- return el;
- }
- return "unknow";
- })();
- cc.Browser.mode = cc.Browser.type == 'ie' && document.documentMode;
-
- if (!document["ccConfig"])
- document["ccConfig"] = {};
-
- var c = document["ccConfig"];
- // check supportWebGL item
- cc._userRenderMode = parseInt(c["renderMode"]) || 0;
-
- if (cc._userRenderMode === 1 || (cc._userRenderMode === 0 && cc.Browser.isMobile)) {
- //canvas only
- cc.Browser.supportWebGL = false;
- } else {
- // WebGL first
- cc.Browser.supportWebGL = !(window.WebGLRenderingContext == null);
- var tempCanvas = document.createElement("Canvas");
- var tempContext = cc.create3DContext(tempCanvas, {'stencil': true, 'preserveDrawingBuffer': true });
- cc.Browser.supportWebGL = !(tempContext == null)
- }
- if (cc._userRenderMode === 2 && !cc.Browser.supportWebGL) {
- // WebGL render only, but browser doesn't support WebGL.
- cc.__renderDoesnotSupport = true;
- }
-
- // check if browser supports Web Audio
- cc.Browser.supportWebAudio = (function () {
- // check Web Audio's context
- try {
- var ctx = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext)();
- return ctx ? true : false;
- } catch (e) {
- return false;
- }
- })();
-
-
- cc.Browser.openURL = function (url) {
- if (this.isMobile) {
- var size = cc.Director.getInstance().getWinSize();
- var w = size.width + "px";
- var h = size.height + "px";
-
- var div = cc.$new("div");
- div.style.backgroundColor = "#ffffff";
- div.style.width = w;
- div.style.height = h;
- div.style.zindex = 1000;
- div.style.position = 'absolute';
- div.style.top = 0 + 'px';
- div.style.left = 0 + 'px';
- div.id = "cocos2d-browser";
-
- var iframe = cc.$new("iframe");
- iframe.src = url;
- iframe.style.width = w;
- iframe.style.height = h;
- iframe.setAttribute("frameborder", "no");
- iframe.setAttribute("scrolling", "no");
- div.appendChild(iframe);
-
- iframe.onload = function () {
- var close = document.createElement('img');
- close.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5OERBMEM3OUQzRTMxMUUyODg2Q0RFNjU1QkU1RjlFQSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo5OERBMEM3QUQzRTMxMUUyODg2Q0RFNjU1QkU1RjlFQSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjk4REEwQzc3RDNFMzExRTI4ODZDREU2NTVCRTVGOUVBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjk4REEwQzc4RDNFMzExRTI4ODZDREU2NTVCRTVGOUVBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+NwBuoAAAA/tJREFUeNrEWF0sW3EUb6+28zFhbGadsBaNhazV+kpDYhFWKRGWbHvwFV5IvPiIFw9evElEPEiWSUgsIWoIglhmUomPxj6aKC0zKVJjtPU5o9j5J7dLdbf33jKc5Jfc3v+v5/+755x7/j1lMoiNBRDh4AO88HvO2m+ACbAC+AJQAyz2JCbBFyMBWQA/xv+3DUAXLuivudhcY4BMwCuAB+NqDPmNAnAAOsCZvQgk4BnjeiwEwAbM2YoQA14yrteQEANgDcML7gXjZgw9OAuJkADu3JAIb7Q/hr+GtCwuLs6LDq+iooLvhBAREhFEl11ZWRne0tIiIeNIpVKv4uJi4dTUVApNt0EY3ohILSIiwqO7u1sql8vD8vLyJJ2dnXH2HDabzczPz3/Y1taWzOfz78XExDxSq9Vyd3d3jMK9F2pWr6lEtLa2RmVnZ4tt7w0NDWlTU1OVtkK7urqSQ0NDzzW5hYWFjcTExAGDwXDkyD+VSkZ7e3tsWlpamP19mUwWplQqk9B1UlKST3NzczxE4K49D4mCiDwn24PyPMjIyHjs6urKIVpLSEgInp6eZsM6Kzw8nEvEMZvNBxC1BbI9KCMhkUgUy8vLRpL1QIFA4EcSyZmcnJzpS4mYnZ3dj46O7p2fn193xIGi/CeiFovlFIp5pqGhYZ5qD1qFiQxCjk1OTsqEQmEAFReloL+/X0sVAadFWE2n02VA+O+TcVZXV01QkO8ODw9P6fjEnO2zvb2936g4XC7XG4rWm65P2iL8/f05kN8nBQUFQkqnGMYcGBjIys3N5dLxjY7ydDrE6urqsNLSUqmbmxuH1tOBkMzMTIHRaNxSqVTmS4soKyvjFRUViTw9PV2dTR901WAOh7M/MjKyeeHCbGpqEhcWFkY5Wl9aWtpUKBRaONziSbsii/Xm5OTk7EIdU6/X7zpaW1xc/Al5HxkfH9/e2dk5rqmpeUrE6+vr06ADzpEIlI5kMjFwPhh5PB5DJBKdK7KDg4Oj2tpaVUdHxw/0eWxszIjyj8Jvy4N60FdVVX2Grnt4dkaowYJESAG3yaLR09Oz5uvrexwbGxuAR2erpKTkI6RqxW5DM6RnLT09PQQV5vDwsDYlJWUU+I4EIDMhEQLAA6q0DA4OrqMCg/c/qL6+XtXY2Kgn4sGJuavRaFbFYrFPeXn5FIj6ReFa64KnIpJOpaMK39vbM9XV1X13lF9kc3Nz+xMTEwZo89s03A4ycRE1N/RjF/WPKgyfDRU39Gu7w1qYyNYAtwDB1yhgGPDBfgzU4bMi7xoEjAI6iWZRdGMGH80Cr2goRlP5W8B7qwBHfw1YO6kEH4yC8EnJ5QKbnuDFh17nr4BPRP9P/BFgAHo7ZNgI9EbHAAAAAElFTkSuQmCC";
- div.appendChild(close);
- close.style.zindex = 1000;
- close.style.position = 'absolute';
- close.style.bottom = 10 + 'px';
- close.style.right = 10 + 'px';
- close.onclick = function () {
- div.remove();
- }
- };
-
- var tag = document['ccConfig'].tag;
- var parent = document.getElementById(tag).parentNode;
- if (parent) {
- parent.appendChild(div);
- }
- }
- else {
- window.open(url);
- }
- }
-})();
-
-cc.RenderDoesnotSupport = function () {
- if (cc.__renderDoesnotSupport === "undefined")
- return false;
- return cc.__renderDoesnotSupport;
-};
-
-
-/**
- * the dollar sign, classic like jquery, this selector add extra methods to HTMLElement without touching its prototype
- * it is also chainable like jquery
- * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement
- * @class
- * @return {cc.$}
- */
-cc.$ = function (x) {
- /** @lends cc.$# */
- var parent = (this == cc) ? document : this;
-
- /**
- * @type {HTMLElement}
- */
- var el = (x instanceof HTMLElement) ? x : parent.querySelector(x);
-
- if (el) {
- /**
- * find and return the child wth css selector (same as jquery.find)
- * @param {HTMLElement|String} x pass in a css selector in string or the whole HTMLElement
- * @return {cc.$}
- */
- el.find = el.find || cc.$;
- /**
- * check if a DOMNode has a specific class
- * @param {String} cls
- * @return {Boolean}
- */
- el.hasClass = el.hasClass || function (cls) {
- return this.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
- };
- /**
- * add a class to a DOMNode, returns self to allow chaining
- * @param {String} cls
- * @return {cc.$}
- */
- el.addClass = el.addClass || function (cls) {
- if (!this.hasClass(cls)) {
- if (this.className) {
- this.className += " ";
- }
- this.className += cls;
- }
- return this;
- };
- /**
- * remove a specific class from a DOMNode, returns self to allow chaining
- * @param {String} cls
- * @return {cc.$}
- */
- el.removeClass = el.removeClass || function (cls) {
- if (this.hasClass(cls)) {
- this.className = this.className.replace(cls, '');
- }
- return this;
- };
- /**
- * detach it self from parent
- * @function
- */
- el.remove = el.remove || function () {
- if (this.parentNode)
- this.parentNode.removeChild(this);
- return this;
- };
-
- /**
- * add to another element as a child
- * @param {HTMLElement|cc.$} x
- * @return {cc.$}
- */
- el.appendTo = el.appendTo || function (x) {
- x.appendChild(this);
- return this;
- };
-
- /**
- * add to another element as a child and place on the top of the children list
- * @param {HTMLElement|cc.$} x
- * @return {cc.$}
- */
- el.prependTo = el.prependTo || function (x) {
- ( x.childNodes[0]) ? x.insertBefore(this, x.childNodes[0]) : x.appendChild(this);
- return this;
- };
-
- /**
- * helper function for updating the css transform
- * @return {cc.$}
- */
- el.transforms = el.transforms || function () {
- this.style[cc.$.trans] = cc.$.translate(this.position) + cc.$.rotate(this.rotation) + cc.$.scale(this.scale) + cc.$.skew(this.skew);
- return this;
- };
-
- el.position = el.position || {x: 0, y: 0};
- el.rotation = el.rotation || 0;
- el.scale = el.scale || {x: 1, y: 1};
- el.skew = el.skew || {x: 0, y: 0};
-
- /**
- * move the element
- * @param {Number} x in pixel
- * @param {Number} y in pixel
- * @return {cc.$}
- */
- el.translates = function (x, y) {
- this.position.x = x;
- this.position.y = y;
- this.transforms();
- return this
- };
-
- /**
- * rotate the element
- * @param {Number} x in degrees
- * @return {cc.$}
- */
- el.rotate = function (x) {
- this.rotation = x;
- this.transforms();
- return this
- };
-
- /**
- * resize the element
- * @param {Number} x
- * @param {Number} y
- * @return {cc.$}
- */
- el.resize = function (x, y) {
- this.scale.x = x;
- this.scale.y = y;
- this.transforms();
- return this
- };
-
- /**
- * skews the element
- * @param {Number} x in degrees
- * @param {Number} y
- * @return {cc.$}
- */
- el.setSkew = function (x, y) {
- this.skew.x = x;
- this.skew.y = y;
- this.transforms();
- return this
- };
- }
- return el;
-};
-//getting the prefix and css3 3d support
-switch (cc.Browser.type) {
- case "firefox":
- cc.$.pfx = "Moz";
- cc.$.hd = true;
- break;
- case "chrome":
- case "safari":
- cc.$.pfx = "webkit";
- cc.$.hd = true;
- break;
- case "opera":
- cc.$.pfx = "O";
- cc.$.hd = false;
- break;
- case "ie":
- cc.$.pfx = "ms";
- cc.$.hd = false;
- break;
- default:
- cc.$.pfx = "webkit";
- cc.$.hd = true;
-}
-//cache for prefixed transform
-cc.$.trans = cc.$.pfx + "Transform";
-//helper function for constructing transform strings
-cc.$.translate = (cc.$.hd) ? function (a) {
- return "translate3d(" + a.x + "px, " + a.y + "px, 0) "
-} : function (a) {
- return "translate(" + a.x + "px, " + a.y + "px) "
-};
-cc.$.rotate = (cc.$.hd) ? function (a) {
- return "rotateZ(" + a + "deg) ";
-} : function (a) {
- return "rotate(" + a + "deg) ";
-};
-cc.$.scale = function (a) {
- return "scale(" + a.x + ", " + a.y + ") "
-};
-cc.$.skew = function (a) {
- return "skewX(" + -a.x + "deg) skewY(" + a.y + "deg)";
-};
-
-
-/**
- * Creates a new element, and adds cc.$ methods
- * @param {String} x name of the element tag to create
- * @return {cc.$}
- */
-cc.$new = function (x) {
- return cc.$(document.createElement(x))
-};
-cc.$.findpos = function (obj) {
- var curleft = 0;
- var curtop = 0;
- do {
- curleft += obj.offsetLeft;
- curtop += obj.offsetTop;
- } while (obj = obj.offsetParent);
- return {x: curleft, y: curtop};
-};
diff --git a/cocos2d/actions/CCActionProgressTimer.js b/cocos2d/progress-timer/CCActionProgressTimer.js
similarity index 56%
rename from cocos2d/actions/CCActionProgressTimer.js
rename to cocos2d/progress-timer/CCActionProgressTimer.js
index 3c298f92da..026af89750 100644
--- a/cocos2d/actions/CCActionProgressTimer.js
+++ b/cocos2d/progress-timer/CCActionProgressTimer.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (C) 2010 Lam Pham
http://www.cocos2d-x.org
@@ -27,15 +29,27 @@
* Progress to percentage
* @class
* @extends cc.ActionInterval
+ * @param {Number} duration duration in seconds
+ * @param {Number} percent
+ * @example
+ * var to = new cc.ProgressTo(2, 100);
*/
cc.ProgressTo = cc.ActionInterval.extend(/** @lends cc.ProgressTo# */{
_to:0,
_from:0,
- ctor: function(){
+ /**
+ * Creates a ProgressTo action with a duration and a percent
+ * Constructor of cc.ProgressTo
+ * @param {Number} duration duration in seconds
+ * @param {Number} percent
+ */
+ ctor: function(duration, percent){
cc.ActionInterval.prototype.ctor.call(this);
this._to = 0;
this._from = 0;
+
+ percent !== undefined && this.initWithDuration(duration, percent);
},
/** Initializes with a duration and a percent
@@ -50,68 +64,94 @@ cc.ProgressTo = cc.ActionInterval.extend(/** @lends cc.ProgressTo# */{
}
return false;
},
-
+ /**
+ * return a new cc.ProgressTo, all the configuration is the same as the original
+ * @returns {cc.ProgressTo}
+ */
clone:function(){
var action = new cc.ProgressTo();
action.initWithDuration(this._duration, this._to);
return action;
},
-
+ /**
+ * reverse hasn't been supported
+ * @returns {null}
+ */
reverse: function(){
- cc.Assert(false, "reverse() not supported in ProgressTo");
+ cc.log("cc.ProgressTo.reverse(): reverse hasn't been supported.");
return null;
},
/**
+ * start with a target
* @param {cc.Node} target
*/
startWithTarget:function (target) {
cc.ActionInterval.prototype.startWithTarget.call(this, target);
- this._from = target.getPercentage();
-
- // XXX: Is this correct ?
- // Adding it to support CCRepeat
- if (this._from == 100)
- this._from = 0;
+ this._from = target.percentage;
},
/**
+ * custom update
* @param {Number} time time in seconds
*/
update:function (time) {
- if (this._target instanceof cc.ProgressTimer)
- this._target.setPercentage(this._from + (this._to - this._from) * time);
+ if (this.target instanceof cc.ProgressTimer)
+ this.target.percentage = this._from + (this._to - this._from) * time;
}
});
-/** Creates and initializes with a duration and a percent
+/**
+ * Creates and initializes with a duration and a percent
+ * @function
* @param {Number} duration duration in seconds
* @param {Number} percent
* @return {cc.ProgressTo}
* @example
* // example
- * var to = cc.ProgressTo.create(2, 100);
- *
+ * var to = cc.progressTo(2, 100);
*/
-cc.ProgressTo.create = function (duration, percent) {
- var progressTo = new cc.ProgressTo();
- progressTo.initWithDuration(duration, percent);
- return progressTo;
+cc.progressTo = function (duration, percent) {
+ return new cc.ProgressTo(duration, percent);
};
+/**
+ * Please use cc.progressTo instead
+ * Creates and initializes with a duration and a percent
+ * @static
+ * @deprecated since v3.0,please use cc.progressTo instead.
+ * @param {Number} duration duration in seconds
+ * @param {Number} percent
+ * @return {cc.ProgressTo}
+ */
+cc.ProgressTo.create = cc.progressTo;
/**
* Progress from a percentage to another percentage
* @class
* @extends cc.ActionInterval
+ * @param {Number} duration duration in seconds
+ * @param {Number} fromPercentage
+ * @param {Number} toPercentage
+ * @example
+ * var fromTo = new cc.ProgressFromTo(2, 100.0, 0.0);
*/
cc.ProgressFromTo = cc.ActionInterval.extend(/** @lends cc.ProgressFromTo# */{
_to:0,
_from:0,
- ctor:function(){
+ /**
+ * Creates and initializes the action with a duration, a "from" percentage and a "to" percentage
+ * Constructor of cc.ProgressFromTo
+ * @param {Number} duration duration in seconds
+ * @param {Number} fromPercentage
+ * @param {Number} toPercentage
+ */
+ ctor:function(duration, fromPercentage, toPercentage){
cc.ActionInterval.prototype.ctor.call(this);
this._to = 0;
this._from = 0;
+
+ toPercentage !== undefined && this.initWithDuration(duration, fromPercentage, toPercentage);
},
/** Initializes the action with a duration, a "from" percentage and a "to" percentage
@@ -128,7 +168,10 @@ cc.ProgressFromTo = cc.ActionInterval.extend(/** @lends cc.ProgressFromTo# */{
}
return false;
},
-
+ /**
+ * return a new cc.ProgressTo, all the configuration is the same as the original
+ * @returns {cc.ProgressFromTo}
+ */
clone:function(){
var action = new cc.ProgressFromTo();
action.initWithDuration(this._duration, this._from, this._to);
@@ -139,10 +182,11 @@ cc.ProgressFromTo = cc.ActionInterval.extend(/** @lends cc.ProgressFromTo# */{
* @return {cc.ActionInterval}
*/
reverse:function () {
- return cc.ProgressFromTo.create(this._duration, this._to, this._from);
+ return cc.progressFromTo(this._duration, this._to, this._from);
},
/**
+ * start with a target
* @param {cc.Node} target
*/
startWithTarget:function (target) {
@@ -153,22 +197,31 @@ cc.ProgressFromTo = cc.ActionInterval.extend(/** @lends cc.ProgressFromTo# */{
* @param {Number} time time in seconds
*/
update:function (time) {
- if (this._target instanceof cc.ProgressTimer)
- this._target.setPercentage(this._from + (this._to - this._from) * time);
+ if (this.target instanceof cc.ProgressTimer)
+ this.target.percentage = this._from + (this._to - this._from) * time;
}
});
/** Creates and initializes the action with a duration, a "from" percentage and a "to" percentage
+ * @function
* @param {Number} duration duration in seconds
* @param {Number} fromPercentage
* @param {Number} toPercentage
* @return {cc.ProgressFromTo}
* @example
* // example
- * var fromTO = cc.ProgressFromTo.create(2, 100.0, 0.0);
+ * var fromTo = cc.progressFromTo(2, 100.0, 0.0);
*/
-cc.ProgressFromTo.create = function (duration, fromPercentage, toPercentage) {
- var progressFromTo = new cc.ProgressFromTo();
- progressFromTo.initWithDuration(duration, fromPercentage, toPercentage);
- return progressFromTo;
+cc.progressFromTo = function (duration, fromPercentage, toPercentage) {
+ return new cc.ProgressFromTo(duration, fromPercentage, toPercentage);
};
+/**
+ * Creates and initializes the action with a duration, a "from" percentage and a "to" percentage
+ * @static
+ * @deprecated since v3.0,please use cc.ProgressFromTo(duration, fromPercentage, toPercentage) instead.
+ * @param {Number} duration duration in seconds
+ * @param {Number} fromPercentage
+ * @param {Number} toPercentage
+ * @return {cc.ProgressFromTo}
+ */
+cc.ProgressFromTo.create = cc.progressFromTo;
diff --git a/cocos2d/progress-timer/CCProgressTimer.js b/cocos2d/progress-timer/CCProgressTimer.js
new file mode 100644
index 0000000000..abeeb16ce0
--- /dev/null
+++ b/cocos2d/progress-timer/CCProgressTimer.js
@@ -0,0 +1,363 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2010 Lam Pham
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.Progresstimer is a subclass of cc.Node.
+ * It renders the inner sprite according to the percentage.
+ * The progress can be Radial, Horizontal or vertical.
+ * @class
+ * @extends cc.Node
+ *
+ * @property {cc.Point} midPoint - Midpoint is used to modify the progress start position.
+ * If you're using radials type then the midpoint changes the center point
+ * If you're using bar type the the midpoint changes the bar growth
+ * it expands from the center but clamps to the sprites edge so:
+ * you want a left to right then set the midpoint all the way to cc.p(0,y)
+ * you want a right to left then set the midpoint all the way to cc.p(1,y)
+ * you want a bottom to top then set the midpoint all the way to cc.p(x,0)
+ * you want a top to bottom then set the midpoint all the way to cc.p(x,1)
+ * @property {cc.Point} barChangeRate - This allows the bar type to move the component at a specific rate.
+ * @property {enum} type - Type of the progress timer: cc.ProgressTimer.TYPE_RADIAL|cc.ProgressTimer.TYPE_BAR.
+ * @property {Number} percentage - Percentage to change progress, from 0 to 100.
+ * @property {cc.Sprite} sprite - The sprite to show the progress percentage.
+ * @property {Boolean} reverseDir - Indicate whether the direction is reversed.
+ *
+ */
+cc.ProgressTimer = cc.Node.extend(/** @lends cc.ProgressTimer# */{
+ _type:null,
+ _percentage:0.0,
+ _sprite:null,
+
+ _midPoint:null,
+ _barChangeRate:null,
+ _reverseDirection:false,
+ _className:"ProgressTimer",
+
+ /**
+ * constructor of cc.cc.ProgressTimer
+ * @function
+ * @param {cc.Sprite} sprite
+ */
+ ctor: function(sprite){
+ cc.Node.prototype.ctor.call(this);
+
+ this._type = cc.ProgressTimer.TYPE_RADIAL;
+ this._percentage = 0.0;
+ this._midPoint = cc.p(0, 0);
+ this._barChangeRate = cc.p(0, 0);
+ this._reverseDirection = false;
+ this._sprite = null;
+
+ sprite && this.initWithSprite(sprite);
+ },
+
+ onEnter: function () {
+ this._super();
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ this._renderCmd.initCmd();
+ this._renderCmd._updateProgress();
+ }
+ },
+
+ cleanup: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ this._renderCmd.releaseData();
+ }
+ this._super();
+ },
+
+ /**
+ * Midpoint is used to modify the progress start position.
+ * If you're using radials type then the midpoint changes the center point
+ * If you're using bar type the the midpoint changes the bar growth
+ * it expands from the center but clamps to the sprites edge so:
+ * you want a left to right then set the midpoint all the way to cc.p(0,y)
+ * you want a right to left then set the midpoint all the way to cc.p(1,y)
+ * you want a bottom to top then set the midpoint all the way to cc.p(x,0)
+ * you want a top to bottom then set the midpoint all the way to cc.p(x,1)
+ * @return {cc.Point}
+ */
+ getMidpoint:function () {
+ return cc.p(this._midPoint.x, this._midPoint.y);
+ },
+
+ /**
+ * Midpoint setter
+ * @param {cc.Point} mpoint
+ */
+ setMidpoint:function (mpoint) {
+ this._midPoint = cc.pClamp(mpoint, cc.p(0, 0), cc.p(1, 1));
+ },
+
+ /**
+ * This allows the bar type to move the component at a specific rate
+ * Set the component to 0 to make sure it stays at 100%.
+ * For example you want a left to right bar but not have the height stay 100%
+ * Set the rate to be cc.p(0,1); and set the midpoint to = cc.p(0,.5f);
+ * @return {cc.Point}
+ */
+ getBarChangeRate:function () {
+ return cc.p(this._barChangeRate.x, this._barChangeRate.y);
+ },
+
+ /**
+ * @param {cc.Point} barChangeRate
+ */
+ setBarChangeRate:function (barChangeRate) {
+ this._barChangeRate = cc.pClamp(barChangeRate, cc.p(0, 0), cc.p(1, 1));
+ },
+
+ /**
+ * Change the percentage to change progress
+ * @return {cc.ProgressTimer.TYPE_RADIAL|cc.ProgressTimer.TYPE_BAR}
+ */
+ getType:function () {
+ return this._type;
+ },
+
+ /**
+ * Percentages are from 0 to 100
+ * @return {Number}
+ */
+ getPercentage:function () {
+ return this._percentage;
+ },
+
+ /**
+ * The image to show the progress percentage, retain
+ * @return {cc.Sprite}
+ */
+ getSprite:function () {
+ return this._sprite;
+ },
+
+ /**
+ * from 0-100
+ * @param {Number} percentage
+ */
+ setPercentage:function (percentage) {
+ if (this._percentage !== percentage) {
+ this._percentage = cc.clampf(percentage, 0, 100);
+ this._renderCmd._updateProgress();
+ }
+ },
+ /**
+ * only use for jsbinding
+ * @param bValue
+ */
+ setOpacityModifyRGB:function (bValue) {
+ },
+ /**
+ * only use for jsbinding
+ * @returns {boolean}
+ */
+ isOpacityModifyRGB:function () {
+ return false;
+ },
+ /**
+ * return if reverse direction
+ * @returns {boolean}
+ */
+ isReverseDirection:function () {
+ return this._reverseDirection;
+ },
+
+ /**
+ * set color of sprite
+ * @param {cc.Color} color
+ */
+ setColor:function (color) {
+ this._sprite.color = color;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ },
+
+ /**
+ * set opacity of sprite
+ * @param {Number} opacity
+ */
+ setOpacity:function (opacity) {
+ this._sprite.opacity = opacity;
+ //this._renderCmd._updateColor();
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.opacityDirty);
+ },
+
+ /**
+ * return color of sprite
+ * @return {cc.Color}
+ */
+ getColor:function () {
+ return this._sprite.color;
+ },
+
+ /**
+ * return Opacity of sprite
+ * @return {Number}
+ */
+ getOpacity:function () {
+ return this._sprite.opacity;
+ },
+
+ /**
+ * set reverse cc.ProgressTimer
+ * @function
+ * @param {Boolean} reverse
+ */
+ setReverseProgress: function(reverse){
+ if (this._reverseDirection !== reverse){
+ this._reverseDirection = reverse;
+ this._renderCmd.resetVertexData();
+ }
+ },
+
+ /**
+ * set sprite for cc.ProgressTimer
+ * @function
+ * @param {cc.Sprite} sprite
+ */
+ setSprite: function(sprite){
+ if (this._sprite !== sprite) {
+ this._sprite = sprite;
+ if(sprite) {
+ this.setContentSize(sprite.width, sprite.height);
+ sprite.ignoreAnchorPointForPosition(true);
+ }
+ else {
+ this.setContentSize(0,0);
+ }
+ this._renderCmd.resetVertexData();
+ }
+ },
+
+ /**
+ * set Progress type of cc.ProgressTimer
+ * @function
+ * @param {cc.ProgressTimer.TYPE_RADIAL|cc.ProgressTimer.TYPE_BAR} type
+ */
+ setType: function(type){
+ if (type !== this._type){
+ this._type = type;
+ this._renderCmd.resetVertexData();
+ }
+ },
+
+ /**
+ * Reverse Progress setter
+ * @function
+ * @param {Boolean} reverse
+ */
+ setReverseDirection: function(reverse){
+ if (this._reverseDirection !== reverse){
+ this._reverseDirection = reverse;
+ this._renderCmd.resetVertexData();
+ }
+ },
+
+ /**
+ * Initializes a progress timer with the sprite as the shape the timer goes through
+ * @function
+ * @param {cc.Sprite} sprite
+ * @return {Boolean}
+ */
+ initWithSprite: function(sprite){
+ this.percentage = 0;
+ this.setAnchorPoint(0.5,0.5);
+
+ this._type = cc.ProgressTimer.TYPE_RADIAL;
+ this._reverseDirection = false;
+ this.midPoint = cc.p(0.5, 0.5);
+ this.barChangeRate = cc.p(1, 1);
+ this.setSprite(sprite);
+ this._renderCmd.resetVertexData();
+ return true;
+ },
+
+ _createRenderCmd: function(){
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.ProgressTimer.CanvasRenderCmd(this);
+ else
+ return new cc.ProgressTimer.WebGLRenderCmd(this);
+ }
+});
+
+// Extended properties
+var _p = cc.ProgressTimer.prototype;
+
+/** @expose */
+_p.midPoint;
+cc.defineGetterSetter(_p, "midPoint", _p.getMidpoint, _p.setMidpoint);
+/** @expose */
+_p.barChangeRate;
+cc.defineGetterSetter(_p, "barChangeRate", _p.getBarChangeRate, _p.setBarChangeRate);
+/** @expose */
+_p.type;
+cc.defineGetterSetter(_p, "type", _p.getType, _p.setType);
+/** @expose */
+_p.percentage;
+cc.defineGetterSetter(_p, "percentage", _p.getPercentage, _p.setPercentage);
+/** @expose */
+_p.sprite;
+cc.defineGetterSetter(_p, "sprite", _p.getSprite, _p.setSprite);
+/** @expose */
+_p.reverseDir;
+cc.defineGetterSetter(_p, "reverseDir", _p.isReverseDirection, _p.setReverseDirection);
+
+
+/**
+ * create a progress timer object with image file name that renders the inner sprite according to the percentage
+ * @deprecated since v3.0,please use new cc.ProgressTimer(sprite) instead.
+ * @param {cc.Sprite} sprite
+ * @return {cc.ProgressTimer}
+ */
+cc.ProgressTimer.create = function (sprite) {
+ return new cc.ProgressTimer(sprite);
+};
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ProgressTimer.TEXTURE_COORDS_COUNT = 4;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.ProgressTimer.TEXTURE_COORDS = 0x4b;
+
+/**
+ * Radial Counter-Clockwise
+ * @type Number
+ * @constant
+ */
+cc.ProgressTimer.TYPE_RADIAL = 0;
+
+/**
+ * Bar
+ * @type Number
+ * @constant
+ */
+cc.ProgressTimer.TYPE_BAR = 1;
diff --git a/cocos2d/progress-timer/CCProgressTimerCanvasRenderCmd.js b/cocos2d/progress-timer/CCProgressTimerCanvasRenderCmd.js
new file mode 100644
index 0000000000..4dc2a71b74
--- /dev/null
+++ b/cocos2d/progress-timer/CCProgressTimerCanvasRenderCmd.js
@@ -0,0 +1,286 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.ProgressTimer's rendering objects of Canvas
+ */
+(function () {
+ cc.ProgressTimer.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+
+ this._PI180 = Math.PI / 180;
+ this._barRect = cc.rect(0, 0, 0, 0);
+ this._origin = cc.p(0, 0);
+ this._radius = 0;
+ this._startAngle = 270;
+ this._endAngle = 270;
+ this._counterClockWise = false;
+ this._canUseDirtyRegion = true;
+ };
+
+ var proto = cc.ProgressTimer.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.ProgressTimer.CanvasRenderCmd;
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext(), node = this._node, locSprite = node._sprite;
+ var locTextureCoord = locSprite._renderCmd._textureCoord, alpha = locSprite._renderCmd._displayedOpacity / 255;
+
+ if (locTextureCoord.width === 0 || locTextureCoord.height === 0)
+ return;
+ if (!locSprite._texture || !locTextureCoord.validRect || alpha === 0)
+ return;
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ wrapper.setCompositeOperation(locSprite._blendFuncStr);
+ wrapper.setGlobalAlpha(alpha);
+
+ var locRect = locSprite._rect, locOffsetPosition = locSprite._offsetPosition;
+ var locX = locOffsetPosition.x,
+ locY = -locOffsetPosition.y - locRect.height,
+ locWidth = locRect.width,
+ locHeight = locRect.height;
+
+ wrapper.save();
+ if (locSprite._flippedX) {
+ locX = -locX - locWidth;
+ context.scale(-1, 1);
+ }
+ if (locSprite._flippedY) {
+ locY = locOffsetPosition.y;
+ context.scale(1, -1);
+ }
+
+ //clip
+ if (node._type === cc.ProgressTimer.TYPE_BAR) {
+ var locBarRect = this._barRect;
+ context.beginPath();
+ context.rect(locBarRect.x, locBarRect.y, locBarRect.width, locBarRect.height);
+ context.clip();
+ context.closePath();
+ } else if (node._type === cc.ProgressTimer.TYPE_RADIAL) {
+ var locOriginX = this._origin.x;
+ var locOriginY = this._origin.y;
+ context.beginPath();
+ context.arc(locOriginX, locOriginY, this._radius, this._PI180 * this._startAngle, this._PI180 * this._endAngle, this._counterClockWise);
+ context.lineTo(locOriginX, locOriginY);
+ context.clip();
+ context.closePath();
+ }
+
+ //draw sprite
+ var texture = locSprite._renderCmd._textureToRender || locSprite._texture;
+ var image = texture.getHtmlElementObj();
+ if (locSprite._renderCmd._colorized) {
+ context.drawImage(image,
+ 0, 0, locTextureCoord.width, locTextureCoord.height,
+ locX, locY, locWidth, locHeight);
+ } else {
+ context.drawImage(image,
+ locTextureCoord.renderX, locTextureCoord.renderY, locTextureCoord.width, locTextureCoord.height,
+ locX, locY, locWidth, locHeight);
+ }
+ wrapper.restore();
+ cc.g_NumberOfDraws++;
+ };
+
+ proto.releaseData = function () {
+ };
+
+ proto.resetVertexData = function () {
+ };
+
+ proto._updateProgress = function () {
+ this.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ var node = this._node;
+ var locSprite = node._sprite;
+ var sw = locSprite.width, sh = locSprite.height;
+ var locMidPoint = node._midPoint;
+
+ if (node._type === cc.ProgressTimer.TYPE_RADIAL) {
+ this._radius = Math.round(Math.sqrt(sw * sw + sh * sh));
+ var locStartAngle, locEndAngle, locCounterClockWise = false, locOrigin = this._origin;
+ locOrigin.x = sw * locMidPoint.x;
+ locOrigin.y = -sh * locMidPoint.y;
+
+ if (node._reverseDirection) {
+ locEndAngle = 270;
+ locStartAngle = 270 - 3.6 * node._percentage;
+ } else {
+ locStartAngle = -90;
+ locEndAngle = -90 + 3.6 * node._percentage;
+ }
+
+ if (locSprite._flippedX) {
+ locOrigin.x -= sw * (node._midPoint.x * 2);
+ locStartAngle = -locStartAngle;
+ locEndAngle = -locEndAngle;
+ locStartAngle -= 180;
+ locEndAngle -= 180;
+ locCounterClockWise = !locCounterClockWise;
+ }
+ if (locSprite._flippedY) {
+ locOrigin.y += sh * (node._midPoint.y * 2);
+ locCounterClockWise = !locCounterClockWise;
+ locStartAngle = -locStartAngle;
+ locEndAngle = -locEndAngle;
+ }
+
+ this._startAngle = locStartAngle;
+ this._endAngle = locEndAngle;
+ this._counterClockWise = locCounterClockWise;
+ } else {
+ var locBarChangeRate = node._barChangeRate;
+ var percentageF = node._percentage / 100;
+ var locBarRect = this._barRect;
+
+ var drewSize = cc.size((sw * (1 - locBarChangeRate.x)), (sh * (1 - locBarChangeRate.y)));
+ var drawingSize = cc.size((sw - drewSize.width) * percentageF, (sh - drewSize.height) * percentageF);
+ var currentDrawSize = cc.size(drewSize.width + drawingSize.width, drewSize.height + drawingSize.height);
+
+ var startPoint = cc.p(sw * locMidPoint.x, sh * locMidPoint.y);
+
+ var needToLeft = startPoint.x - currentDrawSize.width / 2;
+ if ((locMidPoint.x > 0.5) && (currentDrawSize.width / 2 >= sw - startPoint.x))
+ needToLeft = sw - currentDrawSize.width;
+
+ var needToTop = startPoint.y - currentDrawSize.height / 2;
+ if ((locMidPoint.y > 0.5) && (currentDrawSize.height / 2 >= sh - startPoint.y))
+ needToTop = sh - currentDrawSize.height;
+
+ //left pos
+ locBarRect.x = 0;
+ var flipXNeed = 1;
+ if (locSprite._flippedX) {
+ locBarRect.x -= currentDrawSize.width;
+ flipXNeed = -1;
+ }
+
+ if (needToLeft > 0)
+ locBarRect.x += needToLeft * flipXNeed;
+
+ //right pos
+ locBarRect.y = 0;
+ var flipYNeed = 1;
+ if (locSprite._flippedY) {
+ locBarRect.y += currentDrawSize.height;
+ flipYNeed = -1;
+ }
+
+ if (needToTop > 0)
+ locBarRect.y -= needToTop * flipYNeed;
+
+ //clip width and clip height
+ locBarRect.width = currentDrawSize.width;
+ locBarRect.height = -currentDrawSize.height;
+ }
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ var node = this._node;
+ if (!node._sprite)
+ return;
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ var parentNode = parentCmd ? parentCmd._node : null;
+
+ if (parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & flags.colorDirty))
+ locFlag |= flags.colorDirty;
+
+ if (parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & flags.opacityDirty))
+ locFlag |= flags.opacityDirty;
+
+ if (parentCmd && (parentCmd._dirtyFlag & flags.transformDirty))
+ locFlag |= flags.transformDirty;
+
+ this._dirtyFlag = locFlag;
+
+ var spriteCmd = node._sprite._renderCmd;
+ var spriteFlag = spriteCmd._dirtyFlag;
+
+ var colorDirty = spriteFlag & flags.colorDirty,
+ opacityDirty = spriteFlag & flags.opacityDirty;
+
+ if (colorDirty) {
+ spriteCmd._syncDisplayColor();
+ spriteCmd._dirtyFlag &= ~flags.colorDirty;
+ this._dirtyFlag &= ~flags.colorDirty;
+ }
+
+ if (opacityDirty) {
+ spriteCmd._syncDisplayOpacity();
+ spriteCmd._dirtyFlag &= ~flags.opacityDirty;
+ this._dirtyFlag &= ~flags.opacityDirty;
+ }
+
+ if (colorDirty || opacityDirty) {
+ spriteCmd._updateColor();
+ }
+
+ if (locFlag & flags.transformDirty) {
+ //update the transform
+ this.transform(parentCmd);
+ }
+
+ if (locFlag & flags.orderDirty) {
+ this._dirtyFlag &= ~flags.orderDirty;
+ }
+ };
+
+ proto.updateStatus = function () {
+ var node = this._node;
+ if (!node._sprite)
+ return;
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ var spriteCmd = node._sprite._renderCmd;
+ var spriteFlag = spriteCmd._dirtyFlag;
+
+ var colorDirty = spriteFlag & flags.colorDirty,
+ opacityDirty = spriteFlag & flags.opacityDirty;
+
+ if (colorDirty) {
+ spriteCmd._updateDisplayColor();
+ spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.colorDirty ^ spriteCmd._dirtyFlag;
+ this._dirtyFlag = this._dirtyFlag & flags.colorDirty ^ this._dirtyFlag;
+ }
+
+ if (opacityDirty) {
+ spriteCmd._updateDisplayOpacity();
+ spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.opacityDirty ^ spriteCmd._dirtyFlag;
+ this._dirtyFlag = this._dirtyFlag & flags.opacityDirty ^ this._dirtyFlag;
+ }
+
+ if (colorDirty || opacityDirty) {
+ spriteCmd._updateColor();
+ }
+
+ if (locFlag & flags.transformDirty) {
+ //update the transform
+ this.transform(this.getParentRenderCmd(), true);
+ }
+ if(locFlag & flags.contentDirty) {
+ this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
+ }
+ this._dirtyFlag = 0;
+ };
+})();
diff --git a/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js b/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js
new file mode 100644
index 0000000000..8a89913eed
--- /dev/null
+++ b/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js
@@ -0,0 +1,542 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.ProgressTimer's rendering objects of WebGL
+ */
+(function () {
+ var MAX_VERTEX_COUNT = 8;
+
+ cc.ProgressTimer.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._progressDirty = true;
+
+ this._bl = cc.p();
+ this._tr = cc.p();
+ this._transformUpdating = false;
+
+ this.initCmd();
+ };
+
+ var proto = cc.ProgressTimer.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.ProgressTimer.WebGLRenderCmd;
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+ var sp = this._node._sprite;
+ sp._renderCmd.transform(this, recursive);
+
+ var lx = sp._offsetPosition.x, rx = lx + sp._rect.width,
+ by = sp._offsetPosition.y, ty = by + sp._rect.height,
+ wt = this._worldTransform;
+ this._bl.x = lx * wt.a + by * wt.c + wt.tx;
+ this._bl.y = lx * wt.b + by * wt.d + wt.ty;
+ this._tr.x = rx * wt.a + ty * wt.c + wt.tx;
+ this._tr.y = rx * wt.b + ty * wt.d + wt.ty;
+
+ this._transformUpdating = true;
+ this._updateProgressData();
+ this._transformUpdating = false;
+ };
+
+ proto.rendering = function (ctx) {
+ var node = this._node;
+ var context = ctx || cc._renderContext;
+ if (this._vertexDataCount === 0 || !node._sprite)
+ return;
+
+ this._glProgramState.apply();
+ this._shaderProgram._updateProjectionUniform();
+
+ var blendFunc = node._sprite._blendFunc;
+ cc.glBlendFunc(blendFunc.src, blendFunc.dst);
+ cc.glBindTexture2D(node._sprite.texture);
+ context.bindBuffer(context.ARRAY_BUFFER, this._vertexWebGLBuffer);
+
+ context.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ context.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+ context.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+
+ if (this._vertexDataDirty) {
+ context.bufferSubData(context.ARRAY_BUFFER, 0, this._float32View);
+ this._vertexDataDirty = false;
+ }
+ var locVertexDataLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT;
+ context.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, context.FLOAT, false, locVertexDataLen, 0);
+ context.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, context.UNSIGNED_BYTE, true, locVertexDataLen, 12);
+ context.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, context.FLOAT, false, locVertexDataLen, 16);
+
+ if (node._type === cc.ProgressTimer.TYPE_RADIAL)
+ context.drawArrays(context.TRIANGLE_FAN, 0, this._vertexDataCount);
+ else if (node._type === cc.ProgressTimer.TYPE_BAR) {
+ if (!node._reverseDirection)
+ context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount);
+ else {
+ context.drawArrays(context.TRIANGLE_STRIP, 0, this._vertexDataCount / 2);
+ context.drawArrays(context.TRIANGLE_STRIP, 4, this._vertexDataCount / 2);
+ // 2 draw calls
+ cc.g_NumberOfDraws++;
+ }
+ }
+ cc.g_NumberOfDraws++;
+ };
+
+ proto._syncStatus = function (parentCmd) {
+ var node = this._node;
+ if (!node._sprite)
+ return;
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ var parentNode = parentCmd ? parentCmd._node : null;
+
+ if (parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & flags.colorDirty))
+ locFlag |= flags.colorDirty;
+ if (parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & flags.opacityDirty))
+ locFlag |= flags.opacityDirty;
+ if (parentCmd && (parentCmd._dirtyFlag & flags.transformDirty))
+ locFlag |= flags.transformDirty;
+ this._dirtyFlag = locFlag;
+
+ var spriteCmd = node._sprite._renderCmd;
+ var spriteFlag = spriteCmd._dirtyFlag;
+
+ var colorDirty = (locFlag | spriteFlag) & flags.colorDirty,
+ opacityDirty = (locFlag | spriteFlag) & flags.opacityDirty;
+
+ if (colorDirty) {
+ spriteCmd._syncDisplayColor();
+ spriteCmd._dirtyFlag &= ~flags.colorDirty;
+ this._dirtyFlag &= ~flags.colorDirty;
+ }
+
+ if (opacityDirty) {
+ spriteCmd._syncDisplayOpacity();
+ spriteCmd._dirtyFlag &= ~flags.opacityDirty;
+ this._dirtyFlag &= ~flags.opacityDirty;
+ }
+
+ if (colorDirty || opacityDirty) {
+ this._updateColor();
+ }
+
+ if (locFlag & flags.transformDirty) {
+ //update the transform
+ this.transform(parentCmd);
+ }
+
+ if (locFlag & flags.textureDirty) {
+ this._updateProgressData();
+ this._dirtyFlag &= ~flags.textureDirty;
+ }
+
+ spriteCmd._dirtyFlag = 0;
+ };
+
+ proto.updateStatus = function () {
+ var node = this._node;
+ if (!node._sprite)
+ return;
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ var spriteCmd = node._sprite._renderCmd;
+ var spriteFlag = spriteCmd._dirtyFlag;
+
+ var colorDirty = (locFlag | spriteFlag) & flags.colorDirty,
+ opacityDirty = (locFlag | spriteFlag) & flags.opacityDirty;
+
+ if (colorDirty) {
+ spriteCmd._updateDisplayColor();
+ spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.colorDirty ^ spriteCmd._dirtyFlag;
+ this._dirtyFlag = this._dirtyFlag & flags.colorDirty ^ this._dirtyFlag;
+ }
+
+ if (opacityDirty) {
+ spriteCmd._updateDisplayOpacity();
+ spriteCmd._dirtyFlag = spriteCmd._dirtyFlag & flags.opacityDirty ^ spriteCmd._dirtyFlag;
+ this._dirtyFlag = this._dirtyFlag & flags.opacityDirty ^ this._dirtyFlag;
+ }
+
+ if (colorDirty || opacityDirty) {
+ this._updateColor();
+ }
+
+ if (locFlag & flags.transformDirty) {
+ //update the transform
+ this.transform(this.getParentRenderCmd(), true);
+ }
+
+ if (locFlag & flags.orderDirty) {
+ this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
+ }
+
+ if (locFlag & flags.textureDirty) {
+ this._updateProgressData();
+ this._dirtyFlag = this._dirtyFlag & flags.textureDirty ^ this._dirtyFlag;
+ }
+ };
+
+ proto.releaseData = function () {
+ if (this._vertexData) {
+ //release all previous information
+ var webglBuffer = this._vertexWebGLBuffer;
+ setTimeout(function () {
+ cc._renderContext.deleteBuffer(webglBuffer);
+ }, 0.1);
+ this._vertexWebGLBuffer = null;
+ this._vertexData = null;
+ this._float32View = null;
+ this._vertexArrayBuffer = null;
+ this._vertexDataCount = 0;
+ }
+ };
+
+ proto.initCmd = function () {
+ if (!this._vertexData) {
+ this._vertexWebGLBuffer = cc._renderContext.createBuffer();
+
+ var vertexDataLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT;
+ this._vertexArrayBuffer = new ArrayBuffer(MAX_VERTEX_COUNT * vertexDataLen);
+ this._float32View = new Float32Array(this._vertexArrayBuffer);
+ this._vertexData = [];
+ for (var i = 0; i < MAX_VERTEX_COUNT; i++) {
+ this._vertexData[i] = new cc.V3F_C4B_T2F(null, null, null, this._vertexArrayBuffer, i * vertexDataLen);
+ }
+
+ // Init buffer data
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexWebGLBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, this._float32View, gl.DYNAMIC_DRAW);
+
+ this._vertexDataCount = 0;
+ this._vertexDataDirty = true;
+
+ //shader program
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
+ }
+ };
+
+ proto.resetVertexData = function () {
+ this._vertexDataCount = 0;
+ };
+
+ proto._updateProgressData = function () {
+ var node = this._node;
+ var locType = node._type;
+ if (locType === cc.ProgressTimer.TYPE_RADIAL)
+ this._updateRadial();
+ else if (locType === cc.ProgressTimer.TYPE_BAR)
+ this._updateBar();
+ this._vertexDataDirty = true;
+ };
+
+ proto._updateProgress = function () {
+ this.setDirtyFlag(cc.Node._dirtyFlags.textureDirty);
+ };
+
+ /**
+ *
+ * Update does the work of mapping the texture onto the triangles for the bar
+ * It now doesn't occur the cost of free/alloc data every update cycle.
+ * It also only changes the percentage point but no other points if they have not been modified.
+ *
+ * It now deals with flipped texture. If you run into this problem, just use the
+ * sprite property and enable the methods flipX, flipY.
+ *
+ * @private
+ */
+ proto._updateBar = function () {
+ var node = this._node;
+ if (!node._sprite)
+ return;
+
+ var i, alpha = node._percentage / 100.0;
+ var locBarChangeRate = node._barChangeRate;
+ var alphaOffset = cc.pMult(cc.p((1.0 - locBarChangeRate.x) + alpha * locBarChangeRate.x,
+ (1.0 - locBarChangeRate.y) + alpha * locBarChangeRate.y), 0.5);
+ var min = cc.pSub(node._midPoint, alphaOffset), max = cc.pAdd(node._midPoint, alphaOffset);
+
+ if (min.x < 0) {
+ max.x += -min.x;
+ min.x = 0;
+ }
+
+ if (max.x > 1) {
+ min.x -= max.x - 1;
+ max.x = 1;
+ }
+
+ if (min.y < 0) {
+ max.y += -min.y;
+ min.y = 0;
+ }
+
+ if (max.y > 1) {
+ min.y -= max.y - 1;
+ max.y = 1;
+ }
+
+ var locVertexData;
+ if (!this._reverseDirection) {
+ if (!this._vertexDataCount) {
+ this._vertexDataCount = 4;
+ }
+ locVertexData = this._vertexData;
+ // TOPLEFT
+ this._textureCoordFromAlphaPoint(locVertexData[0].texCoords, min.x, max.y);
+ this._vertexFromAlphaPoint(locVertexData[0].vertices, min.x, max.y);
+
+ // BOTLEFT
+ this._textureCoordFromAlphaPoint(locVertexData[1].texCoords, min.x, min.y);
+ this._vertexFromAlphaPoint(locVertexData[1].vertices, min.x, min.y);
+
+ // TOPRIGHT
+ this._textureCoordFromAlphaPoint(locVertexData[2].texCoords, max.x, max.y);
+ this._vertexFromAlphaPoint(locVertexData[2].vertices, max.x, max.y);
+
+ // BOTRIGHT
+ this._textureCoordFromAlphaPoint(locVertexData[3].texCoords, max.x, min.y);
+ this._vertexFromAlphaPoint(locVertexData[3].vertices, max.x, min.y);
+ } else {
+ locVertexData = this._vertexData;
+ if (!this._vertexDataCount) {
+ this._vertexDataCount = 8;
+ // TOPLEFT 1
+ this._textureCoordFromAlphaPoint(locVertexData[0].texCoords, 0, 1);
+ this._vertexFromAlphaPoint(locVertexData[0].vertices, 0, 1);
+
+ // BOTLEFT 1
+ this._textureCoordFromAlphaPoint(locVertexData[1].texCoords, 0, 0);
+ this._vertexFromAlphaPoint(locVertexData[1].vertices, 0, 0);
+
+ // TOPRIGHT 2
+ this._textureCoordFromAlphaPoint(locVertexData[6].texCoords, 1, 1);
+ this._vertexFromAlphaPoint(locVertexData[6].vertices, 1, 1);
+
+ // BOTRIGHT 2
+ this._textureCoordFromAlphaPoint(locVertexData[7].texCoords, 1, 0);
+ this._vertexFromAlphaPoint(locVertexData[7].vertices, 1, 0);
+ }
+
+ // TOPRIGHT 1
+ this._textureCoordFromAlphaPoint(locVertexData[2].texCoords, min.x, max.y);
+ this._vertexFromAlphaPoint(locVertexData[2].vertices, min.x, max.y);
+
+ // BOTRIGHT 1
+ this._textureCoordFromAlphaPoint(locVertexData[3].texCoords, min.x, min.y);
+ this._vertexFromAlphaPoint(locVertexData[3].vertices, min.x, min.y);
+
+ // TOPLEFT 2
+ this._textureCoordFromAlphaPoint(locVertexData[4].texCoords, max.x, max.y);
+ this._vertexFromAlphaPoint(locVertexData[4].vertices, max.x, max.y);
+
+ // BOTLEFT 2
+ this._textureCoordFromAlphaPoint(locVertexData[5].texCoords, max.x, min.y);
+ this._vertexFromAlphaPoint(locVertexData[5].vertices, max.x, min.y);
+ }
+ this._updateColor();
+ };
+
+ /**
+ *
+ * Update does the work of mapping the texture onto the triangles
+ * It now doesn't occur the cost of free/alloc data every update cycle.
+ * It also only changes the percentage point but no other points if they have not been modified.
+ *
+ * It now deals with flipped texture. If you run into this problem, just use the
+ * sprite property and enable the methods flipX, flipY.
+ *
+ * @private
+ */
+ proto._updateRadial = function () {
+ var node = this._node;
+ if (!node._sprite)
+ return;
+
+ var i, locMidPoint = node._midPoint;
+ var alpha = node._percentage / 100;
+ var angle = 2 * (cc.PI) * ( node._reverseDirection ? alpha : 1.0 - alpha);
+
+ // We find the vector to do a hit detection based on the percentage
+ // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate
+ // from that by the progress angle around the m_tMidpoint pivot
+ var topMid = cc.p(locMidPoint.x, 1);
+ var percentagePt = cc.pRotateByAngle(topMid, locMidPoint, angle);
+
+ var index = 0;
+ var hit;
+
+ if (alpha === 0) {
+ // More efficient since we don't always need to check intersection
+ // If the alpha is zero then the hit point is top mid and the index is 0.
+ hit = topMid;
+ index = 0;
+ } else if (alpha === 1) {
+ // More efficient since we don't always need to check intersection
+ // If the alpha is one then the hit point is top mid and the index is 4.
+ hit = topMid;
+ index = 4;
+ } else {
+ // We run a for loop checking the edges of the texture to find the
+ // intersection point
+ // We loop through five points since the top is split in half
+
+ var min_t = cc.FLT_MAX;
+ var locProTextCoordsCount = cc.ProgressTimer.TEXTURE_COORDS_COUNT;
+ for (i = 0; i <= locProTextCoordsCount; ++i) {
+ var pIndex = (i + (locProTextCoordsCount - 1)) % locProTextCoordsCount;
+
+ var edgePtA = this._boundaryTexCoord(i % locProTextCoordsCount);
+ var edgePtB = this._boundaryTexCoord(pIndex);
+
+ // Remember that the top edge is split in half for the 12 o'clock position
+ // Let's deal with that here by finding the correct endpoints
+ if (i === 0)
+ edgePtB = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x);
+ else if (i === 4)
+ edgePtA = cc.pLerp(edgePtA, edgePtB, 1 - locMidPoint.x);
+
+ // retPoint are returned by ccpLineIntersect
+ var retPoint = cc.p(0, 0);
+ if (cc.pLineIntersect(edgePtA, edgePtB, locMidPoint, percentagePt, retPoint)) {
+ // Since our hit test is on rays we have to deal with the top edge
+ // being in split in half so we have to test as a segment
+ if ((i === 0 || i === 4)) {
+ // s represents the point between edgePtA--edgePtB
+ if (!(0 <= retPoint.x && retPoint.x <= 1))
+ continue;
+ }
+ // As long as our t isn't negative we are at least finding a
+ // correct hitpoint from m_tMidpoint to percentagePt.
+ if (retPoint.y >= 0) {
+ // Because the percentage line and all the texture edges are
+ // rays we should only account for the shortest intersection
+ if (retPoint.y < min_t) {
+ min_t = retPoint.y;
+ index = i;
+ }
+ }
+ }
+ }
+
+ // Now that we have the minimum magnitude we can use that to find our intersection
+ hit = cc.pAdd(locMidPoint, cc.pMult(cc.pSub(percentagePt, locMidPoint), min_t));
+ }
+
+ // The size of the vertex data is the index from the hitpoint
+ // the 3 is for the m_tMidpoint, 12 o'clock point and hitpoint position.
+ var sameIndexCount = true;
+ if (this._vertexDataCount !== index + 3) {
+ sameIndexCount = false;
+ this._vertexDataCount = index + 3;
+ }
+
+ this._updateColor();
+
+ var locVertexData = this._vertexData;
+ if (this._transformUpdating || !sameIndexCount) {
+ // First we populate the array with the m_tMidpoint, then all
+ // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint
+ this._textureCoordFromAlphaPoint(locVertexData[0].texCoords, locMidPoint.x, locMidPoint.y);
+ this._vertexFromAlphaPoint(locVertexData[0].vertices, locMidPoint.x, locMidPoint.y);
+
+ this._textureCoordFromAlphaPoint(locVertexData[1].texCoords, topMid.x, topMid.y);
+ this._vertexFromAlphaPoint(locVertexData[1].vertices, topMid.x, topMid.y);
+
+ for (i = 0; i < index; i++) {
+ var alphaPoint = this._boundaryTexCoord(i);
+ this._textureCoordFromAlphaPoint(locVertexData[i + 2].texCoords, alphaPoint.x, alphaPoint.y);
+ this._vertexFromAlphaPoint(locVertexData[i + 2].vertices, alphaPoint.x, alphaPoint.y);
+ }
+ }
+
+ // hitpoint will go last
+ this._textureCoordFromAlphaPoint(locVertexData[this._vertexDataCount - 1].texCoords, hit.x, hit.y);
+ this._vertexFromAlphaPoint(locVertexData[this._vertexDataCount - 1].vertices, hit.x, hit.y);
+ };
+
+ proto._boundaryTexCoord = function (index) {
+ if (index < cc.ProgressTimer.TEXTURE_COORDS_COUNT) {
+ var locProTextCoords = cc.ProgressTimer.TEXTURE_COORDS;
+ if (this._node._reverseDirection)
+ return cc.p((locProTextCoords >> (7 - (index << 1))) & 1, (locProTextCoords >> (7 - ((index << 1) + 1))) & 1);
+ else
+ return cc.p((locProTextCoords >> ((index << 1) + 1)) & 1, (locProTextCoords >> (index << 1)) & 1);
+ }
+ return cc.p(0, 0);
+ };
+
+ proto._textureCoordFromAlphaPoint = function (coords, ax, ay) {
+ var locSprite = this._node._sprite;
+ if (!locSprite) {
+ coords.u = 0;
+ coords.v = 0;
+ return;
+ }
+ var uvs = locSprite._renderCmd._vertices,
+ bl = uvs[1],
+ tr = uvs[2];
+ var min = cc.p(bl.u, bl.v);
+ var max = cc.p(tr.u, tr.v);
+
+ // Fix bug #1303 so that progress timer handles sprite frame texture rotation
+ if (locSprite.textureRectRotated) {
+ var temp = ax;
+ ax = ay;
+ ay = temp;
+ }
+ coords.u = min.x * (1 - ax) + max.x * ax;
+ coords.v = min.y * (1 - ay) + max.y * ay;
+ };
+
+ proto._vertexFromAlphaPoint = function (vertex, ax, ay) {
+ vertex.x = this._bl.x * (1 - ax) + this._tr.x * ax;
+ vertex.y = this._bl.y * (1 - ay) + this._tr.y * ay;
+ vertex.z = this._node._vertexZ;
+ };
+
+ proto._updateColor = function () {
+ var sp = this._node._sprite;
+ if (!this._vertexDataCount || !sp)
+ return;
+
+ var color = this._displayedColor;
+ var spColor = sp._renderCmd._displayedColor;
+ var r = spColor.r;
+ var g = spColor.g;
+ var b = spColor.b;
+ var a = sp._renderCmd._displayedOpacity / 255;
+ if (sp._opacityModifyRGB) {
+ r *= a;
+ g *= a;
+ b *= a;
+ }
+ color.r = r;
+ color.g = g;
+ color.b = b;
+ color.a = sp._renderCmd._displayedOpacity;
+ var locVertexData = this._vertexData;
+ for (var i = 0, len = this._vertexDataCount; i < len; ++i) {
+ locVertexData[i].colors = color;
+ }
+ this._vertexDataDirty = true;
+ };
+})();
diff --git a/cocos2d/render-texture/CCRenderTexture.js b/cocos2d/render-texture/CCRenderTexture.js
new file mode 100644
index 0000000000..5cc00ae45a
--- /dev/null
+++ b/cocos2d/render-texture/CCRenderTexture.js
@@ -0,0 +1,425 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2009 Jason Booth
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * enum for jpg
+ * @constant
+ * @type Number
+ */
+cc.IMAGE_FORMAT_JPEG = 0;
+/**
+ * enum for png
+ * @constant
+ * @type Number
+ */
+cc.IMAGE_FORMAT_PNG = 1;
+/**
+ * enum for raw
+ * @constant
+ * @type Number
+ */
+cc.IMAGE_FORMAT_RAWDATA = 9;
+
+/**
+ * @param {Number} x
+ * @return {Number}
+ * Constructor
+ */
+cc.NextPOT = function (x) {
+ x = x - 1;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >> 16);
+ return x + 1;
+};
+
+/**
+ * cc.RenderTexture is a generic rendering target. To render things into it,
+ * simply construct a render target, call begin on it, call visit on any cocos
+ * scenes or objects to render them, and call end. For convenience, render texture
+ * adds a sprite as it's display child with the results, so you can simply add
+ * the render texture to your scene and treat it like any other CocosNode.
+ * There are also functions for saving the render texture to disk in PNG or JPG format.
+ * @class
+ * @extends cc.Node
+ *
+ * @property {cc.Sprite} sprite - The sprite.
+ * @property {cc.Sprite} clearFlags - Code for "auto" update.
+ * @property {Number} clearDepthVal - Clear depth value.
+ * @property {Boolean} autoDraw - Indicate auto draw mode activate or not.
+ * @property {Number} clearStencilVal - Clear stencil value.
+ * @property {cc.Color} clearColorVal - Clear color value, valid only when "autoDraw" is true.
+ */
+cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{
+ sprite: null,
+
+ //
+ // Code for "auto" update
+ // Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT.
+ // They can be OR'ed. Valid when "autoDraw is YES.
+ // @public
+ //
+ clearFlags: 0,
+
+ clearDepthVal: 0,
+ autoDraw: false,
+
+ _texture: null,
+ _pixelFormat: 0,
+
+ clearStencilVal: 0,
+ _clearColor: null,
+
+ _className: "RenderTexture",
+
+ /**
+ * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid
+ * Constructor of cc.RenderTexture for Canvas
+ * @param {Number} width
+ * @param {Number} height
+ * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
+ * @param {Number} depthStencilFormat
+ * @example
+ * // Example
+ * var rt = new cc.RenderTexture(width, height, format, depthStencilFormat)
+ * @function
+ */
+ ctor: function (width, height, format, depthStencilFormat) {
+ cc.Node.prototype.ctor.call(this);
+ this._cascadeColorEnabled = true;
+ this._cascadeOpacityEnabled = true;
+ this._pixelFormat = cc.Texture2D.PIXEL_FORMAT_RGBA8888;
+ this._clearColor = new cc.Color(0, 0, 0, 255);
+
+ if (width !== undefined && height !== undefined) {
+ format = format || cc.Texture2D.PIXEL_FORMAT_RGBA8888;
+ depthStencilFormat = depthStencilFormat || 0;
+ this.initWithWidthAndHeight(width, height, format, depthStencilFormat);
+ }
+ this.setAnchorPoint(0, 0);
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.RenderTexture.CanvasRenderCmd(this);
+ else
+ return new cc.RenderTexture.WebGLRenderCmd(this);
+ },
+
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ var renderer = cc.renderer;
+
+ cmd.visit(parentCmd);
+ renderer.pushRenderCommand(cmd);
+ this.sprite.visit(this);
+ cmd._dirtyFlag = 0;
+ },
+
+ /**
+ * Clear RenderTexture.
+ * @function
+ */
+ cleanup: function () {
+ cc.Node.prototype.onExit.call(this);
+ this._renderCmd.cleanup();
+ },
+
+ /**
+ * Gets the sprite
+ * @return {cc.Sprite}
+ */
+ getSprite: function () {
+ return this.sprite;
+ },
+
+ /**
+ * Set the sprite
+ * @param {cc.Sprite} sprite
+ */
+ setSprite: function (sprite) {
+ this.sprite = sprite;
+ },
+
+ /**
+ * Used for grab part of screen to a texture.
+ * @param {cc.Point} rtBegin
+ * @param {cc.Rect} fullRect
+ * @param {cc.Rect} fullViewport
+ */
+ setVirtualViewport: function (rtBegin, fullRect, fullViewport) {
+ this._renderCmd.setVirtualViewport(rtBegin, fullRect, fullViewport);
+ },
+
+ /**
+ * Initializes the instance of cc.RenderTexture
+ * @function
+ * @param {Number} width
+ * @param {Number} height
+ * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} [format]
+ * @param {Number} [depthStencilFormat]
+ * @return {Boolean}
+ */
+ initWithWidthAndHeight: function (width, height, format, depthStencilFormat) {
+ return this._renderCmd.initWithWidthAndHeight(width, height, format, depthStencilFormat);
+ },
+
+ /**
+ * starts grabbing
+ * @function
+ */
+ begin: function () {
+ cc.renderer._turnToCacheMode(this.__instanceId);
+ this._renderCmd.begin();
+ },
+ /**
+ * starts rendering to the texture while clearing the texture first.
+ * This is more efficient then calling -clear first and then -begin
+ * @param {Number} r red 0-255
+ * @param {Number} g green 0-255
+ * @param {Number} b blue 0-255
+ * @param {Number} a alpha 0-255 0 is transparent
+ * @param {Number} [depthValue=]
+ * @param {Number} [stencilValue=]
+ */
+ beginWithClear: function (r, g, b, a, depthValue, stencilValue) {
+ //todo: only for WebGL?
+ var gl = cc._renderContext;
+ depthValue = depthValue || gl.COLOR_BUFFER_BIT;
+ stencilValue = stencilValue || (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ this._beginWithClear(r, g, b, a, depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
+ },
+
+ _beginWithClear: function (r, g, b, a, depthValue, stencilValue, flags) {
+ this.begin();
+ this._renderCmd._beginWithClear(r, g, b, a, depthValue, stencilValue, flags);
+ },
+
+ /**
+ * ends grabbing
+ * @function
+ */
+ end: function () {
+ this._renderCmd.end();
+ },
+
+ /**
+ * clears the texture with a color
+ * @param {Number|cc.Rect} r red 0-255
+ * @param {Number} g green 0-255
+ * @param {Number} b blue 0-255
+ * @param {Number} a alpha 0-255
+ */
+ clear: function (r, g, b, a) {
+ this.beginWithClear(r, g, b, a);
+ this.end();
+ },
+
+ /**
+ * clears the texture with rect.
+ * @function
+ * @param {number} x
+ * @param {number} y
+ * @param {number} width
+ * @param {number} height
+ */
+ clearRect: function (x, y, width, height) {
+ this._renderCmd.clearRect(x, y, width, height);
+ },
+
+ /**
+ * clears the texture with a specified depth value
+ * @function
+ * @param {Number} depthValue
+ */
+ clearDepth: function (depthValue) {
+ this._renderCmd.clearDepth(depthValue);
+ },
+
+ /**
+ * clears the texture with a specified stencil value
+ * @function
+ * @param {Number} stencilValue
+ */
+ clearStencil: function (stencilValue) {
+ this._renderCmd.clearStencil(stencilValue);
+ },
+
+ /**
+ * Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES.
+ * @return {Number}
+ */
+ getClearFlags: function () {
+ return this.clearFlags;
+ },
+
+ /**
+ * Set the clearFlags
+ * @param {Number} clearFlags
+ */
+ setClearFlags: function (clearFlags) {
+ this.clearFlags = clearFlags;
+ },
+
+ /**
+ * Clear color value. Valid only when "autoDraw" is true.
+ * @function
+ * @return {cc.Color}
+ */
+ getClearColor: function () {
+ return this._clearColor;
+ },
+
+ /**
+ * Set the clear color value. Valid only when "autoDraw" is true.
+ * @function
+ * @param {cc.Color} clearColor The clear color
+ */
+ setClearColor: function (clearColor) {
+ var locClearColor = this._clearColor;
+ locClearColor.r = clearColor.r;
+ locClearColor.g = clearColor.g;
+ locClearColor.b = clearColor.b;
+ locClearColor.a = clearColor.a;
+ this._renderCmd.updateClearColor(clearColor);
+ },
+
+ /**
+ * Value for clearDepth. Valid only when autoDraw is true.
+ * @return {Number}
+ */
+ getClearDepth: function () {
+ return this.clearDepthVal;
+ },
+
+ /**
+ * Set value for clearDepth. Valid only when autoDraw is true.
+ * @param {Number} clearDepth
+ */
+ setClearDepth: function (clearDepth) {
+ this.clearDepthVal = clearDepth;
+ },
+
+ /**
+ * Value for clear Stencil. Valid only when autoDraw is true
+ * @return {Number}
+ */
+ getClearStencil: function () {
+ return this.clearStencilVal;
+ },
+
+ /**
+ * Set value for clear Stencil. Valid only when autoDraw is true
+ * @return {Number}
+ */
+ setClearStencil: function (clearStencil) {
+ this.clearStencilVal = clearStencil;
+ },
+
+ /**
+ * When enabled, it will render its children into the texture automatically. Disabled by default for compatibility reasons.
+ * Will be enabled in the future.
+ * @return {Boolean}
+ */
+ isAutoDraw: function () {
+ return this.autoDraw;
+ },
+
+ /**
+ * When enabled, it will render its children into the texture automatically. Disabled by default for compatibility reasons.
+ * Will be enabled in the future.
+ * @return {Boolean}
+ */
+ setAutoDraw: function (autoDraw) {
+ this.autoDraw = autoDraw;
+ },
+
+ //---- some stub functions for jsb
+ /**
+ * saves the texture into a file using JPEG format. The file will be saved in the Documents folder.
+ * Returns YES if the operation is successful.
+ * (doesn't support in HTML5)
+ * @param {Number} filePath
+ * @param {Number} format
+ */
+ saveToFile: function (filePath, format) {
+ cc.log("saveToFile isn't supported on Cocos2d-Html5");
+ },
+
+ /**
+ * creates a new CCImage from with the texture's data. Caller is responsible for releasing it by calling delete.
+ * @return {*}
+ */
+ newCCImage: function (flipImage) {
+ cc.log("saveToFile isn't supported on cocos2d-html5");
+ return null;
+ },
+
+ /**
+ * Listen "come to background" message, and save render texture. It only has effect on Android.
+ * @param {cc.Class} obj
+ */
+ listenToBackground: function (obj) {
+ },
+
+ /**
+ * Listen "come to foreground" message and restore the frame buffer object. It only has effect on Android.
+ * @param {cc.Class} obj
+ */
+ listenToForeground: function (obj) {
+ }
+});
+
+var _p = cc.RenderTexture.prototype;
+// Extended
+/** @expose */
+_p.clearColorVal;
+cc.defineGetterSetter(_p, "clearColorVal", _p.getClearColor, _p.setClearColor);
+
+
+/**
+ * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid
+ * @deprecated since v3.0 please use new cc.RenderTexture() instead.
+ * @param {Number} width
+ * @param {Number} height
+ * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
+ * @param {Number} depthStencilFormat
+ * @return {cc.RenderTexture}
+ */
+cc.RenderTexture.create = function (width, height, format, depthStencilFormat) {
+ return new cc.RenderTexture(width, height, format, depthStencilFormat);
+};
diff --git a/cocos2d/render-texture/CCRenderTextureCanvasRenderCmd.js b/cocos2d/render-texture/CCRenderTextureCanvasRenderCmd.js
new file mode 100644
index 0000000000..c55f9e7ad1
--- /dev/null
+++ b/cocos2d/render-texture/CCRenderTextureCanvasRenderCmd.js
@@ -0,0 +1,105 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.RenderTexture.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = false;
+ this._clearColorStr = "rgba(255,255,255,1)";
+
+ this._cacheCanvas = document.createElement('canvas');
+ this._cacheContext = new cc.CanvasContextWrapper(this._cacheCanvas.getContext('2d'));
+ };
+
+ var proto = cc.RenderTexture.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.RenderTexture.CanvasRenderCmd;
+
+ proto.cleanup = function () {
+ this._cacheContext = null;
+ this._cacheCanvas = null;
+ };
+
+ proto.clearStencil = function (stencilValue) {
+ };
+
+ proto.setVirtualViewport = function (rtBegin, fullRect, fullViewport) {
+ };
+
+ proto.updateClearColor = function (clearColor) {
+ this._clearColorStr = "rgba(" + (0 | clearColor.r) + "," + (0 | clearColor.g) + "," + (0 | clearColor.b) + "," + clearColor.a / 255 + ")";
+ };
+
+ proto.initWithWidthAndHeight = function (width, height, format, depthStencilFormat) {
+ var node = this._node;
+ var locCacheCanvas = this._cacheCanvas, locScaleFactor = cc.contentScaleFactor();
+ locCacheCanvas.width = 0 | (width * locScaleFactor);
+ locCacheCanvas.height = 0 | (height * locScaleFactor);
+
+ var texture = new cc.Texture2D();
+ texture.initWithElement(locCacheCanvas);
+ texture.handleLoadedTexture();
+
+ var locSprite = node.sprite = new cc.Sprite(texture);
+ locSprite.setBlendFunc(cc.ONE, cc.ONE_MINUS_SRC_ALPHA);
+ // Disabled by default.
+ node.autoDraw = false;
+ // add sprite for backward compatibility
+ node.addChild(locSprite);
+ return true;
+ };
+
+ proto.begin = function () {
+ };
+
+ proto._beginWithClear = function (r, g, b, a, depthValue, stencilValue, flags) {
+ r = r || 0;
+ g = g || 0;
+ b = b || 0;
+ a = isNaN(a) ? 255 : a;
+
+ var context = this._cacheContext.getContext();
+ var locCanvas = this._cacheCanvas;
+ context.setTransform(1, 0, 0, 1, 0, 0);
+ this._cacheContext.setFillStyle("rgba(" + (0 | r) + "," + (0 | g) + "," + (0 | b) + "," + a / 255 + ")");
+ context.clearRect(0, 0, locCanvas.width, locCanvas.height);
+ context.fillRect(0, 0, locCanvas.width, locCanvas.height);
+ };
+
+ proto.end = function () {
+ var node = this._node;
+
+ var scale = cc.contentScaleFactor();
+ cc.renderer._renderingToCacheCanvas(this._cacheContext, node.__instanceId, scale, scale);
+ var spriteRenderCmd = node.sprite._renderCmd;
+ spriteRenderCmd._notifyRegionStatus && spriteRenderCmd._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.Dirty);
+ };
+
+ proto.clearRect = function (x, y, width, height) {
+ this._cacheContext.clearRect(x, y, width, -height);
+ };
+
+ proto.clearDepth = function (depthValue) {
+ cc.log("clearDepth isn't supported on Cocos2d-Html5");
+ };
+})();
diff --git a/cocos2d/render-texture/CCRenderTextureWebGLRenderCmd.js b/cocos2d/render-texture/CCRenderTextureWebGLRenderCmd.js
new file mode 100644
index 0000000000..9abe91feaf
--- /dev/null
+++ b/cocos2d/render-texture/CCRenderTextureWebGLRenderCmd.js
@@ -0,0 +1,366 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.RenderTexture.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+
+ this._fBO = null;
+ this._oldFBO = null;
+ this._textureCopy = null;
+ this._depthRenderBuffer = null;
+
+ this._rtTextureRect = new cc.Rect();
+ this._fullRect = new cc.Rect();
+ this._fullViewport = new cc.Rect();
+ };
+
+ var proto = cc.RenderTexture.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.RenderTexture.WebGLRenderCmd;
+
+ proto.setVirtualViewport = function (rtBegin, fullRect, fullViewport) {
+ this._rtTextureRect.x = rtBegin.x;
+ this._rtTextureRect.y = rtBegin.y;
+
+ this._fullRect = fullRect;
+ this._fullViewport = fullViewport;
+ };
+
+ proto.needDraw = function () {
+ return this._needDraw && this._node.autoDraw;
+ };
+
+ proto.rendering = function (ctx) {
+ var gl = ctx || cc._renderContext;
+ var node = this._node;
+ if (node.autoDraw) {
+ node.begin();
+
+ var locClearFlags = node.clearFlags;
+ if (locClearFlags) {
+ var oldClearColor = [0.0, 0.0, 0.0, 0.0];
+ var oldDepthClearValue = 0.0;
+ var oldStencilClearValue = 0;
+
+ // backup and set
+ if (locClearFlags & gl.COLOR_BUFFER_BIT) {
+ oldClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ gl.clearColor(node._clearColor.r / 255, node._clearColor.g / 255, node._clearColor.b / 255, node._clearColor.a / 255);
+ }
+
+ if (locClearFlags & gl.DEPTH_BUFFER_BIT) {
+ oldDepthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
+ gl.clearDepth(node.clearDepthVal);
+ }
+
+ if (locClearFlags & gl.STENCIL_BUFFER_BIT) {
+ oldStencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
+ gl.clearStencil(node.clearStencilVal);
+ }
+
+ // clear
+ gl.clear(locClearFlags);
+
+ // restore
+ if (locClearFlags & gl.COLOR_BUFFER_BIT)
+ gl.clearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]);
+
+ if (locClearFlags & gl.DEPTH_BUFFER_BIT)
+ gl.clearDepth(oldDepthClearValue);
+
+ if (locClearFlags & gl.STENCIL_BUFFER_BIT)
+ gl.clearStencil(oldStencilClearValue);
+ }
+
+ //! make sure all children are drawn
+ node.sortAllChildren();
+ var locChildren = node._children;
+ for (var i = 0; i < locChildren.length; i++) {
+ var getChild = locChildren[i];
+ if (getChild !== node.sprite) {
+ getChild.visit(node.sprite); //TODO it's very Strange
+ }
+ }
+ node.end();
+ }
+ };
+
+ proto.clearStencil = function (stencilValue) {
+ var gl = cc._renderContext;
+ // save old stencil value
+ var stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
+
+ gl.clearStencil(stencilValue);
+ gl.clear(gl.STENCIL_BUFFER_BIT);
+
+ // restore clear color
+ gl.clearStencil(stencilClearValue);
+ };
+
+ proto.cleanup = function () {
+ var node = this._node;
+ //node.sprite = null;
+ this._textureCopy = null;
+
+ var gl = cc._renderContext;
+ gl.deleteFramebuffer(this._fBO);
+ if (this._depthRenderBuffer)
+ gl.deleteRenderbuffer(this._depthRenderBuffer);
+ };
+
+ proto.updateClearColor = function (clearColor) {
+ };
+
+ proto.initWithWidthAndHeight = function (width, height, format, depthStencilFormat) {
+ var node = this._node;
+ if (format === cc.Texture2D.PIXEL_FORMAT_A8)
+ cc.log("cc.RenderTexture._initWithWidthAndHeightForWebGL() : only RGB and RGBA formats are valid for a render texture;");
+
+ var gl = cc._renderContext, locScaleFactor = cc.contentScaleFactor();
+ this._fullRect = new cc.Rect(0, 0, width, height);
+ this._fullViewport = new cc.Rect(0, 0, width, height);
+
+ width = 0 | (width * locScaleFactor);
+ height = 0 | (height * locScaleFactor);
+
+ this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
+
+ // textures must be power of two squared
+ var powW, powH;
+
+ if (cc.configuration.supportsNPOT()) {
+ powW = width;
+ powH = height;
+ } else {
+ powW = cc.NextPOT(width);
+ powH = cc.NextPOT(height);
+ }
+
+ //void *data = malloc(powW * powH * 4);
+ var dataLen = powW * powH * 4;
+ var data = new Uint8Array(dataLen);
+ //memset(data, 0, (int)(powW * powH * 4));
+ for (var i = 0; i < powW * powH * 4; i++)
+ data[i] = 0;
+
+ this._pixelFormat = format;
+
+ var locTexture = node._texture = new cc.Texture2D();
+ if (!node._texture)
+ return false;
+
+ locTexture.initWithData(data, node._pixelFormat, powW, powH, cc.size(width, height));
+ //free( data );
+
+ var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING);
+
+ if (cc.configuration.checkForGLExtension("GL_QCOM")) {
+ this._textureCopy = new cc.Texture2D();
+ if (!this._textureCopy)
+ return false;
+ this._textureCopy.initWithData(data, node._pixelFormat, powW, powH, cc.size(width, height));
+ }
+
+ // generate FBO
+ this._fBO = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);
+
+ // associate texture with FBO
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, locTexture._webTextureObj, 0);
+
+ if (depthStencilFormat !== 0) {
+ //create and attach depth buffer
+ this._depthRenderBuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderBuffer);
+ gl.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, powW, powH);
+ if (depthStencilFormat === gl.DEPTH_STENCIL)
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
+ else if (depthStencilFormat === gl.STENCIL_INDEX || depthStencilFormat === gl.STENCIL_INDEX8)
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
+ else if (depthStencilFormat === gl.DEPTH_COMPONENT16)
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
+ }
+
+ // check if it worked (probably worth doing :) )
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE)
+ cc.log("Could not attach texture to the framebuffer");
+
+ locTexture.setAliasTexParameters();
+
+ var locSprite = node.sprite = new cc.Sprite(locTexture);
+ locSprite.scaleY = -1;
+ locSprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
+
+ gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
+
+ // Disabled by default.
+ node.autoDraw = false;
+
+ // add sprite for backward compatibility
+ node.addChild(locSprite);
+ return true;
+ };
+
+ proto.begin = function () {
+ var node = this._node;
+ // Save the current matrix
+ cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
+ cc.kmGLPushMatrix();
+ cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
+ cc.kmGLPushMatrix();
+
+ var gl = cc._renderContext;
+
+ var director = cc.director;
+ director.setProjection(director.getProjection());
+
+ var texSize = node._texture.getContentSizeInPixels();
+
+ // Calculate the adjustment ratios based on the old and new projections
+ var size = cc.director.getWinSizeInPixels();
+ var widthRatio = size.width / texSize.width;
+ var heightRatio = size.height / texSize.height;
+
+ var orthoMatrix = cc.math.Matrix4.createOrthographicProjection(-1.0 / widthRatio, 1.0 / widthRatio,
+ -1.0 / heightRatio, 1.0 / heightRatio, -1, 1);
+ cc.kmGLMultMatrix(orthoMatrix);
+
+ //calculate viewport
+ var viewport = new cc.Rect(0, 0, 0, 0);
+ viewport.width = this._fullViewport.width;
+ viewport.height = this._fullViewport.height;
+ var viewPortRectWidthRatio = viewport.width / this._fullRect.width;
+ var viewPortRectHeightRatio = viewport.height / this._fullRect.height;
+ viewport.x = (this._fullRect.x - this._rtTextureRect.x) * viewPortRectWidthRatio;
+ viewport.y = (this._fullRect.y - this._rtTextureRect.y) * viewPortRectHeightRatio;
+ gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+ this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);//Will direct drawing to the frame buffer created above
+
+ /* Certain Qualcomm Adreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture.
+ * The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture.
+ * Create a temporary texture to overcome this. At the end of CCRenderTexture::begin(), switch the attached texture to the second one, call glClear,
+ * and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers.
+ */
+ if (cc.configuration.checkForGLExtension("GL_QCOM")) {
+ // -- bind a temporary texture so we can clear the render buffer without losing our texture
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._textureCopy._webTextureObj, 0);
+ //cc.checkGLErrorDebug();
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, node._texture._webTextureObj, 0);
+ }
+ };
+
+ proto._beginWithClear = function (r, g, b, a, depthValue, stencilValue, flags) {
+ r = r / 255;
+ g = g / 255;
+ b = b / 255;
+ a = a / 255;
+
+ var gl = cc._renderContext;
+
+ // save clear color
+ var clearColor = [0.0, 0.0, 0.0, 0.0];
+ var depthClearValue = 0.0;
+ var stencilClearValue = 0;
+
+ if (flags & gl.COLOR_BUFFER_BIT) {
+ clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ gl.clearColor(r, g, b, a);
+ }
+
+ if (flags & gl.DEPTH_BUFFER_BIT) {
+ depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
+ gl.clearDepth(depthValue);
+ }
+
+ if (flags & gl.STENCIL_BUFFER_BIT) {
+ stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
+ gl.clearStencil(stencilValue);
+ }
+
+ gl.clear(flags);
+
+ // restore
+ if (flags & gl.COLOR_BUFFER_BIT)
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+
+ if (flags & gl.DEPTH_BUFFER_BIT)
+ gl.clearDepth(depthClearValue);
+
+ if (flags & gl.STENCIL_BUFFER_BIT)
+ gl.clearStencil(stencilClearValue);
+ };
+
+ proto.end = function () {
+ var node = this._node;
+ cc.renderer._renderingToBuffer(node.__instanceId);
+
+ var gl = cc._renderContext;
+ var director = cc.director;
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
+
+ //restore viewport
+ director.setViewport();
+ cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
+ cc.kmGLPopMatrix();
+ cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
+ cc.kmGLPopMatrix();
+
+ /* var size = director.getWinSizeInPixels();
+
+ // restore viewport
+ gl.viewport(0, 0, size.width * cc.contentScaleFactor(), size.height * cc.contentScaleFactor());
+
+ // special viewport for 3d projection + retina display
+ if (director.getProjection() == cc.Director.PROJECTION_3D && cc.contentScaleFactor() != 1) {
+ gl.viewport((-size.width / 2), (-size.height / 2), (size.width * cc.contentScaleFactor()), (size.height * cc.contentScaleFactor()));
+ }
+
+ director.setProjection(director.getProjection());*/
+ };
+
+ proto.clearRect = function (x, y, width, height) {
+ //TODO need to implement
+ };
+
+ proto.clearDepth = function (depthValue) {
+ var node = this._node;
+ node.begin();
+
+ var gl = cc._renderContext;
+ //! save old depth value
+ var depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
+
+ gl.clearDepth(depthValue);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ // restore clear color
+ gl.clearDepth(depthClearValue);
+ node.end();
+ };
+})();
diff --git a/cocos2d/shaders/CCGLProgram.js b/cocos2d/shaders/CCGLProgram.js
index d34ff3b16e..0cf9f4702d 100644
--- a/cocos2d/shaders/CCGLProgram.js
+++ b/cocos2d/shaders/CCGLProgram.js
@@ -1,9 +1,9 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright 2011 Jeff Lamarche
Copyright 2012 Goffredo Marocchi
- Copyright (c) 2011 Zynga Inc.
http://www.cocos2d-x.org
@@ -26,193 +26,12 @@
THE SOFTWARE.
****************************************************************************/
-//-------------Vertex Attributes-----------
/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_POSITION = 0;
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_COLOR = 1;
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_TEX_COORDS = 2;
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_MAX = 3;
-
-//------------Uniforms------------------
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_PMATRIX = 0;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_MVMATRIX = 1;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_MVPMATRIX = 2;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_TIME = 3;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_SINTIME = 4;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_COSTIME = 5;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_RANDOM01 = 6;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_SAMPLER = 7;
-/**
- * @constant
- * @type {Number}
- */
-cc.UNIFORM_MAX = 8;
-
-//------------Shader Name---------------
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_TEXTURECOLOR = "ShaderPositionTextureColor";
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_TEXTURECOLORALPHATEST = "ShaderPositionTextureColorAlphaTest";
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_COLOR = "ShaderPositionColor";
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_TEXTURE = "ShaderPositionTexture";
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_TEXTURE_UCOLOR = "ShaderPositionTexture_uColor";
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_TEXTUREA8COLOR = "ShaderPositionTextureA8Color";
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_UCOLOR = "ShaderPosition_uColor";
-/**
- * @constant
- * @type {String}
- */
-cc.SHADER_POSITION_LENGTHTEXTURECOLOR = "ShaderPositionLengthTextureColor";
-
-//------------uniform names----------------
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_PMATRIX_S = "CC_PMatrix";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_MVMATRIX_S = "CC_MVMatrix";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_MVPMATRIX_S = "CC_MVPMatrix";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_TIME_S = "CC_Time";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_SINTIME_S = "CC_SinTime";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_COSTIME_S = "CC_CosTime";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_RANDOM01_S = "CC_Random01";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_SAMPLER_S = "CC_Texture0";
-/**
- * @constant
- * @type {String}
- */
-cc.UNIFORM_ALPHA_TEST_VALUE_S = "CC_alpha_value";
-
-//------------Attribute names--------------
-/**
- * @constant
- * @type {String}
- */
-cc.ATTRIBUTE_NAME_COLOR = "a_color";
-/**
- * @constant
- * @type {String}
- */
-cc.ATTRIBUTE_NAME_POSITION = "a_position";
-/**
- * @constant
- * @type {String}
- */
-cc.ATTRIBUTE_NAME_TEX_COORD = "a_texCoord";
-
-cc.HashUniformEntry = function (value, location, hh) {
- this.value = value;
- this.location = location;
- this.hh = hh || {};
-};
-
-/**
- * Class that implements a glProgram
+ * Class that implements a WebGL program
* @class
* @extends cc.Class
*/
-cc.GLProgram = cc.Class.extend({
+cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{
_glContext: null,
_programObj: null,
_vertShader: null,
@@ -220,30 +39,36 @@ cc.GLProgram = cc.Class.extend({
_uniforms: null,
_hashForUniforms: null,
_usesTime: false,
+ _projectionUpdated: -1,
// Uniform cache
- _updateUniformLocation: function (location, data, bytes) {
- if (location == null)
+ _updateUniform: function (name) {
+ if (!name)
return false;
- var updated = true;
- var element = null;
- for (var i = 0; i < this._hashForUniforms.length; i++)
- if (this._hashForUniforms[i].location == location)
- element = this._hashForUniforms[i];
-
- if (!element) {
- element = new cc.HashUniformEntry();
- // key
- element.location = location;
- // value
- element.value = data;
- this._hashForUniforms.push(element);
+ var updated = false;
+ var element = this._hashForUniforms[name];
+ var args;
+ if (Array.isArray(arguments[1])) {
+ args = arguments[1];
} else {
- if (element.value == data)
- updated = false;
- else
- element.value = data;
+ args = new Array(arguments.length - 1);
+ for (var i = 1; i < arguments.length; i += 1) {
+ args[i - 1] = arguments[i];
+ }
+ }
+
+ if (!element || element.length !== args.length) {
+ this._hashForUniforms[name] = [].concat(args);
+ updated = true;
+ } else {
+ for (var i = 0; i < args.length; i += 1) {
+ // Array and Typed Array inner values could be changed, so we must update them
+ if (args[i] !== element[i] || typeof args[i] === 'object') {
+ element[i] = args[i];
+ updated = true;
+ }
+ }
}
return updated;
@@ -258,8 +83,7 @@ cc.GLProgram = cc.Class.extend({
if (!source || !shader)
return false;
- var preStr = (type == this._glContext.VERTEX_SHADER) ? "precision highp float;\n" : "precision mediump float;\n";
-
+ var preStr = cc.GLProgram._isHighpSupported() ? "precision highp float;\n" : "precision mediump float;\n";
source = preStr
+ "uniform mat4 CC_PMatrix; \n"
+ "uniform mat4 CC_MVMatrix; \n"
@@ -268,7 +92,8 @@ cc.GLProgram = cc.Class.extend({
+ "uniform vec4 CC_SinTime; \n"
+ "uniform vec4 CC_CosTime; \n"
+ "uniform vec4 CC_Random01; \n"
- + "//CC INCLUDES END \n \n" + source;
+ + "uniform sampler2D CC_Texture0; \n"
+ + "//CC INCLUDES END \n" + source;
this._glContext.shaderSource(shader, source);
this._glContext.compileShader(shader);
@@ -276,23 +101,31 @@ cc.GLProgram = cc.Class.extend({
if (!status) {
cc.log("cocos2d: ERROR: Failed to compile shader:\n" + this._glContext.getShaderSource(shader));
- if (type == this._glContext.VERTEX_SHADER)
+ if (type === this._glContext.VERTEX_SHADER)
cc.log("cocos2d: \n" + this.vertexShaderLog());
else
cc.log("cocos2d: \n" + this.fragmentShaderLog());
}
- return ( status == 1 );
+ return ( status === true );
},
- ctor: function (glContext) {
- this._programObj = null;
- this._vertShader = null;
- this._fragShader = null;
- this._uniforms = [];
- this._hashForUniforms = [];
- this._glContext = glContext || cc.renderContext;
+ /**
+ * Create a cc.GLProgram object
+ * @param {String} vShaderFileName
+ * @param {String} fShaderFileName
+ * @returns {cc.GLProgram}
+ */
+ ctor: function (vShaderFileName, fShaderFileName, glContext) {
+ this._uniforms = {};
+ this._hashForUniforms = {};
+ this._glContext = glContext || cc._renderContext;
+
+ vShaderFileName && fShaderFileName && this.init(vShaderFileName, fShaderFileName);
},
+ /**
+ * destroy program
+ */
destroyProgram: function () {
this._vertShader = null;
this._fragShader = null;
@@ -309,36 +142,38 @@ cc.GLProgram = cc.Class.extend({
* @return {Boolean}
*/
initWithVertexShaderByteArray: function (vertShaderStr, fragShaderStr) {
- this._programObj = cc.renderContext.createProgram();
- //cc.CHECK_GL_ERROR_DEBUG();
+ var locGL = this._glContext;
+ this._programObj = locGL.createProgram();
+ //cc.checkGLErrorDebug();
this._vertShader = null;
this._fragShader = null;
if (vertShaderStr) {
- this._vertShader = this._glContext.createShader(this._glContext.VERTEX_SHADER);
- if (!this._compileShader(this._vertShader, this._glContext.VERTEX_SHADER, vertShaderStr)) {
+ this._vertShader = locGL.createShader(locGL.VERTEX_SHADER);
+ if (!this._compileShader(this._vertShader, locGL.VERTEX_SHADER, vertShaderStr)) {
cc.log("cocos2d: ERROR: Failed to compile vertex shader");
}
}
// Create and compile fragment shader
if (fragShaderStr) {
- this._fragShader = this._glContext.createShader(this._glContext.FRAGMENT_SHADER);
- if (!this._compileShader(this._fragShader, this._glContext.FRAGMENT_SHADER, fragShaderStr)) {
+ this._fragShader = locGL.createShader(locGL.FRAGMENT_SHADER);
+ if (!this._compileShader(this._fragShader, locGL.FRAGMENT_SHADER, fragShaderStr)) {
cc.log("cocos2d: ERROR: Failed to compile fragment shader");
}
}
if (this._vertShader)
- this._glContext.attachShader(this._programObj, this._vertShader);
- cc.CHECK_GL_ERROR_DEBUG();
+ locGL.attachShader(this._programObj, this._vertShader);
+ cc.checkGLErrorDebug();
if (this._fragShader)
- this._glContext.attachShader(this._programObj, this._fragShader);
- this._hashForUniforms = [];
+ locGL.attachShader(this._programObj, this._fragShader);
+
+ if (Object.keys(this._hashForUniforms).length > 0) this._hashForUniforms = {};
- cc.CHECK_GL_ERROR_DEBUG();
+ cc.checkGLErrorDebug();
return true;
},
@@ -359,9 +194,10 @@ cc.GLProgram = cc.Class.extend({
* @return {Boolean}
*/
initWithVertexShaderFilename: function (vShaderFilename, fShaderFileName) {
- var fileUtils = cc.FileUtils.getInstance();
- var vertexSource = fileUtils.getTextFileData(fileUtils.fullPathForFilename(vShaderFilename));
- var fragmentSource = fileUtils.getTextFileData(fileUtils.fullPathForFilename(fShaderFileName));
+ var vertexSource = cc.loader.getRes(vShaderFilename);
+ if (!vertexSource) throw new Error("Please load the resource firset : " + vShaderFilename);
+ var fragmentSource = cc.loader.getRes(fShaderFileName);
+ if (!fragmentSource) throw new Error("Please load the resource firset : " + fShaderFileName);
return this.initWithVertexShaderByteArray(vertexSource, fragmentSource);
},
@@ -389,7 +225,10 @@ cc.GLProgram = cc.Class.extend({
* @return {Boolean}
*/
link: function () {
- cc.Assert(this._programObj != null, "Cannot link invalid program");
+ if (!this._programObj) {
+ cc.log("cc.GLProgram.link(): Cannot link invalid program");
+ return false;
+ }
this._glContext.linkProgram(this._programObj);
@@ -401,10 +240,10 @@ cc.GLProgram = cc.Class.extend({
this._vertShader = null;
this._fragShader = null;
- if (cc.COCOS2D_DEBUG) {
+ if (cc.game.config[cc.game.CONFIG_KEY.debugMode]) {
var status = this._glContext.getProgramParameter(this._programObj, this._glContext.LINK_STATUS);
if (!status) {
- cc.log("cocos2d: ERROR: Failed to link program: " + this._programObj);
+ cc.log("cocos2d: ERROR: Failed to link program: " + this._glContext.getProgramInfoLog(this._programObj));
cc.glDeleteProgram(this._programObj);
this._programObj = null;
return false;
@@ -429,21 +268,26 @@ cc.GLProgram = cc.Class.extend({
* cc.UNIFORM_SAMPLER
*/
updateUniforms: function () {
- this._uniforms[cc.UNIFORM_PMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_PMATRIX_S);
- this._uniforms[cc.UNIFORM_MVMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVMATRIX_S);
- this._uniforms[cc.UNIFORM_MVPMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVPMATRIX_S);
- this._uniforms[cc.UNIFORM_TIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_TIME_S);
- this._uniforms[cc.UNIFORM_SINTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SINTIME_S);
- this._uniforms[cc.UNIFORM_COSTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_COSTIME_S);
-
- this._usesTime = (this._uniforms[cc.UNIFORM_TIME] != null || this._uniforms[cc.UNIFORM_SINTIME] != null || this._uniforms[cc.UNIFORM_COSTIME] != null);
-
- this._uniforms[cc.UNIFORM_RANDOM01] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_RANDOM01_S);
- this._uniforms[cc.UNIFORM_SAMPLER] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SAMPLER_S);
+ this._addUniformLocation(cc.UNIFORM_PMATRIX_S);
+ this._addUniformLocation(cc.UNIFORM_MVMATRIX_S);
+ this._addUniformLocation(cc.UNIFORM_MVPMATRIX_S);
+ this._addUniformLocation(cc.UNIFORM_TIME_S);
+ this._addUniformLocation(cc.UNIFORM_SINTIME_S);
+ this._addUniformLocation(cc.UNIFORM_COSTIME_S);
+ this._addUniformLocation(cc.UNIFORM_RANDOM01_S);
+ this._addUniformLocation(cc.UNIFORM_SAMPLER_S);
+ this._usesTime = (this._uniforms[cc.UNIFORM_TIME_S] != null || this._uniforms[cc.UNIFORM_SINTIME_S] != null || this._uniforms[cc.UNIFORM_COSTIME_S] != null);
this.use();
// Since sample most probably won't change, set it to 0 now.
- this.setUniformLocationWith1i(this._uniforms[cc.UNIFORM_SAMPLER], 0);
+ this.setUniformLocationWith1i(this._uniforms[cc.UNIFORM_SAMPLER_S], 0);
+ },
+
+ _addUniformLocation: function (name) {
+ var location = this._glContext.getUniformLocation(this._programObj, name);
+ if (location) location._name = name;
+ this._uniforms[name] = location;
+ return location;
},
/**
@@ -451,224 +295,360 @@ cc.GLProgram = cc.Class.extend({
* @param {String} name
* @returns {Number}
*/
- getUniformLocationForName:function(name){
- cc.Assert(name != null, "Invalid uniform name" );
- cc.Assert(this._programObj != 0, "Invalid operation. Cannot get uniform location when program is not initialized");
+ getUniformLocationForName: function (name) {
+ if (!name)
+ throw new Error("cc.GLProgram.getUniformLocationForName(): uniform name should be non-null");
+ if (!this._programObj)
+ throw new Error("cc.GLProgram.getUniformLocationForName(): Invalid operation. Cannot get uniform location when program is not initialized");
- return this._glContext.getUniformLocation(this._programObj, name);
+ var location = this._uniforms[name] || this._addUniformLocation(name);
+ return location;
},
+ /**
+ * get uniform MVP matrix
+ * @returns {WebGLUniformLocation}
+ */
getUniformMVPMatrix: function () {
- return this._uniforms[cc.UNIFORM_MVPMATRIX];
+ return this._uniforms[cc.UNIFORM_MVPMATRIX_S];
},
+ /**
+ * get uniform sampler
+ * @returns {WebGLUniformLocation}
+ */
getUniformSampler: function () {
- return this._uniforms[cc.UNIFORM_SAMPLER];
+ return this._uniforms[cc.UNIFORM_SAMPLER_S];
},
/**
* calls glUniform1i only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} i1
*/
setUniformLocationWith1i: function (location, i1) {
- var updated = this._updateUniformLocation(location, i1);
- if (updated)
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, i1)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform1i(location, i1);
+ }
+ } else {
this._glContext.uniform1i(location, i1);
+ }
},
/**
* calls glUniform2i only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} i1
* @param {Number} i2
*/
- setUniformLocationWith2i:function(location, i1,i2){
- var intArray= [i1,i2];
- var updated = this._updateUniformLocation(location, intArray);
-
- if( updated )
+ setUniformLocationWith2i: function (location, i1, i2) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, i1, i2)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform2i(location, i1, i2);
+ }
+ } else {
this._glContext.uniform2i(location, i1, i2);
+ }
},
/**
* calls glUniform3i only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} i1
* @param {Number} i2
* @param {Number} i3
*/
- setUniformLocationWith3i:function(location, i1, i2, i3){
- var intArray = [i1,i2,i3];
- var updated = this._updateUniformLocation(location, intArray);
-
- if( updated )
+ setUniformLocationWith3i: function (location, i1, i2, i3) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, i1, i2, i3)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform3i(location, i1, i2, i3);
+ }
+ } else {
this._glContext.uniform3i(location, i1, i2, i3);
+ }
},
/**
* calls glUniform4i only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} i1
* @param {Number} i2
* @param {Number} i3
* @param {Number} i4
*/
- setUniformLocationWith4i:function(location, i1, i2, i3, i4){
- var intArray = [i1,i2,i3,i4];
- var updated = this._updateUniformLocation(location, intArray);
-
- if( updated )
+ setUniformLocationWith4i: function (location, i1, i2, i3, i4) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, i1, i2, i3, i4)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform4i(location, i1, i2, i3, i4);
+ }
+ } else {
this._glContext.uniform4i(location, i1, i2, i3, i4);
+ }
},
/**
- * calls glUniform2iv only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * calls glUniform2iv
+ * @param {WebGLUniformLocation|String} location
* @param {Int32Array} intArray
* @param {Number} numberOfArrays
*/
- setUniformLocationWith2iv:function(location, intArray, numberOfArrays){
- var updated = this._updateUniformLocation(location, intArray);
-
- if( updated )
+ setUniformLocationWith2iv: function (location, intArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, intArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform2iv(location, intArray);
+ }
+ } else {
this._glContext.uniform2iv(location, intArray);
+ }
},
/**
- * calls glUniform3iv only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * calls glUniform3iv
+ * @param {WebGLUniformLocation|String} location
* @param {Int32Array} intArray
- * @param {Number} numberOfArrays
*/
- setUniformLocationWith3iv:function(location, intArray, numberOfArrays){
- var updated = this._updateUniformLocation(location, intArray);
-
- if( updated )
+ setUniformLocationWith3iv: function (location, intArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, intArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform3iv(location, intArray);
+ }
+ } else {
this._glContext.uniform3iv(location, intArray);
+ }
},
/**
- * calls glUniform4iv only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * calls glUniform4iv
+ * @param {WebGLUniformLocation|String} location
* @param {Int32Array} intArray
- * @param {Number} numberOfArrays
*/
- setUniformLocationWith4iv:function(location, intArray, numberOfArrays){
- var updated = this._updateUniformLocation(location, intArray);
-
- if( updated )
+ setUniformLocationWith4iv: function (location, intArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, intArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform4iv(location, intArray);
+ }
+ } else {
this._glContext.uniform4iv(location, intArray);
+ }
},
/**
* calls glUniform1i only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} i1
*/
setUniformLocationI32: function (location, i1) {
- this.setUniformLocationWith1i(arguments[0], arguments[1]);
+ this.setUniformLocationWith1i(location, i1);
},
/**
* calls glUniform1f only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} f1
*/
setUniformLocationWith1f: function (location, f1) {
- var updated = this._updateUniformLocation(location, f1);
- if (updated)
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, f1)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform1f(location, f1);
+ }
+ } else {
this._glContext.uniform1f(location, f1);
+ }
},
/**
* calls glUniform2f only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} f1
* @param {Number} f2
*/
setUniformLocationWith2f: function (location, f1, f2) {
- var floats = [f1, f2];
- var updated = this._updateUniformLocation(location, floats);
- if (updated)
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, f1, f2)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform2f(location, f1, f2);
+ }
+ } else {
this._glContext.uniform2f(location, f1, f2);
+ }
},
/**
* calls glUniform3f only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} f1
* @param {Number} f2
* @param {Number} f3
*/
setUniformLocationWith3f: function (location, f1, f2, f3) {
- var floats = [f1, f2, f3];
- var updated = this._updateUniformLocation(location, floats);
- if (updated)
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, f1, f2, f3)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform3f(location, f1, f2, f3);
+ }
+ } else {
this._glContext.uniform3f(location, f1, f2, f3);
+ }
},
/**
* calls glUniform4f only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * @param {WebGLUniformLocation|String} location
* @param {Number} f1
* @param {Number} f2
* @param {Number} f3
* @param {Number} f4
*/
setUniformLocationWith4f: function (location, f1, f2, f3, f4) {
- var floats = [f1, f2, f3, f4];
- var updated = this._updateUniformLocation(location, floats);
- if (updated)
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, f1, f2, f3, f4)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform4f(location, f1, f2, f3, f4);
+ }
+ } else {
this._glContext.uniform4f(location, f1, f2, f3, f4);
+ cc.log('uniform4f', f1, f2, f3, f4);
+ }
},
/**
- * calls glUniform2fv only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * calls glUniform2fv
+ * @param {WebGLUniformLocation|String} location
* @param {Float32Array} floatArray
- * @param {Number} numberOfArrays
*/
- setUniformLocationWith2fv: function (location, floatArray, numberOfArrays) {
- var updated = this._updateUniformLocation(location, floatArray);
- if (updated)
+ setUniformLocationWith2fv: function (location, floatArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, floatArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform2fv(location, floatArray);
+ }
+ } else {
this._glContext.uniform2fv(location, floatArray);
+ }
},
/**
- * calls glUniform3fv only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * calls glUniform3fv
+ * @param {WebGLUniformLocation|String} location
* @param {Float32Array} floatArray
- * @param {Number} numberOfArrays
*/
- setUniformLocationWith3fv: function (location, floatArray, numberOfArrays) {
- var updated = this._updateUniformLocation(location, floatArray);
- if (updated)
+ setUniformLocationWith3fv: function (location, floatArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, floatArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform3fv(location, floatArray);
+ }
+ } else {
this._glContext.uniform3fv(location, floatArray);
+ }
},
/**
- * calls glUniform4fv only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * calls glUniform4fv
+ * @param {WebGLUniformLocation|String} location
* @param {Float32Array} floatArray
- * @param {Number} numberOfArrays
*/
- setUniformLocationWith4fv: function (location, floatArray, numberOfArrays) {
- var updated = this._updateUniformLocation(location, floatArray);
- if (updated)
+ setUniformLocationWith4fv: function (location, floatArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, floatArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniform4fv(location, floatArray);
+ }
+ } else {
this._glContext.uniform4fv(location, floatArray);
+ cc.log('uniform4fv', floatArray);
+ }
+ },
+
+ /**
+ * calls glUniformMatrix2fv
+ * @param {WebGLUniformLocation|String} location
+ * @param {Float32Array} matrixArray
+ */
+ setUniformLocationWithMatrix2fv: function (location, matrixArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, matrixArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniformMatrix2fv(location, false, matrixArray);
+ }
+ } else {
+ this._glContext.uniformMatrix2fv(location, false, matrixArray);
+ }
+ },
+
+ /**
+ * calls glUniformMatrix3fv
+ * @param {WebGLUniformLocation|String} location
+ * @param {Float32Array} matrixArray
+ */
+ setUniformLocationWithMatrix3fv: function (location, matrixArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, matrixArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniformMatrix3fv(location, false, matrixArray);
+ }
+ } else {
+ this._glContext.uniformMatrix3fv(location, false, matrixArray);
+ }
},
/**
- * calls glUniformMatrix4fv only if the values are different than the previous call for this same shader program.
- * @param {WebGLUniformLocation} location
+ * calls glUniformMatrix4fv
+ * @param {WebGLUniformLocation|String} location
* @param {Float32Array} matrixArray
- * @param {Number} numberOfMatrices
*/
- setUniformLocationWithMatrix4fv: function (location, matrixArray, numberOfMatrices) {
- var updated = this._updateUniformLocation(location, matrixArray);
- if (updated)
+ setUniformLocationWithMatrix4fv: function (location, matrixArray) {
+ var isString = typeof location === 'string';
+ var name = isString ? location : location && location._name;
+ if (name) {
+ if (this._updateUniform(name, matrixArray)) {
+ if (isString) location = this.getUniformLocationForName(name);
+ this._glContext.uniformMatrix4fv(location, false, matrixArray);
+ }
+ } else {
this._glContext.uniformMatrix4fv(location, false, matrixArray);
+ }
},
setUniformLocationF32: function () {
@@ -695,53 +675,100 @@ cc.GLProgram = cc.Class.extend({
* will update the builtin uniforms if they are different than the previous call for this same shader program.
*/
setUniformsForBuiltins: function () {
- var matrixP = new cc.kmMat4();
- var matrixMV = new cc.kmMat4();
- var matrixMVP = new cc.kmMat4();
+ var matrixP = new cc.math.Matrix4();
+ var matrixMV = new cc.math.Matrix4();
+ var matrixMVP = new cc.math.Matrix4();
cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, matrixP);
cc.kmGLGetMatrix(cc.KM_GL_MODELVIEW, matrixMV);
cc.kmMat4Multiply(matrixMVP, matrixP, matrixMV);
- this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], matrixP.mat, 1);
- this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], matrixMV.mat, 1);
- this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], matrixMVP.mat, 1);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], matrixP.mat, 1);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], matrixMV.mat, 1);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], matrixMVP.mat, 1);
if (this._usesTime) {
- var director = cc.Director.getInstance();
+ var director = cc.director;
// This doesn't give the most accurate global time value.
// Cocos2D doesn't store a high precision time value, so this will have to do.
// Getting Mach time per frame per shader using time could be extremely expensive.
var time = director.getTotalFrames() * director.getAnimationInterval();
- this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME], time / 10.0, time, time * 2, time * 4);
- this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME], time / 8.0, time / 4.0, time / 2.0, Math.sin(time));
- this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME], time / 8.0, time / 4.0, time / 2.0, Math.cos(time));
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME_S], time / 10.0, time, time * 2, time * 4);
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.sin(time));
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.cos(time));
}
- if (this._uniforms[cc.UNIFORM_RANDOM01] != -1)
- this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01], Math.random(), Math.random(), Math.random(), Math.random());
+ if (this._uniforms[cc.UNIFORM_RANDOM01_S] !== -1)
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01_S], Math.random(), Math.random(), Math.random(), Math.random());
+ },
+
+ _setUniformsForBuiltinsForRenderer: function (node) {
+ if (!node || !node._renderCmd)
+ return;
+
+ var matrixP = new cc.math.Matrix4();
+ //var matrixMV = new cc.kmMat4();
+ var matrixMVP = new cc.math.Matrix4();
+
+ cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, matrixP);
+ //cc.kmGLGetMatrix(cc.KM_GL_MODELVIEW, node._stackMatrix);
+
+ cc.kmMat4Multiply(matrixMVP, matrixP, node._renderCmd._stackMatrix);
+
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], matrixP.mat, 1);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], node._renderCmd._stackMatrix.mat, 1);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], matrixMVP.mat, 1);
+
+ if (this._usesTime) {
+ var director = cc.director;
+ // This doesn't give the most accurate global time value.
+ // Cocos2D doesn't store a high precision time value, so this will have to do.
+ // Getting Mach time per frame per shader using time could be extremely expensive.
+ var time = director.getTotalFrames() * director.getAnimationInterval();
+
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME_S], time / 10.0, time, time * 2, time * 4);
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.sin(time));
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME_S], time / 8.0, time / 4.0, time / 2.0, Math.cos(time));
+ }
+
+ if (this._uniforms[cc.UNIFORM_RANDOM01_S] !== -1)
+ this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01_S], Math.random(), Math.random(), Math.random(), Math.random());
},
/**
* will update the MVP matrix on the MVP uniform if it is different than the previous call for this same shader program.
*/
setUniformForModelViewProjectionMatrix: function () {
- this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false,
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S],
cc.getMat4MultiplyValue(cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top));
},
setUniformForModelViewProjectionMatrixWithMat4: function (swapMat4) {
cc.kmMat4Multiply(swapMat4, cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top);
- this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false, swapMat4.mat);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], swapMat4.mat);
},
setUniformForModelViewAndProjectionMatrixWithMat4: function () {
- this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], false, cc.modelview_matrix_stack.top.mat);
- this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], false, cc.projection_matrix_stack.top.mat);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], cc.modelview_matrix_stack.top.mat);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], cc.projection_matrix_stack.top.mat);
+ },
+
+ _setUniformForMVPMatrixWithMat4: function (modelViewMatrix) {
+ if (!modelViewMatrix)
+ throw new Error("modelView matrix is undefined.");
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], modelViewMatrix.mat);
+ this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], cc.projection_matrix_stack.top.mat);
},
+ _updateProjectionUniform: function () {
+ var stack = cc.projection_matrix_stack;
+ if (stack.lastUpdated !== this._projectionUpdated) {
+ this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], false, stack.top.mat);
+ this._projectionUpdated = stack.lastUpdated;
+ }
+ },
/**
* returns the vertexShader error log
@@ -798,7 +825,7 @@ cc.GLProgram = cc.Class.extend({
reset: function () {
this._vertShader = null;
this._fragShader = null;
- this._uniforms = [];
+ if (Object.keys(this._uniforms).length > 0) this._uniforms = {};
// it is already deallocated by android
//ccGLDeleteProgram(m_uProgram);
@@ -806,12 +833,7 @@ cc.GLProgram = cc.Class.extend({
this._programObj = null;
// Purge uniform hash
- for (var i = 0; i < this._hashForUniforms.length; i++) {
- this._hashForUniforms[i].value = null;
- this._hashForUniforms[i] = null;
- }
-
- this._hashForUniforms = [];
+ if (Object.keys(this._hashForUniforms).length > 0) this._hashForUniforms = {};
},
/**
@@ -823,7 +845,7 @@ cc.GLProgram = cc.Class.extend({
},
/**
- * Currently JavaScript Bindigns (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
+ * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB,
* and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB.
* This is a hack, and should be removed once JSB fixes the retain/release bug
*/
@@ -835,13 +857,46 @@ cc.GLProgram = cc.Class.extend({
/**
* Create a cc.GLProgram object
+ * @deprecated since v3.0, please use new cc.GLProgram(vShaderFileName, fShaderFileName) instead
* @param {String} vShaderFileName
* @param {String} fShaderFileName
* @returns {cc.GLProgram}
*/
cc.GLProgram.create = function (vShaderFileName, fShaderFileName) {
- var program = new cc.GLProgram();
- if (program.init(vShaderFileName, fShaderFileName))
- return program;
- return null;
+ return new cc.GLProgram(vShaderFileName, fShaderFileName);
+};
+
+cc.GLProgram._highpSupported = null;
+
+cc.GLProgram._isHighpSupported = function () {
+ var ctx = cc._renderContext;
+ if (ctx.getShaderPrecisionFormat && cc.GLProgram._highpSupported == null) {
+ var highp = ctx.getShaderPrecisionFormat(ctx.FRAGMENT_SHADER, ctx.HIGH_FLOAT);
+ cc.GLProgram._highpSupported = highp.precision !== 0;
+ }
+ return cc.GLProgram._highpSupported;
+};
+
+/**
+ *
+ * Sets the shader program for this node
+ *
+ * Since v2.0, each rendering node must set its shader program.
+ * It should be set in initialize phase.
+ *
+ * @function
+ * @param {cc.Node} node
+ * @param {cc.GLProgram} program The shader program which fetches from CCShaderCache.
+ * @example
+ * cc.setGLProgram(node, cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
+ */
+cc.setProgram = function (node, program) {
+ node.shaderProgram = program;
+
+ var children = node.children;
+ if (!children)
+ return;
+
+ for (var i = 0; i < children.length; i++)
+ cc.setProgram(children[i], program);
};
diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js
new file mode 100644
index 0000000000..c5bc2fd428
--- /dev/null
+++ b/cocos2d/shaders/CCGLProgramState.js
@@ -0,0 +1,303 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+var types =
+ {
+ GL_FLOAT: 0,
+ GL_INT: 1,
+ GL_FLOAT_VEC2: 2,
+ GL_FLOAT_VEC3: 3,
+ GL_FLOAT_VEC4: 4,
+ GL_FLOAT_MAT4: 5,
+ GL_CALLBACK: 6,
+ GL_TEXTURE: 7
+ };
+
+
+
+cc.UniformValue = function (uniform, glprogram) {
+ this._uniform = uniform;
+ this._glprogram = glprogram;
+
+ this._value = null;
+ this._type = -1;
+};
+
+cc.UniformValue.prototype = {
+ setFloat: function setFloat(value) {
+ this._value = value;
+ this._type = types.GL_FLOAT;
+ },
+
+ setInt: function setInt(value) {
+ this._value = value;
+ this._type = types.GL_INT;
+ },
+
+ setVec2: function setVec2(v1, v2) {
+ this._value = [v1, v2];
+ this._type = types.GL_FLOAT_VEC2;
+ },
+
+ setVec2v: function setVec2v(value) {
+ this._value = value.slice(0);
+ this._type = types.GL_FLOAT_VEC2;
+ },
+
+ setVec3: function setVec3(v1, v2, v3) {
+ this._value = [v1, v2, v3];
+ this._type = types.GL_FLOAT_VEC3;
+ },
+
+ setVec3v: function setVec3v(value) {
+ this._value = value.slice(0);
+ this._type = types.GL_FLOAT_VEC3;
+ },
+
+ setVec4: function setVec4(v1, v2, v3, v4) {
+ this._value = [v1, v2, v3, v4];
+ this._type = types.GL_FLOAT_VEC4;
+ },
+
+ setVec4v: function setVec4v(value) {
+ this._value = value.slice(0);
+ this._type = types.GL_FLOAT_VEC4;
+ },
+
+ setMat4: function setMat4(value) {
+ this._value = value.slice(0);
+ this._type = types.GL_FLOAT_MAT4;
+ },
+
+ setCallback: function setCallback(fn) {
+ this._value = fn;
+ this._type = types.GL_CALLBACK;
+ },
+
+ setTexture: function setTexture(textureId, textureUnit) {
+ this._value = textureUnit;
+ this._textureId = textureId;
+ this._type = types.GL_TEXTURE;
+ },
+
+ apply: function apply() {
+ switch (this._type) {
+ case types.GL_INT:
+ this._glprogram.setUniformLocationWith1i(this._uniform._location, this._value);
+ break;
+ case types.GL_FLOAT:
+ this._glprogram.setUniformLocationWith1f(this._uniform._location, this._value);
+ break;
+ case types.GL_FLOAT_VEC2:
+ this._glprogram.setUniformLocationWith2fv(this._uniform._location, this._value);
+ break;
+ case types.GL_FLOAT_VEC3:
+ this._glprogram.setUniformLocationWith3fv(this._uniform._location, this._value);
+ break;
+ case types.GL_FLOAT_VEC4:
+ this._glprogram.setUniformLocationWith4fv(this._uniform._location, this._value);
+ break;
+ case types.GL_FLOAT_MAT4:
+ this._glprogram.setUniformLocationWithMatrix4fv(this._uniform._location, this._value);
+ break;
+ case types.GL_CALLBACK:
+ this._value(this._glprogram, this._uniform);
+ break;
+ case types.GL_TEXTURE:
+ this._glprogram.setUniformLocationWith1i(this._uniform._location, this._value);
+ cc.glBindTexture2DN(this._value, this._textureId);
+ break;
+ default:
+ ;
+ }
+ },
+};
+
+cc.GLProgramState = function (glprogram) {
+ this._glprogram = glprogram;
+ this._uniforms = {};
+ this._boundTextureUnits = {};
+ this._textureUnitIndex = 1; // Start at 1, as CC_Texture0 is bound to 0
+
+ var activeUniforms = glprogram._glContext.getProgramParameter(glprogram._programObj,
+ glprogram._glContext.ACTIVE_UNIFORMS);
+
+ for (var i = 0; i < activeUniforms; i += 1) {
+ var uniform = glprogram._glContext.getActiveUniform(glprogram._programObj, i);
+ if (uniform.name.indexOf("CC_") !== 0) {
+ uniform._location = glprogram._glContext.getUniformLocation(glprogram._programObj, uniform.name);
+ uniform._location._name = uniform.name;
+ var uniformValue = new cc.UniformValue(uniform, glprogram);
+ this._uniforms[uniform.name] = uniformValue;
+ }
+ }
+};
+
+cc.GLProgramState.prototype = {
+ apply: function apply(modelView) {
+ this._glprogram.use();
+ if (modelView) {
+ this._glprogram._setUniformForMVPMatrixWithMat4(modelView);
+ }
+
+ for (var name in this._uniforms) {
+ this._uniforms[name].apply();
+ };
+ },
+
+ setGLProgram: function setGLProgram(glprogram) {
+ this._glprogram = glprogram;
+ },
+
+ getGLProgram: function getGLProgram() {
+ return this._glprogram;
+ },
+
+ getUniformCount: function getUniformCount() {
+ return this._uniforms.length;
+ },
+
+ getUniformValue: function getUniformValue(uniform) {
+ return this._uniforms[uniform];
+ },
+
+ setUniformInt: function setUniformInt(uniform, value) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setInt(value);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+ setUniformFloat: function setUniformFloat(uniform, value) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setFloat(value);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+ setUniformVec2: function setUniformVec2(uniform, v1, v2) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setVec2(v1, v2);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+ setUniformVec2v: function setUniformVec2v(uniform, value) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setVec2v(value);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+ setUniformVec3: function setUniformVec3(uniform, v1, v2, v3) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setVec3(v1, v2, v3);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+ setUniformVec3v: function setUniformVec3v(uniform, value) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setVec3v(value);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+ setUniformVec4: function setUniformVec4(uniform, v1, v2, v3, v4) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setVec4(v1, v2, v3, v4);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+ setUniformVec4v: function setUniformVec4v(uniform, value) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setVec4v(value);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+ },
+
+
+ setUniformMat4: function setUniformMat4(uniform, value) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setMat4(value);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+
+ },
+
+ setUniformCallback: function setUniformCallback(uniform, callback) {
+ var v = this.getUniformValue(uniform);
+ if (v) {
+ v.setCallback(callback);
+ } else {
+ cc.log("cocos2d: warning: Uniform not found: " + uniform);
+ }
+
+ },
+
+ setUniformTexture: function setUniformTexture(uniform, texture) {
+ var uniformValue = this.getUniformValue(uniform);
+ if (uniformValue) {
+ var textureUnit = this._boundTextureUnits[uniform];
+ if (textureUnit) {
+ uniformValue.setTexture(texture, textureUnit);
+ } else {
+ uniformValue.setTexture(texture, this._textureUnitIndex);
+ this._boundTextureUnits[uniform] = this._textureUnitIndex++;
+ }
+ }
+ }
+};
+
+cc.GLProgramState._cache = {};
+cc.GLProgramState.getOrCreateWithGLProgram = function (glprogram) {
+ var programState = cc.GLProgramState._cache[glprogram.__instanceId];
+ if (!programState) {
+ programState = new cc.GLProgramState(glprogram);
+ cc.GLProgramState._cache[glprogram.__instanceId] = programState;
+ }
+
+ return programState;
+};
diff --git a/cocos2d/shaders/CCGLStateCache.js b/cocos2d/shaders/CCGLStateCache.js
index eaf19a82e3..626c587a9c 100644
--- a/cocos2d/shaders/CCGLStateCache.js
+++ b/cocos2d/shaders/CCGLStateCache.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -24,44 +24,7 @@
THE SOFTWARE.
****************************************************************************/
-// ------------------- vertex attrib flags -----------------------------
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_FLAG_NONE = 0;
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_FLAG_POSITION = 1 << 0;
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_FLAG_COLOR = 1 << 1;
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_FLAG_TEXCOORDS = 1 << 2;
-/**
- * @constant
- * @type {Number}
- */
-cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX = ( cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS );
-
-/**
- * GL server side states
- * @constant
- * @type {Number}
- */
-cc.GL_ALL = 0;
-
cc._currentProjectionMatrix = -1;
-cc._vertexAttribPosition = false;
-cc._vertexAttribColor = false;
-cc._vertexAttribTexCoords = false;
if (cc.ENABLE_GL_STATE_CACHE) {
cc.MAX_ACTIVETEXTURE = 16;
@@ -80,13 +43,11 @@ if (cc.ENABLE_GL_STATE_CACHE) {
/**
* Invalidates the GL state cache.
* If CC_ENABLE_GL_STATE_CACHE it will reset the GL state cache.
+ * @function
*/
cc.glInvalidateStateCache = function () {
cc.kmGLFreeAll();
cc._currentProjectionMatrix = -1;
- cc._vertexAttribPosition = false;
- cc._vertexAttribColor = false;
- cc._vertexAttribTexCoords = false;
if (cc.ENABLE_GL_STATE_CACHE) {
cc._currentShaderProgram = -1;
for (var i = 0; i < cc.MAX_ACTIVETEXTURE; i++) {
@@ -101,24 +62,22 @@ cc.glInvalidateStateCache = function () {
/**
* Uses the GL program in case program is different than the current one.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glUseProgram() directly.
+ * @function
* @param {WebGLProgram} program
*/
-cc.glUseProgram = function (program) {
+cc.glUseProgram = cc.ENABLE_GL_STATE_CACHE ? function (program) {
if (program !== cc._currentShaderProgram) {
cc._currentShaderProgram = program;
- cc.renderContext.useProgram(program);
+ cc._renderContext.useProgram(program);
}
+} : function (program) {
+ cc._renderContext.useProgram(program);
};
-if(!cc.ENABLE_GL_STATE_CACHE){
- cc.glUseProgram = function (program) {
- cc.renderContext.useProgram(program);
- }
-}
-
/**
* Deletes the GL program. If it is the one that is being used, it invalidates it.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glDeleteProgram() directly.
+ * @function
* @param {WebGLProgram} program
*/
cc.glDeleteProgram = function (program) {
@@ -130,36 +89,47 @@ cc.glDeleteProgram = function (program) {
};
/**
- * Uses a blending function in case it not already used.
- * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glBlendFunc() directly.
+ * @function
* @param {Number} sfactor
* @param {Number} dfactor
*/
-cc.glBlendFunc = function (sfactor, dfactor) {
- if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) {
- cc._blendingSource = sfactor;
- cc._blendingDest = dfactor;
- cc.setBlending(sfactor, dfactor);
- }
-};
-
cc.setBlending = function (sfactor, dfactor) {
- var ctx = cc.renderContext;
+ var ctx = cc._renderContext;
if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) {
ctx.disable(ctx.BLEND);
} else {
ctx.enable(ctx.BLEND);
- cc.renderContext.blendFunc(sfactor,dfactor);
+ cc._renderContext.blendFunc(sfactor,dfactor);
//TODO need fix for WebGL
//ctx.blendFuncSeparate(ctx.SRC_ALPHA, dfactor, sfactor, dfactor);
}
};
+/**
+ * Uses a blending function in case it not already used.
+ * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glBlendFunc() directly.
+ * @function
+ * @param {Number} sfactor
+ * @param {Number} dfactor
+ */
+cc.glBlendFunc = cc.ENABLE_GL_STATE_CACHE ? function (sfactor, dfactor) {
+ if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) {
+ cc._blendingSource = sfactor;
+ cc._blendingDest = dfactor;
+ cc.setBlending(sfactor, dfactor);
+ }
+} : cc.setBlending;
+
+/**
+ * @function
+ * @param {Number} sfactor
+ * @param {Number} dfactor
+ */
cc.glBlendFuncForParticle = function(sfactor, dfactor) {
if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) {
cc._blendingSource = sfactor;
cc._blendingDest = dfactor;
- var ctx = cc.renderContext;
+ var ctx = cc._renderContext;
if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) {
ctx.disable(ctx.BLEND);
} else {
@@ -170,16 +140,13 @@ cc.glBlendFuncForParticle = function(sfactor, dfactor) {
}
};
-if(!cc.ENABLE_GL_STATE_CACHE){
- cc.glBlendFunc = cc.setBlending;
-};
-
/**
* Resets the blending mode back to the cached state in case you used glBlendFuncSeparate() or glBlendEquation().
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will just set the default blending mode using GL_FUNC_ADD.
+ * @function
*/
cc.glBlendResetToCache = function () {
- var ctx = cc.renderContext;
+ var ctx = cc._renderContext;
ctx.blendEquation(ctx.FUNC_ADD);
if (cc.ENABLE_GL_STATE_CACHE)
cc.setBlending(cc._blendingSource, cc._blendingDest);
@@ -189,59 +156,16 @@ cc.glBlendResetToCache = function () {
/**
* sets the projection matrix as dirty
+ * @function
*/
cc.setProjectionMatrixDirty = function () {
cc._currentProjectionMatrix = -1;
};
-/**
- *
- * Will enable the vertex attribs that are passed as flags.
- * Possible flags:
- * cc.VERTEX_ATTRIB_FLAG_POSITION
- * cc.VERTEX_ATTRIB_FLAG_COLOR
- * cc.VERTEX_ATTRIB_FLAG_TEXCOORDS
- *
- * These flags can be ORed. The flags that are not present, will be disabled.
- *
- * @param {cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS} flags
- */
-cc.glEnableVertexAttribs = function (flags) {
- /* Position */
- var ctx = cc.renderContext;
- var enablePosition = ( flags & cc.VERTEX_ATTRIB_FLAG_POSITION );
- if (enablePosition !== cc._vertexAttribPosition) {
- if (enablePosition)
- ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
- else
- ctx.disableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
- cc._vertexAttribPosition = enablePosition;
- }
-
- /* Color */
- var enableColor = (flags & cc.VERTEX_ATTRIB_FLAG_COLOR);
- if (enableColor !== cc._vertexAttribColor) {
- if (enableColor)
- ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
- else
- ctx.disableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
- cc._vertexAttribColor = enableColor;
- }
-
- /* Tex Coords */
- var enableTexCoords = (flags & cc.VERTEX_ATTRIB_FLAG_TEXCOORDS);
- if (enableTexCoords !== cc._vertexAttribTexCoords) {
- if (enableTexCoords)
- ctx.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
- else
- ctx.disableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
- cc._vertexAttribTexCoords = enableTexCoords;
- }
-};
-
/**
* If the texture is not already bound, it binds it.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly.
+ * @function
* @param {cc.Texture2D} textureId
*/
cc.glBindTexture2D = function (textureId) {
@@ -251,35 +175,34 @@ cc.glBindTexture2D = function (textureId) {
/**
* If the texture is not already bound to a given unit, it binds it.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly.
+ * @function
* @param {Number} textureUnit
* @param {cc.Texture2D} textureId
*/
-cc.glBindTexture2DN = function (textureUnit, textureId) {
- if (cc._currentBoundTexture[textureUnit] == textureId)
+cc.glBindTexture2DN = cc.ENABLE_GL_STATE_CACHE ? function (textureUnit, textureId) {
+ if (cc._currentBoundTexture[textureUnit] === textureId)
return;
cc._currentBoundTexture[textureUnit] = textureId;
- var ctx = cc.renderContext;
+ var ctx = cc._renderContext;
+ ctx.activeTexture(ctx.TEXTURE0 + textureUnit);
+ if(textureId)
+ ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj);
+ else
+ ctx.bindTexture(ctx.TEXTURE_2D, null);
+} : function (textureUnit, textureId) {
+ var ctx = cc._renderContext;
ctx.activeTexture(ctx.TEXTURE0 + textureUnit);
if(textureId)
ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj);
else
ctx.bindTexture(ctx.TEXTURE_2D, null);
};
-if (!cc.ENABLE_GL_STATE_CACHE){
- cc.glBindTexture2DN = function (textureUnit, textureId) {
- var ctx = cc.renderContext;
- ctx.activeTexture(ctx.TEXTURE0 + textureUnit);
- if(textureId)
- ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj);
- else
- ctx.bindTexture(ctx.TEXTURE_2D, null);
- };
-}
/**
* It will delete a given texture. If the texture was bound, it will invalidate the cached.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly.
+ * @function
* @param {WebGLTexture} textureId
*/
cc.glDeleteTexture = function (textureId) {
@@ -289,28 +212,30 @@ cc.glDeleteTexture = function (textureId) {
/**
* It will delete a given texture. If the texture was bound, it will invalidate the cached for the given texture unit.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly.
+ * @function
* @param {Number} textureUnit
* @param {WebGLTexture} textureId
*/
cc.glDeleteTextureN = function (textureUnit, textureId) {
if (cc.ENABLE_GL_STATE_CACHE) {
- if (textureId == cc._currentBoundTexture[ textureUnit ])
+ if (textureId === cc._currentBoundTexture[ textureUnit ])
cc._currentBoundTexture[ textureUnit ] = -1;
}
- cc.renderContext.deleteTexture(textureId);
+ cc._renderContext.deleteTexture(textureId._webTextureObj);
};
/**
* If the vertex array is not already bound, it binds it.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindVertexArray() directly.
- * @param vaoId
+ * @function
+ * @param {Number} vaoId
*/
cc.glBindVAO = function (vaoId) {
if (!cc.TEXTURE_ATLAS_USE_VAO)
return;
if (cc.ENABLE_GL_STATE_CACHE) {
- if (cc._uVAO != vaoId) {
+ if (cc._uVAO !== vaoId) {
cc._uVAO = vaoId;
//TODO need fixed
//glBindVertexArray(vaoId);
@@ -323,6 +248,7 @@ cc.glBindVAO = function (vaoId) {
/**
* It will enable / disable the server side GL states.
* If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glEnable() directly.
+ * @function
* @param {Number} flags
*/
cc.glEnable = function (flags) {
@@ -334,18 +260,17 @@ cc.glEnable = function (flags) {
/*
if ((enabled = (flags & cc.GL_BLEND)) != (cc._GLServerState & cc.GL_BLEND)) {
if (enabled) {
- cc.renderContext.enable(cc.renderContext.BLEND);
+ cc._renderContext.enable(cc._renderContext.BLEND);
cc._GLServerState |= cc.GL_BLEND;
} else {
- cc.renderContext.disable(cc.renderContext.BLEND);
+ cc._renderContext.disable(cc._renderContext.BLEND);
cc._GLServerState &= ~cc.GL_BLEND;
}
}*/
} else {
/*if ((flags & cc.GL_BLEND))
- cc.renderContext.enable(cc.renderContext.BLEND);
+ cc._renderContext.enable(cc._renderContext.BLEND);
else
- cc.renderContext.disable(cc.renderContext.BLEND);*/
+ cc._renderContext.disable(cc._renderContext.BLEND);*/
}
};
-
diff --git a/cocos2d/shaders/CCShaderCache.js b/cocos2d/shaders/CCShaderCache.js
index ef6972bd27..462f208d21 100644
--- a/cocos2d/shaders/CCShaderCache.js
+++ b/cocos2d/shaders/CCShaderCache.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -25,61 +25,107 @@
****************************************************************************/
/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_TEXTURECOLOR = 0;
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST = 1;
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_COLOR = 2;
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_TEXTURE = 3;
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR = 4;
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR = 5;
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_UCOLOR = 6;
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_POSITION_LENGTH_TEXTURECOLOR = 7;
-
-/**
- * @constant
- * @type {Number}
- */
-cc.SHADERTYPE_MAX = 8;
-
-cc._sharedShaderCache = null;
-
-/**
- * Singleton that stores manages GL shaders
+ * cc.shaderCache is a singleton object that stores manages GL shaders
* @class
- * @extends cc.Class
+ * @name cc.shaderCache
*/
-cc.ShaderCache = cc.Class.extend({
- _programs: null,
+cc.shaderCache = /** @lends cc.shaderCache# */{
+
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_TEXTURECOLOR: 0,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_TEXTURECOLOR_ALPHATEST: 1,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_COLOR: 2,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_TEXTURE: 3,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_TEXTURE_UCOLOR: 4,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_TEXTURE_A8COLOR: 5,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_UCOLOR: 6,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_POSITION_LENGTH_TEXTURECOLOR: 7,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_SPRITE_POSITION_TEXTURECOLOR: 8,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_SPRITE_POSITION_TEXTURECOLOR_ALPHATEST: 9,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_SPRITE_POSITION_COLOR: 10,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_SPRITE_POSITION_TEXTURECOLOR_GRAY: 11,
+ /**
+ * @public
+ * @constant
+ * @type {Number}
+ */
+ TYPE_MAX: 11,
+
+ _keyMap: [
+ cc.SHADER_POSITION_TEXTURECOLOR,
+ cc.SHADER_POSITION_TEXTURECOLORALPHATEST,
+ cc.SHADER_POSITION_COLOR,
+ cc.SHADER_POSITION_TEXTURE,
+ cc.SHADER_POSITION_TEXTURE_UCOLOR,
+ cc.SHADER_POSITION_TEXTUREA8COLOR,
+ cc.SHADER_POSITION_UCOLOR,
+ cc.SHADER_POSITION_LENGTHTEXTURECOLOR,
+ cc.SHADER_SPRITE_POSITION_TEXTURECOLOR,
+ cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST,
+ cc.SHADER_SPRITE_POSITION_COLOR,
+ cc.SHADER_SPRITE_POSITION_TEXTURECOLOR_GRAY
+ ],
+
+ _programs: {},
_init: function () {
this.loadDefaultShaders();
@@ -88,138 +134,91 @@ cc.ShaderCache = cc.Class.extend({
_loadDefaultShader: function (program, type) {
switch (type) {
- case cc.SHADERTYPE_POSITION_TEXTURECOLOR:
+ case cc.SHADER_POSITION_TEXTURECOLOR:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_FRAG);
-
program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
break;
- case cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST:
+ case cc.SHADER_SPRITE_POSITION_TEXTURECOLOR:
+ program.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_FRAG);
+ program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
+ program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
+ program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
+ break;
+ case cc.SHADER_SPRITE_POSITION_TEXTURECOLOR_GRAY:
+ program.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_GRAY_FRAG);
+ program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
+ program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
+ program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
+ break;
+ case cc.SHADER_POSITION_TEXTURECOLORALPHATEST:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG);
-
program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
break;
- case cc.SHADERTYPE_POSITION_COLOR:
+ case cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST:
+ program.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG);
+ program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
+ program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
+ program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
+ break;
+ case cc.SHADER_POSITION_COLOR:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_COLOR_VERT, cc.SHADER_POSITION_COLOR_FRAG);
-
program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
break;
- case cc.SHADERTYPE_POSITION_TEXTURE:
+ case cc.SHADER_SPRITE_POSITION_COLOR:
+ program.initWithVertexShaderByteArray(cc.SHADER_SPRITE_POSITION_COLOR_VERT, cc.SHADER_POSITION_COLOR_FRAG);
+ program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
+ program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
+ break;
+ case cc.SHADER_POSITION_TEXTURE:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_VERT, cc.SHADER_POSITION_TEXTURE_FRAG);
-
program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
break;
- case cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR:
+ case cc.SHADER_POSITION_TEXTURE_UCOLOR:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_UCOLOR_VERT, cc.SHADER_POSITION_TEXTURE_UCOLOR_FRAG);
-
program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
break;
- case cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR:
+ case cc.SHADER_POSITION_TEXTUREA8COLOR:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_A8COLOR_VERT, cc.SHADER_POSITION_TEXTURE_A8COLOR_FRAG);
-
program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
break;
- case cc.SHADERTYPE_POSITION_UCOLOR:
+ case cc.SHADER_POSITION_UCOLOR:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_UCOLOR_VERT, cc.SHADER_POSITION_UCOLOR_FRAG);
program.addAttribute("aVertex", cc.VERTEX_ATTRIB_POSITION);
break;
- case cc.SHADERTYPE_POSITION_LENGTH_TEXTURECOLOR:
+ case cc.SHADER_POSITION_LENGTHTEXTURECOLOR:
program.initWithVertexShaderByteArray(cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_VERT, cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_FRAG);
-
program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
break;
default:
- cc.log("cocos2d: cc.ShaderCache._loadDefaultShader, error shader type");
+ cc.log("cocos2d: cc.shaderCache._loadDefaultShader, error shader type");
return;
}
program.link();
program.updateUniforms();
- //cc.CHECK_GL_ERROR_DEBUG();
- },
-
- /**
- * Constructor
- * @override
- */
- ctor: function () {
- this._programs = {};
+ //cc.checkGLErrorDebug();
},
/**
* loads the default shaders
*/
loadDefaultShaders: function () {
- // Position Texture Color shader
- var program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR);
- this._programs[cc.SHADER_POSITION_TEXTURECOLOR] = program;
- this._programs["ShaderPositionTextureColor"] = program;
-
- // Position Texture Color alpha test
- program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST);
- this._programs[cc.SHADER_POSITION_TEXTURECOLORALPHATEST] = program;
- this._programs["ShaderPositionTextureColorAlphaTest"] = program;
-
- //
- // Position, Color shader
- //
- program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_COLOR);
- this._programs[cc.SHADER_POSITION_COLOR] = program;
- this._programs["ShaderPositionColor"] = program;
-
- //
- // Position Texture shader
- //
- program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE);
- this._programs[cc.SHADER_POSITION_TEXTURE] = program;
- this._programs["ShaderPositionTexture"] = program;
-
- //
- // Position, Texture attribs, 1 Color as uniform shader
- //
- program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR);
- this._programs[cc.SHADER_POSITION_TEXTURE_UCOLOR] = program;
- this._programs["ShaderPositionTextureUColor"] = program;
-
- //
- // Position Texture A8 Color shader
- //
- program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR);
- this._programs[cc.SHADER_POSITION_TEXTUREA8COLOR] = program;
- this._programs["ShaderPositionTextureA8Color"] = program;
-
- //
- // Position and 1 color passed as a uniform (to similate glColor4ub )
- //
- program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_UCOLOR);
- this._programs[cc.SHADER_POSITION_UCOLOR] = program;
- this._programs["ShaderPositionUColor"] = program;
-
- //
- // Position, Legth(TexCoords, Color (used by Draw Node basically )
- //
- program = new cc.GLProgram();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_LENGTH_TEXTURECOLOR);
- this._programs[cc.SHADER_POSITION_LENGTHTEXTURECOLOR] = program;
- this._programs["ShaderPositionLengthTextureColor"] = program;
+ for (var i = 0; i < this.TYPE_MAX; ++i) {
+ var key = this._keyMap[i];
+ this.programForKey(key);
+ }
},
/**
@@ -231,85 +230,93 @@ cc.ShaderCache = cc.Class.extend({
// Position Texture Color shader
var program = this.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
program.reset();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR);
+ this._loadDefaultShader(program, cc.SHADER_POSITION_TEXTURECOLOR);
+
+ // Sprite Position Texture Color shader
+ program = this.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
+ program.reset();
+ this._loadDefaultShader(program, cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
// Position Texture Color alpha test
program = this.programForKey(cc.SHADER_POSITION_TEXTURECOLORALPHATEST);
program.reset();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST);
+ this._loadDefaultShader(program, cc.SHADER_POSITION_TEXTURECOLORALPHATEST);
+
+ // Sprite Position Texture Color alpha shader
+ program = this.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
+ program.reset();
+ this._loadDefaultShader(program, cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
//
// Position, Color shader
//
program = this.programForKey(cc.SHADER_POSITION_COLOR);
program.reset();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_COLOR);
+ this._loadDefaultShader(program, cc.SHADER_POSITION_COLOR);
//
// Position Texture shader
//
program = this.programForKey(cc.SHADER_POSITION_TEXTURE);
program.reset();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE);
+ this._loadDefaultShader(program, cc.SHADER_POSITION_TEXTURE);
+
+ //Position Texture Gray shader
+ program = this.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_GRAY_FRAG);
+ program.reset();
+ this._loadDefaultShader(program, cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_GRAY_FRAG);
//
// Position, Texture attribs, 1 Color as uniform shader
//
program = this.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR);
program.reset();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR);
+ this._loadDefaultShader(program, cc.SHADER_POSITION_TEXTURE_UCOLOR);
//
// Position Texture A8 Color shader
//
program = this.programForKey(cc.SHADER_POSITION_TEXTUREA8COLOR);
program.reset();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR);
+ this._loadDefaultShader(program, cc.SHADER_POSITION_TEXTUREA8COLOR);
//
// Position and 1 color passed as a uniform (to similate glColor4ub )
//
program = this.programForKey(cc.SHADER_POSITION_UCOLOR);
program.reset();
- this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_UCOLOR);
+ this._loadDefaultShader(program, cc.SHADER_POSITION_UCOLOR);
},
- /** returns a GL program for a given key */
+ /**
+ * returns a GL program for a given key
+ * @param {String} key
+ */
programForKey: function (key) {
+ if (!this._programs[key]) {
+ var program = new cc.GLProgram();
+ this._loadDefaultShader(program, key);
+ this._programs[key] = program;
+ }
+
return this._programs[key];
},
/**
* returns a GL program for a shader name
* @param {String} shaderName
- * @return cc.GLProgram
+ * @return {cc.GLProgram}
*/
getProgram: function (shaderName) {
- return this._programs[shaderName];
+ return this.programForKey(shaderName);
},
- /** adds a CCGLProgram to the cache for a given name */
+ /**
+ * adds a CCGLProgram to the cache for a given name
+ * @param {cc.GLProgram} program
+ * @param {String} key
+ */
addProgram: function (program, key) {
this._programs[key] = program;
}
-});
-
-/** */
-/**
- * returns the cc.ShaderCache instance
- * @return {cc.ShaderCache}
- */
-cc.ShaderCache.getInstance = function () {
- if (!cc._sharedShaderCache) {
- cc._sharedShaderCache = new cc.ShaderCache();
- cc._sharedShaderCache._init();
- }
- return cc._sharedShaderCache;
};
-
-/**
- * purges the cache. It releases the retained instance.
- */
-cc.ShaderCache.purgeSharedShaderCache = function () {
- cc._sharedShaderCache = null;
-};
\ No newline at end of file
diff --git a/cocos2d/shaders/CCShaders.js b/cocos2d/shaders/CCShaders.js
index 29686f7d28..eb656c55ba 100644
--- a/cocos2d/shaders/CCShaders.js
+++ b/cocos2d/shaders/CCShaders.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2016 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -30,90 +30,82 @@
* @type {String}
*/
cc.SHADER_POSITION_UCOLOR_FRAG =
- " \n"
- + "precision lowp float; \n"
- + " \n"
- + "varying vec4 v_fragmentColor; \n"
- + " \n"
+ "precision lowp float;\n"
+ + "varying vec4 v_fragmentColor;\n"
+ "void main() \n"
- + "{ \n"
+ + "{ \n"
+ " gl_FragColor = v_fragmentColor; \n"
- + "} \n";
-
+ + "}\n";
/**
* @constant
* @type {String}
*/
cc.SHADER_POSITION_UCOLOR_VERT =
- " \n"
- + "attribute vec4 a_position; \n"
- + "uniform vec4 u_color; \n"
- + "uniform float u_pointSize; \n"
- + " \n"
- + "varying lowp vec4 v_fragmentColor; \n"
- + " \n"
- + "void main(void) \n"
- + "{ \n"
+ "attribute vec4 a_position;\n"
+ + "uniform vec4 u_color;\n"
+ + "uniform float u_pointSize;\n"
+ + "varying lowp vec4 v_fragmentColor; \n"
+ + "void main(void) \n"
+ + "{\n"
//+ " gl_Position = CC_MVPMatrix * a_position; \n"
+ " gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position; \n"
+ " gl_PointSize = u_pointSize; \n"
+ " v_fragmentColor = u_color; \n"
+ "}";
-
//---------------------Shader_PositionColor Shader Source-----------------------
/**
* @constant
* @type {String}
*/
cc.SHADER_POSITION_COLOR_FRAG =
- " \n"
- + "precision lowp float; \n"
- + "varying vec4 v_fragmentColor; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
- + " gl_FragColor = v_fragmentColor; \n"
+ "precision lowp float; \n"
+ + "varying vec4 v_fragmentColor; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " gl_FragColor = v_fragmentColor; \n"
+ "} ";
-
/**
* @constant
* @type {String}
*/
cc.SHADER_POSITION_COLOR_VERT =
- " \n"
- + "attribute vec4 a_position; \n"
- + "attribute vec4 a_color; \n"
- + " \n"
- + "varying lowp vec4 v_fragmentColor; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
- //+ " gl_Position = CC_MVPMatrix * a_position; \n"
+ "attribute vec4 a_position;\n"
+ + "attribute vec4 a_color;\n"
+ + "varying lowp vec4 v_fragmentColor;\n"
+ + "void main()\n"
+ + "{\n"
+ " gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position; \n"
+ " v_fragmentColor = a_color; \n"
+ "}";
+cc.SHADER_SPRITE_POSITION_COLOR_VERT =
+ "attribute vec4 a_position;\n"
+ + "attribute vec4 a_color;\n"
+ + "varying lowp vec4 v_fragmentColor;\n"
+ + "void main()\n"
+ + "{\n"
+ + " gl_Position = CC_PMatrix * a_position; \n"
+ + " v_fragmentColor = a_color; \n"
+ + "}";
+
// --------------------- Shader_PositionColorLengthTexture Shader source------------------------
/**
* @constant
* @type {String}
*/
cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_FRAG =
- " \n"
- + "// #extension GL_OES_standard_derivatives : enable \n"
- + "\n"
- + "varying mediump vec4 v_color; \n"
- + "varying mediump vec2 v_texcoord; \n"
- + "\n"
- + "void main() \n"
- + "{ \n"
- + "// #if defined GL_OES_standard_derivatives \n"
- + "// gl_FragColor = v_color*smoothstep(0.0, length(fwidth(v_texcoord)), 1.0 - length(v_texcoord)); \n"
- + "// #else \n"
- + "gl_FragColor = v_color * step(0.0, 1.0 - length(v_texcoord)); \n"
- + "// #endif \n"
+ "// #extension GL_OES_standard_derivatives : enable\n"
+ + "varying mediump vec4 v_color;\n"
+ + "varying mediump vec2 v_texcoord;\n"
+ + "void main() \n"
+ + "{ \n"
+ + "// #if defined GL_OES_standard_derivatives \n"
+ + "// gl_FragColor = v_color*smoothstep(0.0, length(fwidth(v_texcoord)), 1.0 - length(v_texcoord)); \n"
+ + "// #else \n"
+ + "gl_FragColor = v_color * step(0.0, 1.0 - length(v_texcoord)); \n"
+ + "// #endif \n"
+ "}";
/**
@@ -121,19 +113,15 @@ cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_FRAG =
* @type {String}
*/
cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_VERT =
- " \n"
- + "attribute mediump vec4 a_position; \n"
- + "attribute mediump vec2 a_texcoord; \n"
- + "attribute mediump vec4 a_color; \n"
- + "\n"
- + "varying mediump vec4 v_color; \n"
- + "varying mediump vec2 v_texcoord; \n"
- + "\n"
- + "void main() \n"
- + "{ \n"
- + " v_color = a_color;//vec4(a_color.rgb * a_color.a, a_color.a); \n"
- + " v_texcoord = a_texcoord; \n"
- + " \n"
+ "attribute mediump vec4 a_position; \n"
+ + "attribute mediump vec2 a_texcoord; \n"
+ + "attribute mediump vec4 a_color; \n"
+ + "varying mediump vec4 v_color; \n"
+ + "varying mediump vec2 v_texcoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " v_color = a_color;//vec4(a_color.rgb * a_color.a, a_color.a); \n"
+ + " v_texcoord = a_texcoord; \n"
//+ " gl_Position = CC_MVPMatrix * a_position; \n"
+ " gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position; \n"
+ "}";
@@ -144,14 +132,10 @@ cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_VERT =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_FRAG =
- " \n"
- + "precision lowp float; \n"
- + " \n"
- + "varying vec2 v_texCoord; \n"
- + "uniform sampler2D CC_Texture0; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
+ "precision lowp float; \n"
+ + "varying vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ " gl_FragColor = texture2D(CC_Texture0, v_texCoord); \n"
+ "}";
@@ -160,14 +144,11 @@ cc.SHADER_POSITION_TEXTURE_FRAG =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_VERT =
- " \n"
- + "attribute vec4 a_position; \n"
- + "attribute vec2 a_texCoord; \n"
- + " \n"
- + "varying mediump vec2 v_texCoord; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
+ "attribute vec4 a_position; \n"
+ + "attribute vec2 a_texCoord; \n"
+ + "varying mediump vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
//+ " gl_Position = CC_MVPMatrix * a_position; \n"
+ " gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
@@ -179,16 +160,11 @@ cc.SHADER_POSITION_TEXTURE_VERT =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_UCOLOR_FRAG =
- " \n"
- + "precision lowp float; \n"
- + " \n"
- + "uniform vec4 u_color; \n"
- + "varying vec2 v_texCoord; \n"
- + " \n"
- + "uniform sampler2D CC_Texture0; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
+ "precision lowp float; \n"
+ + "uniform vec4 u_color; \n"
+ + "varying vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ " gl_FragColor = texture2D(CC_Texture0, v_texCoord) * u_color; \n"
+ "}";
@@ -197,14 +173,11 @@ cc.SHADER_POSITION_TEXTURE_UCOLOR_FRAG =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_UCOLOR_VERT =
- " \n"
- + "attribute vec4 a_position; \n"
- + "attribute vec2 a_texCoord; \n"
- + " \n"
- + "varying mediump vec2 v_texCoord; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
+ "attribute vec4 a_position;\n"
+ + "attribute vec2 a_texCoord; \n"
+ + "varying mediump vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
//+ " gl_Position = CC_MVPMatrix * a_position; \n"
+ " gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
@@ -216,18 +189,14 @@ cc.SHADER_POSITION_TEXTURE_UCOLOR_VERT =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_A8COLOR_FRAG =
- " \n"
- + "precision lowp float; \n"
- + " \n"
- + "varying vec4 v_fragmentColor; \n"
- + "varying vec2 v_texCoord; \n"
- + "uniform sampler2D CC_Texture0; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
+ "precision lowp float; \n"
+ + "varying vec4 v_fragmentColor; \n"
+ + "varying vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ " gl_FragColor = vec4( v_fragmentColor.rgb, \n" // RGB from uniform
+ " v_fragmentColor.a * texture2D(CC_Texture0, v_texCoord).a \n" // A from texture and uniform
- + " ); \n"
+ + " ); \n"
+ "}";
/**
@@ -235,20 +204,16 @@ cc.SHADER_POSITION_TEXTURE_A8COLOR_FRAG =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_A8COLOR_VERT =
- " \n"
- + "attribute vec4 a_position; \n"
- + "attribute vec2 a_texCoord; \n"
- + "attribute vec4 a_color; \n"
- + " \n"
- + "varying lowp vec4 v_fragmentColor; \n"
- + "varying mediump vec2 v_texCoord; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
- //+ " gl_Position = CC_MVPMatrix * a_position; \n"
+ "attribute vec4 a_position; \n"
+ + "attribute vec2 a_texCoord; \n"
+ + "attribute vec4 a_color; \n"
+ + "varying lowp vec4 v_fragmentColor; \n"
+ + "varying mediump vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ " gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position; \n"
- + " v_fragmentColor = a_color; \n"
- + " v_texCoord = a_texCoord; \n"
+ + " v_fragmentColor = a_color; \n"
+ + " v_texCoord = a_texCoord; \n"
+ "}";
// ------------------------Shader_PositionTextureColor Shader source------------------------------------
@@ -257,16 +222,12 @@ cc.SHADER_POSITION_TEXTURE_A8COLOR_VERT =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_COLOR_FRAG =
- " \n"
- + "precision lowp float; \n"
- + " \n"
- + "varying vec4 v_fragmentColor; \n"
- + "varying vec2 v_texCoord; \n"
- + "uniform sampler2D CC_Texture0; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
- + " gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); \n"
+ "precision lowp float;\n"
+ + "varying vec4 v_fragmentColor; \n"
+ + "varying vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " gl_FragColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord); \n"
+ "}";
/**
@@ -274,46 +235,62 @@ cc.SHADER_POSITION_TEXTURE_COLOR_FRAG =
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_COLOR_VERT =
- " \n"
- + "attribute vec4 a_position; \n"
- + "attribute vec2 a_texCoord; \n"
- + "attribute vec4 a_color; \n"
- + " \n"
- + "varying lowp vec4 v_fragmentColor; \n"
- + "varying mediump vec2 v_texCoord; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
- //+ " gl_Position = CC_MVPMatrix * a_position; \n"
+ "attribute vec4 a_position; \n"
+ + "attribute vec2 a_texCoord; \n"
+ + "attribute vec4 a_color; \n"
+ + "varying lowp vec4 v_fragmentColor; \n"
+ + "varying mediump vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ " gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position; \n"
- + " v_fragmentColor = a_color; \n"
- + " v_texCoord = a_texCoord; \n"
+ + " v_fragmentColor = a_color; \n"
+ + " v_texCoord = a_texCoord; \n"
+ "}";
+/**
+ * @constant
+ * @type {String}
+ */
+cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_VERT =
+ "attribute vec4 a_position; \n"
+ + "attribute vec2 a_texCoord; \n"
+ + "attribute vec4 a_color; \n"
+ + "varying lowp vec4 v_fragmentColor; \n"
+ + "varying mediump vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " gl_Position = CC_PMatrix * a_position; \n"
+ + " v_fragmentColor = a_color; \n"
+ + " v_texCoord = a_texCoord; \n"
+ + "}";
+
+cc.SHADER_SPRITE_POSITION_TEXTURE_COLOR_GRAY_FRAG =
+ "precision lowp float;\n"
+ + "varying vec4 v_fragmentColor; \n"
+ + "varying vec2 v_texCoord; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " vec4 c = texture2D(CC_Texture0, v_texCoord); \n"
+ + " gl_FragColor.xyz = vec3(0.2126*c.r + 0.7152*c.g + 0.0722*c.b); \n"
+ +" gl_FragColor.w = c.w ; \n"
+ + "}";
//-----------------------Shader_PositionTextureColorAlphaTest_frag Shader Source----------------------------
/**
* @constant
* @type {String}
*/
cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG =
- " \n"
- + "precision lowp float; \n"
- + " \n"
- + "varying vec4 v_fragmentColor; \n"
- + "varying vec2 v_texCoord; \n"
- + "uniform sampler2D CC_Texture0; \n"
- + "uniform float CC_alpha_value; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
- + " vec4 texColor = texture2D(CC_Texture0, v_texCoord); \n"
- + " \n"
- + " // mimic: glAlphaFunc(GL_GREATER) \n"
- + " //pass if ( incoming_pixel >= CC_alpha_value ) => fail if incoming_pixel < CC_alpha_value \n"
- + " \n"
+ "precision lowp float; \n"
+ + "varying vec4 v_fragmentColor; \n"
+ + "varying vec2 v_texCoord; \n"
+ + "uniform float CC_alpha_value; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " vec4 texColor = texture2D(CC_Texture0, v_texCoord); \n"
+ // mimic: glAlphaFunc(GL_GREATER)
+ //pass if ( incoming_pixel >= CC_alpha_value ) => fail if incoming_pixel < CC_alpha_value
+ " if ( texColor.a <= CC_alpha_value ) \n"
- + " discard; \n"
- + " \n"
+ + " discard; \n"
+ " gl_FragColor = texColor * v_fragmentColor; \n"
+ "}";
@@ -323,18 +300,15 @@ cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG =
* @type {String}
*/
cc.SHADEREX_SWITCHMASK_FRAG =
- " \n"
- + "precision lowp float; \n"
- + " \n"
- + "varying vec4 v_fragmentColor; \n"
- + "varying vec2 v_texCoord; \n"
- + "uniform sampler2D u_texture; \n"
- + "uniform sampler2D u_mask; \n"
- + " \n"
- + "void main() \n"
- + "{ \n"
- + " vec4 texColor = texture2D(u_texture, v_texCoord); \n"
- + " vec4 maskColor = texture2D(u_mask, v_texCoord); \n"
+ "precision lowp float; \n"
+ + "varying vec4 v_fragmentColor; \n"
+ + "varying vec2 v_texCoord; \n"
+ + "uniform sampler2D u_texture; \n"
+ + "uniform sampler2D u_mask; \n"
+ + "void main() \n"
+ + "{ \n"
+ + " vec4 texColor = texture2D(u_texture, v_texCoord); \n"
+ + " vec4 maskColor = texture2D(u_mask, v_texCoord); \n"
+ " vec4 finalColor = vec4(texColor.r, texColor.g, texColor.b, maskColor.a * texColor.a); \n"
- + " gl_FragColor = v_fragmentColor * finalColor; \n"
- + "}";
\ No newline at end of file
+ + " gl_FragColor = v_fragmentColor * finalColor; \n"
+ + "}";
diff --git a/cocos2d/shape-nodes/CCDrawNode.js b/cocos2d/shape-nodes/CCDrawNode.js
new file mode 100644
index 0000000000..48caafa13f
--- /dev/null
+++ b/cocos2d/shape-nodes/CCDrawNode.js
@@ -0,0 +1,1037 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2012 Scott Lembcke and Howling Moon Software
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * CCDrawNode
+ * Node that draws dots, segments and polygons.
+ * Faster than the "drawing primitives" since it draws everything in one single batch.
+ * @class
+ * @name cc.DrawNode
+ * @extends cc.Node
+ */
+cc.DrawNode = cc.Node.extend(/** @lends cc.DrawNode# */{
+//TODO need refactor
+
+ _buffer: null,
+ _blendFunc: null,
+ _lineWidth: 1,
+ _drawColor: null,
+
+ /**
+ * Gets the blend func
+ * @returns {Object}
+ */
+ getBlendFunc: function () {
+ return this._blendFunc;
+ },
+
+ /**
+ * Set the blend func
+ * @param blendFunc
+ * @param dst
+ */
+ setBlendFunc: function (blendFunc, dst) {
+ if (dst === undefined) {
+ this._blendFunc.src = blendFunc.src;
+ this._blendFunc.dst = blendFunc.dst;
+ } else {
+ this._blendFunc.src = blendFunc;
+ this._blendFunc.dst = dst;
+ }
+ },
+
+ /**
+ * line width setter
+ * @param {Number} width
+ */
+ setLineWidth: function (width) {
+ this._lineWidth = width;
+ },
+
+ /**
+ * line width getter
+ * @returns {Number}
+ */
+ getLineWidth: function () {
+ return this._lineWidth;
+ },
+
+ /**
+ * draw color setter
+ * @param {cc.Color} color
+ */
+ setDrawColor: function (color) {
+ var locDrawColor = this._drawColor;
+ locDrawColor.r = color.r;
+ locDrawColor.g = color.g;
+ locDrawColor.b = color.b;
+ locDrawColor.a = (color.a == null) ? 255 : color.a;
+ },
+
+ /**
+ * draw color getter
+ * @returns {cc.Color}
+ */
+ getDrawColor: function () {
+ return cc.color(this._drawColor.r, this._drawColor.g, this._drawColor.b, this._drawColor.a);
+ }
+});
+
+/**
+ * Creates a DrawNode
+ * @deprecated since v3.0 please use `new cc.DrawNode()` instead.
+ * @return {cc.DrawNode}
+ */
+cc.DrawNode.create = function () {
+ return new cc.DrawNode();
+};
+
+cc.DrawNode.TYPE_DOT = 0;
+cc.DrawNode.TYPE_SEGMENT = 1;
+cc.DrawNode.TYPE_POLY = 2;
+
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+
+ function pMultOut(pin, floatVar, pout) {
+ pout.x = pin.x * floatVar;
+ pout.y = pin.y * floatVar;
+ }
+
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+
+ cc._DrawNodeElement = function (type, verts, fillColor, lineWidth, lineColor, lineCap, isClosePolygon, isFill, isStroke) {
+ var _t = this;
+ _t.type = type;
+ _t.verts = verts || null;
+ _t.fillColor = fillColor || null;
+ _t.lineWidth = lineWidth || 0;
+ _t.lineColor = lineColor || null;
+ _t.lineCap = lineCap || "butt";
+ _t.isClosePolygon = isClosePolygon || false;
+ _t.isFill = isFill || false;
+ _t.isStroke = isStroke || false;
+ };
+
+ cc.extend(cc.DrawNode.prototype, /** @lends cc.DrawNode# */{
+ _className: "DrawNodeCanvas",
+
+ /**
+ * The cc.DrawNodeCanvas's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.DrawNodeCanvas()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
+ */
+ ctor: function () {
+ cc.Node.prototype.ctor.call(this);
+ var locCmd = this._renderCmd;
+ locCmd._buffer = this._buffer = [];
+ locCmd._drawColor = this._drawColor = cc.color(255, 255, 255, 255);
+ locCmd._blendFunc = this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
+
+ this.init();
+ this._localBB = new cc.Rect();
+ },
+
+ setLocalBB: function (rectorX, y, width, height) {
+ var localBB = this._localBB;
+ if (y === undefined) {
+ localBB.x = rectorX.x;
+ localBB.y = rectorX.y;
+ localBB.width = rectorX.width;
+ localBB.height = rectorX.height;
+ } else {
+ localBB.x = rectorX;
+ localBB.y = y;
+ localBB.width = width;
+ localBB.height = height;
+ }
+ },
+ /**
+ * draws a rectangle given the origin and destination point measured in points.
+ * @param {cc.Point} origin
+ * @param {cc.Point} destination
+ * @param {cc.Color} fillColor
+ * @param {Number} lineWidth
+ * @param {cc.Color} lineColor
+ */
+ drawRect: function (origin, destination, fillColor, lineWidth, lineColor) {
+ lineWidth = (lineWidth == null) ? this._lineWidth : lineWidth;
+ lineColor = lineColor || this.getDrawColor();
+ if (lineColor.a == null)
+ lineColor.a = 255;
+
+ var vertices = [
+ origin,
+ cc.p(destination.x, origin.y),
+ destination,
+ cc.p(origin.x, destination.y)
+ ];
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
+ element.verts = vertices;
+ element.lineWidth = lineWidth;
+ element.lineColor = lineColor;
+ element.isClosePolygon = true;
+ element.isStroke = true;
+ element.lineCap = "butt";
+ element.fillColor = fillColor;
+ if (fillColor) {
+ if (fillColor.a == null)
+ fillColor.a = 255;
+ element.isFill = true;
+ }
+ this._buffer.push(element);
+ },
+
+ /**
+ * draws a circle given the center, radius and number of segments.
+ * @override
+ * @param {cc.Point} center center of circle
+ * @param {Number} radius
+ * @param {Number} angle angle in radians
+ * @param {Number} segments
+ * @param {Boolean} drawLineToCenter
+ * @param {Number} lineWidth
+ * @param {cc.Color} color
+ */
+ drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+
+ var coef = 2.0 * Math.PI / segments;
+ var vertices = [];
+ for (var i = 0; i <= segments; i++) {
+ var rads = i * coef;
+ var j = radius * Math.cos(rads + angle) + center.x;
+ var k = radius * Math.sin(rads + angle) + center.y;
+ vertices.push(cc.p(j, k));
+ }
+ if (drawLineToCenter) {
+ vertices.push(cc.p(center.x, center.y));
+ }
+
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
+ element.verts = vertices;
+ element.lineWidth = lineWidth;
+ element.lineColor = color;
+ element.isClosePolygon = true;
+ element.isStroke = true;
+ this._buffer.push(element);
+ },
+
+ /**
+ * draws a quad bezier path
+ * @override
+ * @param {cc.Point} origin
+ * @param {cc.Point} control
+ * @param {cc.Point} destination
+ * @param {Number} segments
+ * @param {Number} lineWidth
+ * @param {cc.Color} color
+ */
+ drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+
+ var vertices = [], t = 0.0;
+ for (var i = 0; i < segments; i++) {
+ var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
+ var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
+ vertices.push(cc.p(x, y));
+ t += 1.0 / segments;
+ }
+ vertices.push(cc.p(destination.x, destination.y));
+
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
+ element.verts = vertices;
+ element.lineWidth = lineWidth;
+ element.lineColor = color;
+ element.isStroke = true;
+ element.lineCap = "round";
+ this._buffer.push(element);
+ },
+
+ /**
+ * draws a cubic bezier path
+ * @override
+ * @param {cc.Point} origin
+ * @param {cc.Point} control1
+ * @param {cc.Point} control2
+ * @param {cc.Point} destination
+ * @param {Number} segments
+ * @param {Number} lineWidth
+ * @param {cc.Color} color
+ */
+ drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+
+ var vertices = [], t = 0;
+ for (var i = 0; i < segments; i++) {
+ var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
+ var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
+ vertices.push(cc.p(x, y));
+ t += 1.0 / segments;
+ }
+ vertices.push(cc.p(destination.x, destination.y));
+
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
+ element.verts = vertices;
+ element.lineWidth = lineWidth;
+ element.lineColor = color;
+ element.isStroke = true;
+ element.lineCap = "round";
+ this._buffer.push(element);
+ },
+
+ /**
+ * draw a CatmullRom curve
+ * @override
+ * @param {Array} points
+ * @param {Number} segments
+ * @param {Number} [lineWidth]
+ * @param {cc.Color} [color]
+ */
+ drawCatmullRom: function (points, segments, lineWidth, color) {
+ this.drawCardinalSpline(points, 0.5, segments, lineWidth, color);
+ },
+
+ /**
+ * draw a cardinal spline path
+ * @override
+ * @param {Array} config
+ * @param {Number} tension
+ * @param {Number} segments
+ * @param {Number} [lineWidth]
+ * @param {cc.Color} [color]
+ */
+ drawCardinalSpline: function (config, tension, segments, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+
+ var vertices = [], p, lt, deltaT = 1.0 / config.length;
+ for (var i = 0; i < segments + 1; i++) {
+ var dt = i / segments;
+ // border
+ if (dt === 1) {
+ p = config.length - 1;
+ lt = 1;
+ } else {
+ p = 0 | (dt / deltaT);
+ lt = (dt - deltaT * p) / deltaT;
+ }
+
+ // Interpolate
+ var newPos = cc.cardinalSplineAt(
+ cc.getControlPointAt(config, p - 1),
+ cc.getControlPointAt(config, p - 0),
+ cc.getControlPointAt(config, p + 1),
+ cc.getControlPointAt(config, p + 2),
+ tension, lt);
+ vertices.push(newPos);
+ }
+
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
+ element.verts = vertices;
+ element.lineWidth = lineWidth;
+ element.lineColor = color;
+ element.isStroke = true;
+ element.lineCap = "round";
+ this._buffer.push(element);
+ },
+
+ /**
+ * draw a dot at a position, with a given radius and color
+ * @param {cc.Point} pos
+ * @param {Number} radius
+ * @param {cc.Color} [color]
+ */
+ drawDot: function (pos, radius, color) {
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_DOT);
+ element.verts = [pos];
+ element.lineWidth = radius;
+ element.fillColor = color;
+ this._buffer.push(element);
+ },
+
+ /**
+ * draws an array of points.
+ * @override
+ * @param {Array} points point of array
+ * @param {Number} radius
+ * @param {cc.Color} [color]
+ */
+ drawDots: function (points, radius, color) {
+ if (!points || points.length == 0)
+ return;
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+ for (var i = 0, len = points.length; i < len; i++)
+ this.drawDot(points[i], radius, color);
+ },
+
+ /**
+ * draw a segment with a radius and color
+ * @param {cc.Point} from
+ * @param {cc.Point} to
+ * @param {Number} [lineWidth]
+ * @param {cc.Color} [color]
+ */
+ drawSegment: function (from, to, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
+ element.verts = [from, to];
+ element.lineWidth = lineWidth * 2;
+ element.lineColor = color;
+ element.isStroke = true;
+ element.lineCap = "round";
+ this._buffer.push(element);
+ },
+
+ /**
+ * draw a polygon with a fill color and line color without copying the vertex list
+ * @param {Array} verts
+ * @param {cc.Color|null} fillColor Fill color or `null` for a hollow polygon.
+ * @param {Number} [lineWidth]
+ * @param {cc.Color} [color]
+ */
+ drawPoly_: function (verts, fillColor, lineWidth, color) {
+ lineWidth = (lineWidth == null ) ? this._lineWidth : lineWidth;
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+ var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
+
+ element.verts = verts;
+ element.fillColor = fillColor;
+ element.lineWidth = lineWidth;
+ element.lineColor = color;
+ element.isClosePolygon = true;
+ element.isStroke = true;
+ element.lineCap = "round";
+ if (fillColor)
+ element.isFill = true;
+ this._buffer.push(element);
+ },
+
+ /**
+ * draw a polygon with a fill color and line color, copying the vertex list
+ * @param {Array} verts
+ * @param {cc.Color|null} fillColor Fill color or `null` for a hollow polygon.
+ * @param {Number} [lineWidth]
+ * @param {cc.Color} [lineColor]
+ */
+ drawPoly: function (verts, fillColor, lineWidth, lineColor) {
+ var vertsCopy = [];
+ for (var i = 0; i < verts.length; i++) {
+ vertsCopy.push(cc.p(verts[i].x, verts[i].y));
+ }
+ return this.drawPoly_(vertsCopy, fillColor, lineWidth, lineColor);
+ },
+
+ /**
+ * Clear the geometry in the node's buffer.
+ */
+ clear: function () {
+ this._buffer.length = 0;
+ },
+
+ _createRenderCmd: function () {
+ return new cc.DrawNode.CanvasRenderCmd(this);
+ }
+ });
+ }
+ else if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+
+ // 9600 vertices by default configurable in ccConfig.js
+ // 20 is 2 float for position, 4 int for color and 2 float for uv
+ var _sharedBuffer = null;
+ var FLOAT_PER_VERTEX = 2 + 1 + 2;
+ var VERTEX_BYTE = FLOAT_PER_VERTEX * 4;
+ var FLOAT_PER_TRIANGLE = 3 * FLOAT_PER_VERTEX;
+ var TRIANGLE_BYTES = FLOAT_PER_TRIANGLE * 4;
+ var MAX_INCREMENT = 200;
+
+ var _vertices = [],
+ _from = cc.p(),
+ _to = cc.p(),
+ _color = new Uint32Array(1);
+
+ // Used in drawSegment
+ var _n = cc.p(), _t = cc.p(), _nw = cc.p(), _tw = cc.p(),
+ _extrude = [];
+
+ cc.extend(cc.DrawNode.prototype, {
+ _bufferCapacity: 0,
+ _vertexCount: 0,
+
+ _offset: 0,
+ _occupiedSize: 0,
+ _f32Buffer: null,
+ _ui32Buffer: null,
+
+ _dirty: false,
+ _className: "DrawNodeWebGL",
+
+ manualRelease: false,
+
+ ctor: function (capacity, manualRelease) {
+ cc.Node.prototype.ctor.call(this);
+
+ if (!_sharedBuffer) {
+ _sharedBuffer = new GlobalVertexBuffer(cc._renderContext, cc.DRAWNODE_TOTAL_VERTICES * VERTEX_BYTE);
+ }
+
+ this._renderCmd._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_LENGTHTEXTURECOLOR);
+ this._blendFunc = new cc.BlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
+ this._drawColor = cc.color(255, 255, 255, 255);
+
+ this._bufferCapacity = capacity || 64;
+ this.manualRelease = manualRelease;
+
+ this._dirty = true;
+ },
+
+ onEnter: function () {
+ cc.Node.prototype.onEnter.call(this);
+ if (this._occupiedSize < this._bufferCapacity) {
+ this._ensureCapacity(this._bufferCapacity);
+ }
+ },
+
+ onExit: function () {
+ if (!this.manualRelease) {
+ this.release();
+ }
+ cc.Node.prototype.onExit.call(this);
+ },
+
+ release: function () {
+ if (this._occupiedSize > 0) {
+ this._vertexCount = 0;
+ _sharedBuffer.freeBuffer(this._offset, VERTEX_BYTE * this._occupiedSize);
+ this._occupiedSize = 0;
+ }
+ },
+
+ _ensureCapacity: function (count) {
+ var _t = this;
+ var prev = _t._occupiedSize;
+ var prevOffset = _t._offset;
+ if (count > prev || _t._bufferCapacity > prev) {
+ var request = Math.max(Math.min(prev + prev, MAX_INCREMENT), count, _t._bufferCapacity);
+ // free previous buffer
+ if (prev !== 0) {
+ _sharedBuffer.freeBuffer(prevOffset, VERTEX_BYTE * prev);
+ _t._occupiedSize = 0;
+ }
+ var offset = _t._offset = _sharedBuffer.requestBuffer(VERTEX_BYTE * request);
+ if (offset >= 0) {
+ _t._occupiedSize = _t._bufferCapacity = request;
+ // 5 floats per vertex
+ _t._f32Buffer = new Float32Array(_sharedBuffer.data, offset, FLOAT_PER_VERTEX * _t._occupiedSize);
+ _t._ui32Buffer = new Uint32Array(_sharedBuffer.data, offset, FLOAT_PER_VERTEX * _t._occupiedSize);
+
+ // Copy old data
+ if (prev !== 0 && prevOffset !== offset) {
+ // offset is in byte, we need to transform to float32 index
+ var last = prevOffset / 4 + prev * FLOAT_PER_VERTEX;
+ for (var i = offset / 4, j = prevOffset / 4; j < last; i++, j++) {
+ _sharedBuffer.dataArray[i] = _sharedBuffer.dataArray[j];
+ }
+ }
+
+ return true;
+ }
+ else {
+ cc.warn('Failed to allocate buffer for DrawNode: buffer for ' + request + ' vertices requested');
+ return false;
+ }
+ }
+ else {
+ return true;
+ }
+ },
+
+ drawRect: function (origin, destination, fillColor, lineWidth, lineColor) {
+ lineWidth = (lineWidth == null) ? this._lineWidth : lineWidth;
+ lineColor = lineColor || this._drawColor;
+ _vertices.length = 0;
+ _vertices.push(origin.x, origin.y, destination.x, origin.y, destination.x, destination.y, origin.x, destination.y);
+ if (fillColor == null)
+ this._drawSegments(_vertices, lineWidth, lineColor, true);
+ else
+ this.drawPoly(_vertices, fillColor, lineWidth, lineColor);
+ _vertices.length = 0;
+ },
+
+ drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this._drawColor;
+ var coef = 2.0 * Math.PI / segments, i, len;
+ _vertices.length = 0;
+ for (i = 0; i <= segments; i++) {
+ var rads = i * coef;
+ var j = radius * Math.cos(rads + angle) + center.x;
+ var k = radius * Math.sin(rads + angle) + center.y;
+ _vertices.push(j, k);
+ }
+ if (drawLineToCenter)
+ _vertices.push(center.x, center.y);
+
+ lineWidth *= 0.5;
+ for (i = 0, len = _vertices.length - 2; i < len; i += 2) {
+ _from.x = _vertices[i];
+ _from.y = _vertices[i + 1];
+ _to.x = _vertices[i + 2];
+ _to.y = _vertices[i + 3];
+ this.drawSegment(_from, _to, lineWidth, color);
+ }
+ _vertices.length = 0;
+ },
+
+ drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this._drawColor;
+ var t = 0.0;
+ _vertices.length = 0;
+ for (var i = 0; i < segments; i++) {
+ var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
+ var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
+ _vertices.push(x, y);
+ t += 1.0 / segments;
+ }
+ _vertices.push(destination.x, destination.y);
+ this._drawSegments(_vertices, lineWidth, color, false);
+ _vertices.length = 0;
+ },
+
+ drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this._drawColor;
+ var t = 0;
+ _vertices.length = 0;
+ for (var i = 0; i < segments; i++) {
+ var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
+ var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
+ _vertices.push(x, y);
+ t += 1.0 / segments;
+ }
+ _vertices.push(destination.x, destination.y);
+ this._drawSegments(_vertices, lineWidth, color, false);
+ _vertices.length = 0;
+ },
+
+ drawCatmullRom: function (points, segments, lineWidth, color) {
+ this.drawCardinalSpline(points, 0.5, segments, lineWidth, color);
+ },
+
+ drawCardinalSpline: function (config, tension, segments, lineWidth, color) {
+ lineWidth = lineWidth || this._lineWidth;
+ color = color || this._drawColor;
+ var p, lt, deltaT = 1.0 / config.length;
+ _vertices.length = 0;
+
+ for (var i = 0; i < segments + 1; i++) {
+ var dt = i / segments;
+
+ // border
+ if (dt === 1) {
+ p = config.length - 1;
+ lt = 1;
+ } else {
+ p = 0 | (dt / deltaT);
+ lt = (dt - deltaT * p) / deltaT;
+ }
+
+ // Interpolate
+ cc.cardinalSplineAt(
+ cc.getControlPointAt(config, p - 1),
+ cc.getControlPointAt(config, p - 0),
+ cc.getControlPointAt(config, p + 1),
+ cc.getControlPointAt(config, p + 2),
+ tension, lt, _from);
+ _vertices.push(_from.x, _from.y);
+ }
+
+ lineWidth *= 0.5;
+ for (var j = 0, len = _vertices.length - 2; j < len; j += 2) {
+ _from.x = _vertices[j];
+ _from.y = _vertices[j + 1];
+ _to.x = _vertices[j + 2];
+ _to.y = _vertices[j + 3];
+ this.drawSegment(_from, _to, lineWidth, color);
+ }
+ _vertices.length = 0;
+ },
+
+ drawDots: function (points, radius, color) {
+ if (!points || points.length === 0)
+ return;
+ color = color || this._drawColor;
+ for (var i = 0, len = points.length; i < len; i++) {
+ this.drawDot(points[i], radius, color);
+ }
+ },
+
+ _render: function () {
+ var gl = cc._renderContext;
+ if (this._offset < 0 || this._vertexCount <= 0) {
+ return;
+ }
+
+ if (this._dirty) {
+ // bindBuffer is done in updateSubData
+ _sharedBuffer.updateSubData(this._offset, this._f32Buffer);
+ this._dirty = false;
+ }
+ else {
+ gl.bindBuffer(gl.ARRAY_BUFFER, _sharedBuffer.vertexBuffer);
+ }
+
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR);
+ gl.enableVertexAttribArray(cc.VERTEX_ATTRIB_TEX_COORDS);
+
+ // vertex
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, VERTEX_BYTE, 0);
+ // color
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, VERTEX_BYTE, 8);
+ // texcood
+ gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, VERTEX_BYTE, 12);
+
+ gl.drawArrays(gl.TRIANGLES, this._offset / VERTEX_BYTE, this._vertexCount);
+ cc.incrementGLDraws(1);
+ //cc.checkGLErrorDebug();
+ },
+
+ appendVertexData: function (x, y, color, u, v) {
+ var f32Buffer = this._f32Buffer;
+ // Float offset = byte offset / 4 + vertex count * floats by vertex
+ var offset = this._vertexCount * FLOAT_PER_VERTEX;
+ f32Buffer[offset] = x;
+ f32Buffer[offset + 1] = y;
+ _color[0] = ((color.a << 24) | (color.b << 16) | (color.g << 8) | color.r);
+ this._ui32Buffer[offset + 2] = _color[0];
+ f32Buffer[offset + 3] = u;
+ f32Buffer[offset + 4] = v;
+ this._vertexCount++;
+ },
+
+ drawDot: function (pos, radius, color) {
+ color = color || this._drawColor;
+ if (color.a == null)
+ color.a = 255;
+ var l = pos.x - radius,
+ b = pos.y - radius,
+ r = pos.x + radius,
+ t = pos.y + radius;
+
+ var vertexCount = 2 * 3;
+ var succeed = this._ensureCapacity(this._vertexCount + vertexCount);
+ if (!succeed)
+ return;
+
+ // lb, lt, rt, lb, rt, rb
+ this.appendVertexData(l, b, color, -1, -1);
+ this.appendVertexData(l, t, color, -1, 1);
+ this.appendVertexData(r, t, color, 1, 1);
+ this.appendVertexData(l, b, color, -1, -1);
+ this.appendVertexData(r, t, color, 1, 1);
+ this.appendVertexData(r, b, color, 1, -1);
+
+ this._dirty = true;
+ },
+
+ drawSegment: function (from, to, radius, color) {
+ color = color || this.getDrawColor();
+ if (color.a == null)
+ color.a = 255;
+ radius = radius || (this._lineWidth * 0.5);
+ var vertexCount = 6 * 3;
+ var succeed = this._ensureCapacity(this._vertexCount + vertexCount);
+ if (!succeed)
+ return;
+
+ var a = from, b = to;
+ // var n = normalize(perp(sub(b, a)))
+ _n.x = a.y - b.y; _n.y = b.x - a.x;
+ cc.pNormalizeIn(_n);
+ // var t = perp(n);
+ _t.x = -_n.y; _t.y = _n.x;
+ // var nw = mult(n, radius), tw = mult(t, radius);
+ pMultOut(_n, radius, _nw);
+ pMultOut(_t, radius, _tw);
+
+ // var v0 = sub(b, add(nw, tw)); uv0 = neg(add(n, t))
+ var v0x = b.x - _nw.x - _tw.x, v0y = b.y - _nw.y - _tw.y, u0 = -(_n.x + _t.x), v0 = -(_n.y + _t.y);
+ // var v1 = add(b, sub(nw, tw)); uv1 = sub(n, t)
+ var v1x = b.x + _nw.x - _tw.x, v1y = b.y + _nw.y - _tw.y, u1 = _n.x - _t.x, v1 = _n.y - _t.y;
+ // var v2 = sub(b, nw); uv2 = neg(n)
+ var v2x = b.x - _nw.x, v2y = b.y - _nw.y, u2 = -_n.x, v2 = -_n.y;
+ // var v3 = add(b, nw); uv3 = n
+ var v3x = b.x + _nw.x, v3y = b.y + _nw.y, u3 = _n.x, v3 = _n.y;
+ // var v4 = sub(a, nw); uv4 = neg(n)
+ var v4x = a.x - _nw.x, v4y = a.y - _nw.y, u4 = u2, v4 = v2;
+ // var v5 = add(a, nw); uv5 = n
+ var v5x = a.x + _nw.x, v5y = a.y + _nw.y, u5 = _n.x, v5 = _n.y;
+ // var v6 = sub(a, sub(nw, tw)); uv6 = sub(t, n)
+ var v6x = a.x - _nw.x + _tw.x, v6y = a.y - _nw.y + _tw.y, u6 = _t.x - _n.x, v6 = _t.y - _n.y;
+ // var v7 = add(a, add(nw, tw)); uv7 = add(n, t)
+ var v7x = a.x + _nw.x + _tw.x, v7y = a.y + _nw.y + _tw.y, u7 = _n.x + _t.x, v7 = _n.y + _t.y;
+
+ this.appendVertexData(v0x, v0y, color, u0, v0);
+ this.appendVertexData(v1x, v1y, color, u1, v1);
+ this.appendVertexData(v2x, v2y, color, u2, v2);
+
+ this.appendVertexData(v3x, v3y, color, u3, v3);
+ this.appendVertexData(v1x, v1y, color, u1, v1);
+ this.appendVertexData(v2x, v2y, color, u2, v2);
+
+ this.appendVertexData(v3x, v3y, color, u3, v3);
+ this.appendVertexData(v4x, v4y, color, u4, v4);
+ this.appendVertexData(v2x, v2y, color, u2, v2);
+
+ this.appendVertexData(v3x, v3y, color, u3, v3);
+ this.appendVertexData(v4x, v4y, color, u4, v4);
+ this.appendVertexData(v5x, v5y, color, u5, v5);
+
+ this.appendVertexData(v6x, v6y, color, u6, v6);
+ this.appendVertexData(v4x, v4y, color, u4, v4);
+ this.appendVertexData(v5x, v5y, color, u5, v5);
+
+ this.appendVertexData(v6x, v6y, color, u6, v6);
+ this.appendVertexData(v7x, v7y, color, u7, v7);
+ this.appendVertexData(v5x, v5y, color, u5, v5);
+ this._dirty = true;
+ },
+
+ drawPoly: function (verts, fillColor, borderWidth, borderColor) {
+ // Backward compatibility
+ if (typeof verts[0] === 'object') {
+ _vertices.length = 0;
+ for (var i = 0; i < verts.length; i++) {
+ _vertices.push(verts[i].x, verts[i].y);
+ }
+ verts = _vertices;
+ }
+
+ if (fillColor == null) {
+ this._drawSegments(verts, borderWidth, borderColor, true);
+ return;
+ }
+ if (fillColor.a == null)
+ fillColor.a = 255;
+ if (borderColor.a == null)
+ borderColor.a = 255;
+ borderWidth = (borderWidth == null) ? this._lineWidth : borderWidth;
+ borderWidth *= 0.5;
+ var v0x, v0y, v1x, v1y, v2x, v2y,
+ factor, offx, offy,
+ i, count = verts.length;
+ _extrude.length = 0;
+ for (i = 0; i < count; i += 2) {
+ v0x = verts[(i - 2 + count) % count];
+ v0y = verts[(i - 1 + count) % count];
+ v1x = verts[i];
+ v1y = verts[i + 1];
+ v2x = verts[(i + 2) % count];
+ v2y = verts[(i + 3) % count];
+ // var n1 = normalize(perp(sub(v1, v0)));
+ // var n2 = normalize(perp(sub(v2, v1)));
+ _n.x = v0y - v1y; _n.y = v1x - v0x;
+ _nw.x = v1y - v2y; _nw.y = v2x - v1x;
+ cc.pNormalizeIn(_n);
+ cc.pNormalizeIn(_nw);
+ // var offset = mult(add(n1, n2), 1.0 / (dot(n1, n2) + 1.0));
+ factor = _n.x * _nw.x + _n.y * _nw.y + 1;
+ offx = (_n.x + _nw.x) / factor;
+ offy = (_n.y + _nw.y) / factor;
+ // extrude[i] = {offset: offset, n: n2};
+ _extrude.push(offx, offy, _nw.x, _nw.y);
+ }
+ // The actual input vertex count
+ count = count / 2;
+ var outline = (borderWidth > 0.0), triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount;
+ var succeed = this._ensureCapacity(this._vertexCount + vertexCount);
+ if (!succeed)
+ return;
+
+ var inset = (outline == false ? 0.5 : 0.0);
+ for (i = 0; i < count - 2; i++) {
+ // v0 = sub(verts[0], multi(extrude[0].offset, inset));
+ v0x = verts[0] - _extrude[0] * inset;
+ v0y = verts[1] - _extrude[1] * inset;
+ // v1 = sub(verts[i + 1], multi(extrude[i + 1].offset, inset));
+ v1x = verts[i * 2 + 2] - _extrude[(i + 1) * 4] * inset;
+ v1y = verts[i * 2 + 3] - _extrude[(i + 1) * 4 + 1] * inset;
+ // v2 = sub(verts[i + 2], multi(extrude[i + 2].offset, inset));
+ v2x = verts[i * 2 + 4] - _extrude[(i + 2) * 4] * inset;
+ v2y = verts[i * 2 + 5] - _extrude[(i + 2) * 4 + 1] * inset;
+
+ this.appendVertexData(v0x, v0y, fillColor, 0, 0);
+ this.appendVertexData(v1x, v1y, fillColor, 0, 0);
+ this.appendVertexData(v2x, v2y, fillColor, 0, 0);
+ }
+
+ var off0x, off0y, off1x, off1y,
+ bw = outline ? borderWidth : 0.5,
+ color = outline ? borderColor : fillColor,
+ in0x, in0y, in1x, in1y, out0x, out0y, out1x, out1y;
+ for (i = 0; i < count; i++) {
+ var j = (i + 1) % count;
+ v0x = verts[i * 2];
+ v0y = verts[i * 2 + 1];
+ v1x = verts[j * 2];
+ v1y = verts[j * 2 + 1];
+
+ _n.x = _extrude[i * 4 + 2];
+ _n.y = _extrude[i * 4 + 3];
+ _nw.x = outline ? -_n.x : 0;
+ _nw.y = outline ? -_n.y : 0;
+ off0x = _extrude[i * 4];
+ off0y = _extrude[i * 4 + 1];
+ off1x = _extrude[j * 4];
+ off1y = _extrude[j * 4 + 1];
+
+ in0x = v0x - off0x * bw; in0y = v0y - off0y * bw;
+ in1x = v1x - off1x * bw; in1y = v1y - off1y * bw;
+ out0x = v0x + off0x * bw; out0y = v0y + off0y * bw;
+ out1x = v1x + off1x * bw; out1y = v1y + off1y * bw;
+
+ this.appendVertexData(in0x, in0y, color, _nw.x, _nw.y);
+ this.appendVertexData(in1x, in1y, color, _nw.x, _nw.y);
+ this.appendVertexData(out1x, out1y, color, _n.x, _n.y);
+
+ this.appendVertexData(in0x, in0y, color, _nw.x, _nw.y);
+ this.appendVertexData(out0x, out0y, color, _n.x, _n.y);
+ this.appendVertexData(out1x, out1y, color, _n.x, _n.y);
+ }
+ _extrude.length = 0;
+ _vertices.length = 0;
+ this._dirty = true;
+ },
+
+ _drawSegments: function (verts, borderWidth, borderColor, closePoly) {
+ borderWidth = (borderWidth == null) ? this._lineWidth : borderWidth;
+ if (borderWidth <= 0)
+ return;
+
+ borderColor = borderColor || this._drawColor;
+ if (borderColor.a == null)
+ borderColor.a = 255;
+ borderWidth *= 0.5;
+
+ var v0x, v0y, v1x, v1y, v2x, v2y,
+ factor, offx, offy,
+ i, count = verts.length;
+ _extrude.length = 0;
+ for (i = 0; i < count; i += 2) {
+ v0x = verts[(i - 2 + count) % count];
+ v0y = verts[(i - 1 + count) % count];
+ v1x = verts[i];
+ v1y = verts[i + 1];
+ v2x = verts[(i + 2) % count];
+ v2y = verts[(i + 3) % count];
+ // var n1 = normalize(perp(sub(v1, v0)));
+ // var n2 = normalize(perp(sub(v2, v1)));
+ _n.x = v0y - v1y; _n.y = v1x - v0x;
+ _nw.x = v1y - v2y; _nw.y = v2x - v1x;
+ cc.pNormalizeIn(_n);
+ cc.pNormalizeIn(_nw);
+ // var offset = multi(add(n1, n2), 1.0 / (dot(n1, n2) + 1.0));
+ factor = _n.x * _nw.x + _n.y * _nw.y + 1;
+ offx = (_n.x + _nw.x) / factor;
+ offy = (_n.y + _nw.y) / factor;
+ // extrude[i] = {offset: offset, n: n2};
+ _extrude.push(offx, offy, _nw.x, _nw.y);
+ }
+
+ // The actual input vertex count
+ count = count / 2;
+ var triangleCount = 3 * count - 2, vertexCount = 3 * triangleCount;
+ var succeed = this._ensureCapacity(this._vertexCount + vertexCount);
+ if (!succeed)
+ return;
+
+ var len = closePoly ? count : count - 1,
+ off0x, off0y, off1x, off1y,
+ in0x, in0y, in1x, in1y, out0x, out0y, out1x, out1y;
+ for (i = 0; i < len; i++) {
+ var j = (i + 1) % count;
+ v0x = verts[i * 2];
+ v0y = verts[i * 2 + 1];
+ v1x = verts[j * 2];
+ v1y = verts[j * 2 + 1];
+
+ _n.x = _extrude[i * 4 + 2];
+ _n.y = _extrude[i * 4 + 3];
+ off0x = _extrude[i * 4];
+ off0y = _extrude[i * 4 + 1];
+ off1x = _extrude[j * 4];
+ off1y = _extrude[j * 4 + 1];
+ in0x = v0x - off0x * borderWidth; in0y = v0y - off0y * borderWidth;
+ in1x = v1x - off1x * borderWidth; in1y = v1y - off1y * borderWidth;
+ out0x = v0x + off0x * borderWidth; out0y = v0y + off0y * borderWidth;
+ out1x = v1x + off1x * borderWidth; out1y = v1y + off1y * borderWidth;
+
+ this.appendVertexData(in0x, in0y, borderColor, -_n.x, -_n.y);
+ this.appendVertexData(in1x, in1y, borderColor, -_n.x, -_n.y);
+ this.appendVertexData(out1x, out1y, borderColor, _n.x, _n.y);
+
+ this.appendVertexData(in0x, in0y, borderColor, -_n.x, -_n.y);
+ this.appendVertexData(out0x, out0y, borderColor, _n.x, _n.y);
+ this.appendVertexData(out1x, out1y, borderColor, _n.x, _n.y);
+ }
+ _extrude.length = 0;
+ this._dirty = true;
+ },
+
+ clear: function () {
+ this.release();
+ this._dirty = true;
+ },
+
+ _createRenderCmd: function () {
+ return new cc.DrawNode.WebGLRenderCmd(this);
+ }
+ });
+ }
+});
diff --git a/cocos2d/shape-nodes/CCDrawNodeCanvasRenderCmd.js b/cocos2d/shape-nodes/CCDrawNodeCanvasRenderCmd.js
new file mode 100644
index 0000000000..92189454b7
--- /dev/null
+++ b/cocos2d/shape-nodes/CCDrawNodeCanvasRenderCmd.js
@@ -0,0 +1,138 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+
+ cc.DrawNode.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._buffer = null;
+ this._drawColor = null;
+ this._blendFunc = null;
+ };
+
+
+ cc.DrawNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ cc.DrawNode.CanvasRenderCmd.prototype.constructor = cc.DrawNode.CanvasRenderCmd;
+
+ cc.DrawNode.CanvasRenderCmd.prototype.getLocalBB = function () {
+ var node = this._node;
+ return node._localBB;
+ };
+
+ cc.extend(cc.DrawNode.CanvasRenderCmd.prototype, {
+ rendering: function (ctx, scaleX, scaleY) {
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext(), node = this._node;
+ var alpha = this._displayedOpacity / 255;
+ if (alpha === 0)
+ return;
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+
+ //context.save();
+ wrapper.setGlobalAlpha(alpha);
+ if ((this._blendFunc && (this._blendFunc.src === cc.SRC_ALPHA) && (this._blendFunc.dst === cc.ONE)))
+ wrapper.setCompositeOperation('lighter'); //todo: need refactor
+ var locBuffer = this._buffer;
+ for (var i = 0, len = locBuffer.length; i < len; i++) {
+ var element = locBuffer[i];
+ switch (element.type) {
+ case cc.DrawNode.TYPE_DOT:
+ this._drawDot(wrapper, element, scaleX, scaleY);
+ break;
+ case cc.DrawNode.TYPE_SEGMENT:
+ this._drawSegment(wrapper, element, scaleX, scaleY);
+ break;
+ case cc.DrawNode.TYPE_POLY:
+ this._drawPoly(wrapper, element, scaleX, scaleY);
+ break;
+ }
+ }
+ //context.restore(); //todo It can be reserve
+ },
+
+ _drawDot: function (wrapper, element) {
+ var locColor = element.fillColor, locPos = element.verts[0], locRadius = element.lineWidth;
+
+ var ctx = wrapper.getContext();
+ wrapper.setFillStyle("rgba(" + (0 | locColor.r) + "," + (0 | locColor.g) + "," + (0 | locColor.b) + "," + locColor.a / 255 + ")");
+
+ ctx.beginPath();
+ ctx.arc(locPos.x, -locPos.y, locRadius, 0, Math.PI * 2, false);
+ ctx.closePath();
+ ctx.fill();
+ },
+
+ _drawSegment: function (wrapper, element, scaleX) {
+ var locColor = element.lineColor;
+ var locFrom = element.verts[0], locTo = element.verts[1];
+ var locLineWidth = element.lineWidth, locLineCap = element.lineCap;
+
+ var ctx = wrapper.getContext();
+ wrapper.setStrokeStyle("rgba(" + (0 | locColor.r) + "," + (0 | locColor.g) + "," + (0 | locColor.b) + "," + locColor.a / 255 + ")");
+
+ ctx.lineWidth = locLineWidth * scaleX;
+ ctx.beginPath();
+ ctx.lineCap = locLineCap;
+ ctx.moveTo(locFrom.x, -locFrom.y);
+ ctx.lineTo(locTo.x, -locTo.y);
+ ctx.stroke();
+ },
+
+ _drawPoly: function (wrapper, element, scaleX) {
+ var locVertices = element.verts, locLineCap = element.lineCap;
+ if (locVertices == null)
+ return;
+
+ var locFillColor = element.fillColor, locLineWidth = element.lineWidth;
+ var locLineColor = element.lineColor, locIsClosePolygon = element.isClosePolygon;
+ var locIsFill = element.isFill, locIsStroke = element.isStroke;
+
+ var ctx = wrapper.getContext();
+ var firstPoint = locVertices[0];
+ ctx.lineCap = locLineCap;
+ if (locFillColor)
+ wrapper.setFillStyle("rgba(" + (0 | locFillColor.r) + "," + (0 | locFillColor.g) + ","
+ + (0 | locFillColor.b) + "," + locFillColor.a / 255 + ")");
+ if (locLineWidth)
+ ctx.lineWidth = locLineWidth * scaleX;
+ if (locLineColor)
+ wrapper.setStrokeStyle("rgba(" + (0 | locLineColor.r) + "," + (0 | locLineColor.g) + ","
+ + (0 | locLineColor.b) + "," + locLineColor.a / 255 + ")");
+
+ ctx.beginPath();
+ ctx.moveTo(firstPoint.x, -firstPoint.y);
+ for (var i = 1, len = locVertices.length; i < len; i++)
+ ctx.lineTo(locVertices[i].x, -locVertices[i].y);
+
+ if (locIsClosePolygon)
+ ctx.closePath();
+ if (locIsFill)
+ ctx.fill();
+ if (locIsStroke)
+ ctx.stroke();
+ }
+ });
+
+})();
diff --git a/cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js b/cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js
new file mode 100644
index 0000000000..cd7ea5125c
--- /dev/null
+++ b/cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js
@@ -0,0 +1,52 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.DrawNode.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ };
+
+ cc.DrawNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ cc.DrawNode.WebGLRenderCmd.prototype.constructor = cc.DrawNode.WebGLRenderCmd;
+
+ cc.DrawNode.WebGLRenderCmd.prototype.rendering = function (ctx) {
+ var node = this._node;
+ if (node._vertexCount > 0) {
+ var wt = this._worldTransform;
+ this._matrix.mat[0] = wt.a;
+ this._matrix.mat[4] = wt.c;
+ this._matrix.mat[12] = wt.tx;
+ this._matrix.mat[1] = wt.b;
+ this._matrix.mat[5] = wt.d;
+ this._matrix.mat[13] = wt.ty;
+
+ cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst);
+ this._glProgramState.apply(this._matrix);
+ node._render();
+ }
+ };
+})();
diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js
deleted file mode 100644
index 2251710e9d..0000000000
--- a/cocos2d/sprite_nodes/CCSprite.js
+++ /dev/null
@@ -1,2255 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * cc.Sprite invalid index on the cc.SpriteBatchNode
- * @constant
- * @type Number
- */
-cc.SPRITE_INDEX_NOT_INITIALIZED = -1;
-
-/**
- * generate texture's cache for texture tint
- * @function
- * @param {HTMLImageElement} texture
- * @return {Array}
- */
-
-cc.generateTextureCacheForColor = function (texture) {
- if (texture.hasOwnProperty('channelCache')) {
- return texture.channelCache;
- }
-
- var textureCache = [
- document.createElement("canvas"),
- document.createElement("canvas"),
- document.createElement("canvas"),
- document.createElement("canvas")
- ];
-
- function renderToCache() {
- var ref = cc.generateTextureCacheForColor;
-
- var w = texture.width;
- var h = texture.height;
-
- textureCache[0].width = w;
- textureCache[0].height = h;
- textureCache[1].width = w;
- textureCache[1].height = h;
- textureCache[2].width = w;
- textureCache[2].height = h;
- textureCache[3].width = w;
- textureCache[3].height = h;
-
- ref.canvas.width = w;
- ref.canvas.height = h;
-
- var ctx = ref.canvas.getContext("2d");
- ctx.drawImage(texture, 0, 0);
-
- ref.tempCanvas.width = w;
- ref.tempCanvas.height = h;
-
- var pixels = ctx.getImageData(0, 0, w, h).data;
-
- for (var rgbI = 0; rgbI < 4; rgbI++) {
- var cacheCtx = textureCache[rgbI].getContext('2d');
- cacheCtx.getImageData(0, 0, w, h).data;
- ref.tempCtx.drawImage(texture, 0, 0);
-
- var to = ref.tempCtx.getImageData(0, 0, w, h);
- var toData = to.data;
-
- for (var i = 0; i < pixels.length; i += 4) {
- toData[i ] = (rgbI === 0) ? pixels[i ] : 0;
- toData[i + 1] = (rgbI === 1) ? pixels[i + 1] : 0;
- toData[i + 2] = (rgbI === 2) ? pixels[i + 2] : 0;
- toData[i + 3] = pixels[i + 3];
- }
- cacheCtx.putImageData(to, 0, 0);
- }
- texture.onload = null;
- }
-
- try {
- renderToCache();
- } catch (e) {
- texture.onload = renderToCache;
- }
-
- texture.channelCache = textureCache;
- return textureCache;
-};
-
-cc.generateTextureCacheForColor.canvas = document.createElement('canvas');
-cc.generateTextureCacheForColor.tempCanvas = document.createElement('canvas');
-cc.generateTextureCacheForColor.tempCtx = cc.generateTextureCacheForColor.tempCanvas.getContext('2d');
-
-/**
- * generate tinted texture
- * source-in: Where source and destination overlaps and both are opaque, the source is displayed.
- * Everywhere else transparency is displayed.
- * @function
- * @param {HTMLImageElement} texture
- * @param {cc.Color3B|cc.Color4F} color
- * @param {cc.Rect} rect
- * @return {HTMLCanvasElement}
- */
-cc.generateTintImage2 = function (texture, color, rect) {
- if (!rect) {
- rect = cc.rect(0, 0, texture.width, texture.height);
- rect = cc.RECT_PIXELS_TO_POINTS(rect);
- }
- var selColor;
- if (color instanceof cc.Color4F) {
- selColor = cc.c4b(color.r * 255, color.g * 255, color.b * 255, color.a * 255);
- } else {
- selColor = cc.c4b(color.r, color.g, color.b, 50);//color;
- }
-
- var buff = document.createElement("canvas");
- var ctx = buff.getContext("2d");
-
- if (buff.width != rect.width) buff.width = rect.width;
- if (buff.height != rect.height) buff.height = rect.height;
- ctx.save();
-
- ctx.drawImage(texture, rect.x, rect.y, rect.width, rect.height, 0, 0, rect.width, rect.height);
-
- ctx.globalCompositeOperation = "source-in";
- ctx.globalAlpha = selColor.a / 255.0;
- ctx.fillStyle = "rgb(" + selColor.r + "," + selColor.g + "," + selColor.b + ")";
- ctx.fillRect(0, 0, rect.width, rect.height);
- ctx.restore();
-
- return buff;
-};
-
-/**
- * generate tinted texture
- * lighter: The source and destination colors are added to each other, resulting in brighter colors,
- * moving towards color values of 1 (maximum brightness for that color).
- * @function
- * @param {HTMLImageElement} texture
- * @param {Array} tintedImgCache
- * @param {cc.Color3B|cc.Color4F} color
- * @param {cc.Rect} rect
- * @param {HTMLCanvasElement} [renderCanvas]
- * @return {HTMLCanvasElement}
- */
-cc.generateTintImage = function (texture, tintedImgCache, color, rect, renderCanvas) {
- if (!rect)
- rect = cc.rect(0, 0, texture.width, texture.height);
-
- var selColor;
- if (color.a == null) {
- // Optimization for the particle system which mainly uses c4f colors
- selColor = cc.c4f(color.r / 255.0, color.g / 255.0, color.b / 255, 1);
- } else {
- selColor = color;
- }
-
- var w = Math.min(rect.width, tintedImgCache[0].width);
- var h = Math.min(rect.height, tintedImgCache[0].height);
- var buff = renderCanvas;
- var ctx;
-
- // Create a new buffer if required
- if (!buff) {
- buff = document.createElement("canvas");
- buff.width = w;
- buff.height = h;
- ctx = buff.getContext("2d");
- } else {
- ctx = buff.getContext("2d");
- ctx.clearRect(0, 0, w, h);
- }
-
- ctx.save();
- ctx.globalCompositeOperation = 'lighter';
-
- // Make sure to keep the renderCanvas alpha in mind in case of overdraw
- var a = ctx.globalAlpha;
- if (selColor.r > 0) {
- ctx.globalAlpha = selColor.r * a;
- ctx.drawImage(tintedImgCache[0], rect.x, rect.y, w, h, 0, 0, w, h);
- }
- if (selColor.g > 0) {
- ctx.globalAlpha = selColor.g * a;
- ctx.drawImage(tintedImgCache[1], rect.x, rect.y, w, h, 0, 0, w, h);
- }
- if (selColor.b > 0) {
- ctx.globalAlpha = selColor.b * a;
- ctx.drawImage(tintedImgCache[2], rect.x, rect.y, w, h, 0, 0, w, h);
- }
-
- if ((selColor.r === 0) && (selColor.g === 0) && (selColor.b === 0)) {
- ctx.globalAlpha = a;
- ctx.drawImage(tintedImgCache[3], rect.x, rect.y, w, h, 0, 0, w, h);
- }
-
- ctx.restore();
- return buff;
-};
-
-cc.cutRotateImageToCanvas = function (texture, rect) {
- if (!texture)
- return null;
-
- if (!rect)
- return texture;
-
- var nCanvas = document.createElement("canvas");
- nCanvas.width = rect.width;
- nCanvas.height = rect.height;
-
- var ctx = nCanvas.getContext("2d");
- ctx.translate(nCanvas.width / 2, nCanvas.height / 2);
- ctx.rotate(-1.5707963267948966);
- ctx.drawImage(texture, rect.x, rect.y, rect.height, rect.width, -rect.height / 2, -rect.width / 2, rect.height, rect.width);
- return nCanvas;
-};
-
-/**
- * a Values object for transform
- * @Class
- * @Construct
- * @param {cc.Point} pos position x and y
- * @param {cc.Point} scale scale x and y
- * @param {Number} rotation
- * @param {cc.Point} skew skew x and y
- * @param {cc.Point} ap anchor point in pixels
- * @param {Boolean} visible
- */
-cc.TransformValues = function (pos, scale, rotation, skew, ap, visible) {
- this.pos = pos; // position x and y
- this.scale = scale; // scale x and y
- this.rotation = rotation;
- this.skew = skew; // skew x and y
- this.ap = ap; // anchor point in pixels
- this.visible = visible;
-};
-
-cc.RENDER_IN_SUBPIXEL = function (A) {
- return (0 | A);
-};
-if (cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) {
- cc.RENDER_IN_SUBPIXEL = function (A) {
- return A;
- };
-}
-
-/**
- * cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) )
- *
- * cc.Sprite can be created with an image, or with a sub-rectangle of an image.
- *
- * If the parent or any of its ancestors is a cc.SpriteBatchNode then the following features/limitations are valid
- * - Features when the parent is a cc.BatchNode:
- * - MUCH faster rendering, specially if the cc.SpriteBatchNode has many children. All the children will be drawn in a single batch.
- *
- * - Limitations
- * - Camera is not supported yet (eg: CCOrbitCamera action doesn't work)
- * - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl)
- * - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property.
- * - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property.
- * - Parallax scroller is not supported, but can be simulated with a "proxy" sprite.
- *
- * If the parent is an standard cc.Node, then cc.Sprite behaves like any other cc.Node:
- * - It supports blending functions
- * - It supports aliasing / antialiasing
- * - But the rendering will be slower: 1 draw per children.
- *
- * The default anchorPoint in cc.Sprite is (0.5, 0.5).
- * @class
- * @extends cc.NodeRGBA
- *
- * @example
- * var aSprite = new cc.Sprite();
- * aSprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320));
- */
-cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{
- RGBAProtocol:true,
- //
- // Data used when the sprite is rendered using a CCSpriteSheet
- //
- _textureAtlas:null, //cc.SpriteBatchNode texture atlas
-
- _atlasIndex:0,
- _batchNode:null,
- _dirty:false, //Whether the sprite needs to be updated
- _recursiveDirty:null, //Whether all of the sprite's children needs to be updated
- _hasChildren:null, //Whether the sprite contains children
- _shouldBeHidden:false, //should not be drawn because one of the ancestors is not visible
- _transformToBatch:null,
-
- //
- // Data used when the sprite is self-rendered
- //
- _blendFunc:null, //It's required for CCTextureProtocol inheritance
- _texture:null, //cc.Texture2D object that is used to render the sprite
-
- //
- // Shared data
- //
- // texture
- _rect:null, //Retangle of cc.Texture2D
- _rectRotated:false, //Whether the texture is rotated
-
- // Offset Position (used by Zwoptex)
- _offsetPosition:null, // absolute
- _unflippedOffsetPositionFromCenter:null,
-
- _opacityModifyRGB:false,
-
- // image is flipped
- _flippedX:false, //Whether the sprite is flipped horizontally or not.
- _flippedY:false, //Whether the sprite is flipped vertically or not.
-
- _textureLoaded:false,
- _loadedEventListeners: null,
- _newTextureWhenChangeColor: null, //hack property for LabelBMFont
-
- textureLoaded:function(){
- return this._textureLoaded;
- },
-
- addLoadedEventListener:function(callback, target){
- this._loadedEventListeners.push({eventCallback:callback, eventTarget:target});
- },
-
- _callLoadedEventCallbacks:function(){
- var locListeners = this._loadedEventListeners;
- for(var i = 0, len = locListeners.length; i < len; i++){
- var selCallback = locListeners[i];
- selCallback.eventCallback.call(selCallback.eventTarget, this);
- }
- locListeners.length = 0;
- },
-
- /**
- * Whether or not the Sprite needs to be updated in the Atlas
- * @return {Boolean} true if the sprite needs to be updated in the Atlas, false otherwise.
- */
- isDirty:function () {
- return this._dirty;
- },
-
- /**
- * Makes the Sprite to be updated in the Atlas.
- * @param {Boolean} bDirty
- */
- setDirty:function (bDirty) {
- this._dirty = bDirty;
- },
-
- /**
- * Returns whether or not the texture rectangle is rotated.
- * @return {Boolean}
- */
- isTextureRectRotated:function () {
- return this._rectRotated;
- },
-
- /**
- * Returns the index used on the TextureAtlas.
- * @return {Number}
- */
- getAtlasIndex:function () {
- return this._atlasIndex;
- },
-
- /**
- * Set the index used on the TextureAtlas.
- * @warning Don't modify this value unless you know what you are doing
- * @param {Number} atlasIndex
- */
- setAtlasIndex:function (atlasIndex) {
- this._atlasIndex = atlasIndex;
- },
-
- /**
- * returns the rect of the cc.Sprite in points
- * @return {cc.Rect}
- */
- getTextureRect:function () {
- return cc.rect(this._rect.x, this._rect.y, this._rect.width, this._rect.height);
- },
-
- /**
- * Gets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode
- * @return {cc.TextureAtlas}
- */
- getTextureAtlas:function () {
- return this._textureAtlas;
- },
-
- /**
- * Sets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode
- * @param {cc.TextureAtlas} textureAtlas
- */
- setTextureAtlas:function (textureAtlas) {
- this._textureAtlas = textureAtlas;
- },
-
- /**
- * return the SpriteBatchNode of the cc.Sprite
- * @return {cc.SpriteBatchNode}
- */
- getSpriteBatchNode:function () {
- return this._batchNode;
- },
-
- /**
- * set the SpriteBatchNode of the cc.Sprite
- * @param {cc.SpriteBatchNode} spriteBatchNode
- */
- setSpriteBatchNode:function (spriteBatchNode) {
- this._batchNode = spriteBatchNode;
- },
-
- /**
- * Gets the offset position of the sprite. Calculated automatically by editors like Zwoptex.
- * @return {cc.Point}
- */
- getOffsetPosition:function () {
- return cc.p(this._offsetPosition.x, this._offsetPosition.y);
- },
-
- /**
- * conforms to cc.TextureProtocol protocol
- * @return {cc.BlendFunc}
- */
- getBlendFunc:function () {
- return this._blendFunc;
- },
-
- /**
- * Initializes a sprite with an SpriteFrame. The texture and rect in SpriteFrame will be applied on this sprite
- * @param {cc.SpriteFrame} spriteFrame A CCSpriteFrame object. It should includes a valid texture and a rect
- * @return {Boolean} true if the sprite is initialized properly, false otherwise.
- * @example
- * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png");
- * var sprite = new cc.Sprite();
- * sprite.initWithSpriteFrame(spriteFrame);
- */
- initWithSpriteFrame:function (spriteFrame) {
- cc.Assert(spriteFrame != null, "");
- if(!spriteFrame.textureLoaded()){
- //add event listener
- this._textureLoaded = false;
- spriteFrame.addLoadedEventListener(this._spriteFrameLoadedCallback, this);
- }
- var ret = this.initWithTexture(spriteFrame.getTexture(), spriteFrame.getRect());
- this.setDisplayFrame(spriteFrame);
-
- return ret;
- },
-
- _spriteFrameLoadedCallback:null,
-
- _spriteFrameLoadedCallbackForWebGL:function(spriteFrame){
- this.setNodeDirty();
- this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize());
- this._callLoadedEventCallbacks();
- },
-
- _spriteFrameLoadedCallbackForCanvas:function(spriteFrame){
- this.setNodeDirty();
- this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize());
- var curColor = this.getColor();
- if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255)
- this._changeTextureColor();
-
- this._callLoadedEventCallbacks();
- },
-
- /**
- * Initializes a sprite with a sprite frame name.
- * A cc.SpriteFrame will be fetched from the cc.SpriteFrameCache by name.
- * If the cc.SpriteFrame doesn't exist it will raise an exception.
- * @param {String} spriteFrameName A key string that can fected a volid cc.SpriteFrame from cc.SpriteFrameCache
- * @return {Boolean} true if the sprite is initialized properly, false otherwise.
- * @example
- * var sprite = new cc.Sprite();
- * sprite.initWithSpriteFrameName("grossini_dance_01.png");
- */
- initWithSpriteFrameName:function (spriteFrameName) {
- cc.Assert(spriteFrameName != null, "");
- var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName);
- return this.initWithSpriteFrame(frame);
- },
-
- /**
- * tell the sprite to use batch node render.
- * @param {cc.SpriteBatchNode} batchNode
- */
- useBatchNode:function (batchNode) {
- this._textureAtlas = batchNode.getTextureAtlas(); // weak ref
- this._batchNode = batchNode;
- },
-
- /**
- *
- * set the vertex rect.
- * It will be called internally by setTextureRect.
- * Useful if you want to create 2x images from SD images in Retina Display.
- * Do not call it manually. Use setTextureRect instead.
- * (override this method to generate "double scale" sprites)
- *
- * @param {cc.Rect} rect
- */
- setVertexRect:function (rect) {
- this._rect.x = rect.x;
- this._rect.y = rect.y;
- this._rect.width = rect.width;
- this._rect.height = rect.height;
- },
-
- sortAllChildren:function () {
- if (this._reorderChildDirty) {
- var j, tempItem, locChildren = this._children, tempChild;
- for (var i = 1; i < locChildren.length; i++) {
- tempItem = locChildren[i];
- j = i - 1;
- tempChild = locChildren[j];
-
- //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
- while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder ||
- ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) {
- locChildren[j + 1] = tempChild;
- j = j - 1;
- tempChild = locChildren[j];
- }
- locChildren[j + 1] = tempItem;
- }
-
- if (this._batchNode) {
- this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren);
- }
- this._reorderChildDirty = false;
- }
- },
-
- /**
- * Reorders a child according to a new z value. (override cc.Node )
- * @param {cc.Node} child
- * @param {Number} zOrder
- * @override
- */
- reorderChild:function (child, zOrder) {
- cc.Assert(child != null, "child is null");
- cc.Assert(this._children.indexOf(child) > -1, "this child is not in children list");
-
- if (zOrder === child.getZOrder())
- return;
-
- if (this._batchNode && !this._reorderChildDirty) {
- this._setReorderChildDirtyRecursively();
- this._batchNode.reorderBatch(true);
- }
- cc.Node.prototype.reorderChild.call(this, child, zOrder);
- },
-
- /**
- * Removes a child from the sprite. (override cc.Node )
- * @param child
- * @param cleanup whether or not cleanup all running actions
- * @override
- */
- removeChild:function (child, cleanup) {
- if (this._batchNode)
- this._batchNode.removeSpriteFromAtlas(child);
- cc.Node.prototype.removeChild.call(this, child, cleanup);
- },
-
- /**
- * Removes all children from the container (override cc.Node )
- * @param cleanup whether or not cleanup all running actions
- * @override
- */
- removeAllChildren:function (cleanup) {
- var locChildren = this._children, locBatchNode = this._batchNode;
- if (locBatchNode && locChildren != null) {
- for (var i = 0, len = locChildren.length; i < len; i++)
- locBatchNode.removeSpriteFromAtlas(locChildren[i]);
- }
-
- cc.Node.prototype.removeAllChildren.call(this, cleanup);
- this._hasChildren = false;
- },
-
- //
- // cc.Node property overloads
- //
-
- /**
- * set Recursively is or isn't Dirty
- * used only when parent is cc.SpriteBatchNode
- * @param {Boolean} value
- */
- setDirtyRecursively:function (value) {
- this._recursiveDirty = value;
- this.setDirty(value);
- // recursively set dirty
- var locChildren = this._children;
- if (locChildren != null) {
- for (var i = 0; i < locChildren.length; i++) {
- if (locChildren[i] instanceof cc.Sprite)
- locChildren[i].setDirtyRecursively(true);
- }
- }
- },
-
- /**
- * HACK: optimization
- */
- SET_DIRTY_RECURSIVELY:function () {
- if (this._batchNode && !this._recursiveDirty) {
- this._recursiveDirty = true;
- this._dirty = true;
- if (this._hasChildren)
- this.setDirtyRecursively(true);
- }
- },
-
- /**
- * position setter (override cc.Node )
- * @param {cc.Point} pos
- * @override
- */
- setPosition:function (pos) {
- if (arguments.length >= 2)
- cc.Node.prototype.setPosition.call(this, pos, arguments[1]);
- else
- cc.Node.prototype.setPosition.call(this, pos);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * Rotation setter (override cc.Node )
- * @param {Number} rotation
- * @override
- */
- setRotation:function (rotation) {
- cc.Node.prototype.setRotation.call(this, rotation);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- setRotationX:function (rotationX) {
- cc.Node.prototype.setRotationX.call(this, rotationX);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- setRotationY:function (rotationY) {
- cc.Node.prototype.setRotationY.call(this, rotationY);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * SkewX setter (override cc.Node )
- * @param {Number} sx SkewX value
- * @override
- */
- setSkewX:function (sx) {
- cc.Node.prototype.setSkewX.call(this, sx);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * SkewY setter (override cc.Node )
- * @param {Number} sy SkewY value
- * @override
- */
- setSkewY:function (sy) {
- cc.Node.prototype.setSkewY.call(this, sy);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * ScaleX setter (override cc.Node )
- * @param {Number} scaleX
- * @override
- */
- setScaleX:function (scaleX) {
- cc.Node.prototype.setScaleX.call(this, scaleX);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * ScaleY setter (override cc.Node )
- * @param {Number} scaleY
- * @override
- */
- setScaleY:function (scaleY) {
- cc.Node.prototype.setScaleY.call(this, scaleY);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * The scale factor of the node. 1.0 is the default scale factor.
- * It modifies the X and Y scale at the same time. (override cc.Node )
- * @param {Number} scale
- * @param {Number|null} [scaleY=]
- * @override
- */
- setScale:function (scale, scaleY) {
- cc.Node.prototype.setScale.call(this, scale, scaleY);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * VertexZ setter (override cc.Node )
- * @param {Number} vertexZ
- * @override
- */
- setVertexZ:function (vertexZ) {
- cc.Node.prototype.setVertexZ.call(this, vertexZ);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * AnchorPoint setter (override cc.Node )
- * @param {cc.Point} anchor
- * @override
- */
- setAnchorPoint:function (anchor) {
- cc.Node.prototype.setAnchorPoint.call(this, anchor);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * visible setter (override cc.Node )
- * @param {Boolean} visible
- * @override
- */
- setVisible:function (visible) {
- cc.Node.prototype.setVisible.call(this, visible);
- this.SET_DIRTY_RECURSIVELY();
- },
-
- /**
- * IsRelativeAnchorPoint setter (override cc.Node )
- * @param {Boolean} relative
- * @override
- */
- ignoreAnchorPointForPosition:function (relative) {
- cc.Assert(!this._batchNode, "ignoreAnchorPointForPosition is invalid in cc.Sprite");
- cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative);
- },
-
- /**
- * Sets whether the sprite should be flipped horizontally or not.
- * @param {Boolean} flippedX true if the sprite should be flipped horizontally, false otherwise.
- */
- setFlippedX:function (flippedX) {
- if (this._flippedX != flippedX) {
- this._flippedX = flippedX;
- this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
- this.setNodeDirty();
- }
- },
-
- /**
- * Sets whether the sprite should be flipped vertically or not.
- * @param {Boolean} flippedY true if the sprite should be flipped vertically, false otherwise.
- */
- setFlippedY:function (flippedY) {
- if (this._flippedY != flippedY) {
- this._flippedY = flippedY;
- this.setTextureRect(this._rect, this._rectRotated, this._contentSize);
- this.setNodeDirty();
- }
- },
-
- /**
- *
- * Returns the flag which indicates whether the sprite is flipped horizontally or not.
- *
- * It only flips the texture of the sprite, and not the texture of the sprite's children.
- * Also, flipping the texture doesn't alter the anchorPoint.
- * If you want to flip the anchorPoint too, and/or to flip the children too use:
- * sprite->setScaleX(sprite->getScaleX() * -1);
- * @return {Boolean} true if the sprite is flipped horizaontally, false otherwise.
- */
- isFlippedX:function () {
- return this._flippedX;
- },
-
- /**
- *
- * Return the flag which indicates whether the sprite is flipped vertically or not.
- *
- * It only flips the texture of the sprite, and not the texture of the sprite's children.
- * Also, flipping the texture doesn't alter the anchorPoint.
- * If you want to flip the anchorPoint too, and/or to flip the children too use:
- * sprite->setScaleY(sprite->getScaleY() * -1);
- * @return {Boolean} true if the sprite is flipped vertically, flase otherwise.
- */
- isFlippedY:function () {
- return this._flippedY;
- },
-
- //
- // RGBA protocol
- //
- /**
- * opacity: conforms to CCRGBAProtocol protocol
- * @param {Boolean} modify
- */
- setOpacityModifyRGB:null,
-
- _setOpacityModifyRGBForWebGL: function (modify) {
- if (this._opacityModifyRGB !== modify) {
- this._opacityModifyRGB = modify;
- this.updateColor();
- }
- },
-
- _setOpacityModifyRGBForCanvas: function (modify) {
- if (this._opacityModifyRGB !== modify) {
- this._opacityModifyRGB = modify;
- this.setNodeDirty();
- }
- },
-
- /**
- * return IsOpacityModifyRGB value
- * @return {Boolean}
- */
- isOpacityModifyRGB:function () {
- return this._opacityModifyRGB;
- },
-
- updateDisplayedOpacity: null,
- _updateDisplayedOpacityForWebGL:function (parentOpacity) {
- cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity);
- this.updateColor();
- },
-
- _updateDisplayedOpacityForCanvas:function (parentOpacity) {
- cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity);
- this._changeTextureColor();
- this.setNodeDirty();
- },
-
- // Animation
-
- /**
- * changes the display frame with animation name and index.
- * The animation name will be get from the CCAnimationCache
- * @param animationName
- * @param frameIndex
- */
- setDisplayFrameWithAnimationName:function (animationName, frameIndex) {
- cc.Assert(animationName, "cc.Sprite#setDisplayFrameWithAnimationName. animationName must not be null");
- var cache = cc.AnimationCache.getInstance().getAnimation(animationName);
- cc.Assert(cache, "cc.Sprite#setDisplayFrameWithAnimationName: Frame not found");
- var animFrame = cache.getFrames()[frameIndex];
- cc.Assert(animFrame, "cc.Sprite#setDisplayFrame. Invalid frame");
- this.setDisplayFrame(animFrame.getSpriteFrame());
- },
-
- /**
- * Returns the batch node object if this sprite is rendered by cc.SpriteBatchNode
- * @returns {cc.SpriteBatchNode|null} The cc.SpriteBatchNode object if this sprite is rendered by cc.SpriteBatchNode, null if the sprite isn't used batch node.
- */
- getBatchNode:function () {
- return this._batchNode;
- },
-
- _setReorderChildDirtyRecursively:function () {
- //only set parents flag the first time
- if (!this._reorderChildDirty) {
- this._reorderChildDirty = true;
- var pNode = this._parent;
- while (pNode && pNode != this._batchNode) {
- pNode._setReorderChildDirtyRecursively();
- pNode = pNode.getParent();
- }
- }
- },
-
- // CCTextureProtocol
- getTexture:function () {
- return this._texture;
- },
-
- _quad:null, // vertex coords, texture coords and color info
- _quadWebBuffer:null,
- _quadDirty:false,
- _colorized:false,
- _isLighterMode:false,
- _originalTexture:null,
- _textureRect_Canvas:null,
- _drawSize_Canvas:null,
-
- /**
- * Constructor
- * @param {String|cc.SpriteFrame|cc.SpriteBatchNode|HTMLImageElement|cc.Texture2D} fileName sprite construct parameter
- */
- ctor: null,
-
- _ctorForWebGL: function (fileName) {
- cc.NodeRGBA.prototype.ctor.call(this);
- this._shouldBeHidden = false;
- this._offsetPosition = cc.p(0, 0);
- this._unflippedOffsetPositionFromCenter = cc.p(0, 0);
- this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
- this._rect = cc.rect(0,0,0,0);
-
- this._quad = new cc.V3F_C4B_T2F_Quad();
- this._quadWebBuffer = cc.renderContext.createBuffer();
- this._quadDirty = true;
-
- this._textureLoaded = true;
- this._loadedEventListeners = [];
-
- if (fileName) {
- if (typeof(fileName) === "string") {
- var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName);
- this.initWithSpriteFrame(frame);
- } else if (typeof(fileName) === "object") {
- if (fileName instanceof cc.SpriteFrame) {
- this.initWithSpriteFrame(fileName);
- } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) {
- var texture2d = new cc.Texture2D();
- texture2d.initWithElement(fileName);
- texture2d.handleLoadedTexture();
- this.initWithTexture(texture2d);
- } else if (fileName instanceof cc.Texture2D) {
- this.initWithTexture(fileName);
- }
- }
- }
- },
-
- _ctorForCanvas: function (fileName) {
- cc.NodeRGBA.prototype.ctor.call(this);
- this._shouldBeHidden = false;
- this._offsetPosition = cc.p(0, 0);
- this._unflippedOffsetPositionFromCenter = cc.p(0, 0);
- this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
- this._rect = cc.rect(0, 0, 0, 0);
-
- this._newTextureWhenChangeColor = false;
- this._textureLoaded = true;
- this._loadedEventListeners = [];
- this._textureRect_Canvas = cc.rect(0, 0, 0, 0);
- this._drawSize_Canvas = cc.size(0, 0);
-
- if (fileName) {
- if (typeof(fileName) === "string") {
- var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName);
- this.initWithSpriteFrame(frame);
- } else if (typeof(fileName) === "object") {
- if (fileName instanceof cc.SpriteFrame) {
- this.initWithSpriteFrame(fileName);
- } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) {
- var texture2d = new cc.Texture2D();
- texture2d.initWithElement(fileName);
- texture2d.handleLoadedTexture();
- this.initWithTexture(texture2d);
- } else if (fileName instanceof cc.Texture2D) {
- this.initWithTexture(fileName);
- }
- }
- }
- },
-
- /**
- * Returns the quad (tex coords, vertex coords and color) information.
- * @return {cc.V3F_C4B_T2F_Quad}
- */
- getQuad:function () {
- return this._quad;
- },
-
- /**
- * conforms to cc.TextureProtocol protocol
- * @param {Number|cc.BlendFunc} src
- * @param {Number} dst
- */
- setBlendFunc: null,
-
- _setBlendFuncForWebGL: function (src, dst) {
- if (arguments.length == 1)
- this._blendFunc = src;
- else
- this._blendFunc = {src: src, dst: dst};
- },
-
- _setBlendFuncForCanvas: function (src, dst) {
- if (arguments.length == 1)
- this._blendFunc = src;
- else
- this._blendFunc = {src: src, dst: dst};
- this._isLighterMode = (this._blendFunc &&
- (( this._blendFunc.src == gl.SRC_ALPHA && this._blendFunc.dst == gl.ONE) || (this._blendFunc.src == gl.ONE && this._blendFunc.dst == gl.ONE)));
- },
-
- /**
- * Initializes an empty sprite with nothing init.
- * @return {Boolean}
- */
- init:null,
-
- _initForWebGL: function () {
- if (arguments.length > 0)
- return this.initWithFile(arguments[0], arguments[1]);
-
- cc.NodeRGBA.prototype.init.call(this);
- this._dirty = this._recursiveDirty = false;
- this._opacityModifyRGB = true;
-
- this._blendFunc.src = cc.BLEND_SRC;
- this._blendFunc.dst = cc.BLEND_DST;
-
- // update texture (calls _updateBlendFunc)
- this.setTexture(null);
- this._textureLoaded = true;
- this._flippedX = this._flippedY = false;
-
- // default transform anchor: center
- this.setAnchorPoint(cc.p(0.5, 0.5));
-
- // zwoptex default values
- this._offsetPosition = cc.PointZero();
- this._hasChildren = false;
-
- // Atlas: Color
- var tempColor = {r: 255, g: 255, b: 255, a: 255};
- this._quad.bl.colors = tempColor;
- this._quad.br.colors = tempColor;
- this._quad.tl.colors = tempColor;
- this._quad.tr.colors = tempColor;
- this._quadDirty = true;
-
- // updated in "useSelfRender"
- // Atlas: TexCoords
- this.setTextureRect(cc.RectZero(), false, cc.SizeZero());
- return true;
- },
-
- _initForCanvas: function () {
- if (arguments.length > 0)
- return this.initWithFile(arguments[0], arguments[1]);
-
- cc.NodeRGBA.prototype.init.call(this);
- this._dirty = this._recursiveDirty = false;
- this._opacityModifyRGB = true;
-
- this._blendFunc.src = cc.BLEND_SRC;
- this._blendFunc.dst = cc.BLEND_DST;
-
- // update texture (calls _updateBlendFunc)
- this.setTexture(null);
- this._textureLoaded = true;
- this._flippedX = this._flippedY = false;
-
- // default transform anchor: center
- this.setAnchorPoint(cc.p(0.5, 0.5));
-
- // zwoptex default values
- this._offsetPosition = cc.PointZero();
- this._hasChildren = false;
-
- // updated in "useSelfRender"
- // Atlas: TexCoords
- this.setTextureRect(cc.RectZero(), false, cc.SizeZero());
- return true;
- },
-
- /**
- *
- * Initializes a sprite with an image filename.
- *
- * This method will find pszFilename from local file system, load its content to CCTexture2D,
- * then use CCTexture2D to create a sprite.
- * After initialization, the rect used will be the size of the image. The offset will be (0,0).
- *
- * @param {String} filename The path to an image file in local file system
- * @param {cc.Rect} rect The rectangle assigned the content area from texture.
- * @return {Boolean} true if the sprite is initialized properly, false otherwise.
- * @example
- * var mySprite = new cc.Sprite();
- * mySprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320));
- */
- initWithFile:function (filename, rect) {
- cc.Assert(filename != null, "Sprite#initWithFile():Invalid filename for sprite");
- var texture = cc.TextureCache.getInstance().textureForKey(filename);
- if (!texture) {
- texture = cc.TextureCache.getInstance().addImage(filename);
- return this.initWithTexture(texture, rect);
- } else {
- if (!rect) {
- var size = texture.getContentSize();
- rect = cc.rect(0, 0, size.width, size.height);
- }
- return this.initWithTexture(texture, rect);
- }
- },
-
- /**
- * Initializes a sprite with a texture and a rect in points, optionally rotated.
- * After initialization, the rect used will be the size of the texture, and the offset will be (0,0).
- * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites.
- * @param {cc.Rect} rect Only the contents inside rect of this texture will be applied for this sprite.
- * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated.
- * @return {Boolean} true if the sprite is initialized properly, false otherwise.
- * @example
- * var img =cc.TextureCache.getInstance().addImage("HelloHTML5World.png");
- * var mySprite = new cc.Sprite();
- * mySprite.initWithTexture(img,cc.rect(0,0,480,320));
- */
- initWithTexture: null,
-
- _initWithTextureForWebGL: function (texture, rect, rotated) {
- var argnum = arguments.length;
- if (argnum == 0)
- throw "Sprite.initWithTexture(): Argument must be non-nil ";
-
- rotated = rotated || false;
-
- if (!cc.NodeRGBA.prototype.init.call(this))
- return false;
-
- this._batchNode = null;
- this._recursiveDirty = false;
- this._dirty = false;
- this._opacityModifyRGB = true;
-
- this._blendFunc.src = cc.BLEND_SRC;
- this._blendFunc.dst = cc.BLEND_DST;
-
- this._flippedX = this._flippedY = false;
-
- // default transform anchor: center
- this.setAnchorPoint(cc.p(0.5, 0.5));
-
- // zwoptex default values
- this._offsetPosition = cc.p(0, 0);
- this._hasChildren = false;
-
- // Atlas: Color
- var tmpColor = new cc.Color4B(255, 255, 255, 255);
- var locQuad = this._quad;
- locQuad.bl.colors = tmpColor;
- locQuad.br.colors = tmpColor;
- locQuad.tl.colors = tmpColor;
- locQuad.tr.colors = tmpColor;
-
- var locTextureLoaded = texture.isLoaded();
- this._textureLoaded = locTextureLoaded;
-
- if (!locTextureLoaded) {
- this._rectRotated = rotated || false;
- if (rect) {
- var locRect = this._rect;
- locRect.x = rect.x;
- locRect.y = rect.y;
- locRect.width = rect.width;
- locRect.height = rect.height;
- }
- texture.addLoadedEventListener(this._textureLoadedCallback, this);
- return true;
- }
-
- if (!rect) {
- rect = cc.rect(0, 0, 0, 0);
- rect.size = texture.getContentSize();
- }
- this.setTexture(texture);
- this.setTextureRect(rect, rotated, rect.size);
-
- // by default use "Self Render".
- // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
- this.setBatchNode(null);
- this._quadDirty = true;
- return true;
- },
-
- _initWithTextureForCanvas: function (texture, rect, rotated) {
- var argnum = arguments.length;
- if (argnum == 0)
- throw "Sprite.initWithTexture(): Argument must be non-nil ";
-
- rotated = rotated || false;
-
- if (!cc.NodeRGBA.prototype.init.call(this))
- return false;
-
- this._batchNode = null;
-
- this._recursiveDirty = false;
- this._dirty = false;
- this._opacityModifyRGB = true;
-
- this._blendFunc.src = cc.BLEND_SRC;
- this._blendFunc.dst = cc.BLEND_DST;
-
- this._flippedX = this._flippedY = false;
-
- // default transform anchor: center
- this.setAnchorPoint(cc.p(0.5, 0.5));
-
- // zwoptex default values
- this._offsetPosition = cc.p(0, 0);
- this._hasChildren = false;
-
- var locTextureLoaded = texture.isLoaded();
- this._textureLoaded = locTextureLoaded;
-
- if (!locTextureLoaded) {
- this._rectRotated = rotated || false;
- if (rect) {
- this._rect.x = rect.x;
- this._rect.y = rect.y;
- this._rect.width = rect.width;
- this._rect.height = rect.height;
- }
- texture.addLoadedEventListener(this._textureLoadedCallback, this);
- return true;
- }
-
- if (!rect) {
- rect = cc.rect(0, 0, 0, 0);
- rect.size = texture.getContentSize();
- }
- this._originalTexture = texture;
-
- this.setTexture(texture);
- this.setTextureRect(rect, rotated, rect.size);
-
- // by default use "Self Render".
- // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
- this.setBatchNode(null);
- return true;
- },
-
- _textureLoadedCallback: null,
-
- _textureLoadedCallbackForWebGL: function (sender) {
- this._textureLoaded = true;
- var locRect = this._rect;
- if (!locRect) {
- locRect = cc.rect(0, 0, 0, 0);
- locRect.size = sender.getContentSize();
- } else if (cc._rectEqualToZero(locRect)) {
- locRect.size = sender.getContentSize();
- }
-
- this.setTexture(sender);
- this.setTextureRect(locRect, this._rectRotated, locRect.size);
-
- // by default use "Self Render".
- // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
- this.setBatchNode(null);
- this._quadDirty = true;
- this._callLoadedEventCallbacks();
- },
-
- _textureLoadedCallbackForCanvas: function (sender) {
- this._textureLoaded = true;
- var locRect = this._rect;
- if (!locRect) {
- locRect = cc.rect(0, 0, 0, 0);
- locRect.size = sender.getContentSize();
- } else if (cc._rectEqualToZero(locRect)) {
- locRect.size = sender.getContentSize();
- }
- this._originalTexture = sender;
-
- this.setTexture(sender);
- this.setTextureRect(locRect, this._rectRotated, locRect.size);
-
- // by default use "Self Render".
- // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
- this.setBatchNode(null);
- this._callLoadedEventCallbacks();
- },
-
- /**
- * updates the texture rect of the CCSprite in points.
- * @param {cc.Rect} rect a rect of texture
- * @param {Boolean} rotated
- * @param {cc.Size} untrimmedSize
- */
- setTextureRect:null,
-
- _setTextureRectForWebGL:function (rect, rotated, untrimmedSize) {
- this._rectRotated = rotated || false;
- untrimmedSize = untrimmedSize || rect.size;
-
- this.setContentSize(untrimmedSize);
- this.setVertexRect(rect);
- this._setTextureCoords(rect);
-
- var relativeOffset = this._unflippedOffsetPositionFromCenter;
- if (this._flippedX)
- relativeOffset.x = -relativeOffset.x;
- if (this._flippedY)
- relativeOffset.y = -relativeOffset.y;
-
- var locRect = this._rect;
- this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - locRect.width) / 2;
- this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - locRect.height) / 2;
-
- // rendering using batch node
- if (this._batchNode) {
- // update dirty_, don't update recursiveDirty_
- //this.setDirty(true);
- this._dirty = true;
- } else {
- // self rendering
- // Atlas: Vertex
- var x1 = 0 + this._offsetPosition.x;
- var y1 = 0 + this._offsetPosition.y;
- var x2 = x1 + locRect.width;
- var y2 = y1 + locRect.height;
-
- // Don't update Z.
- var locQuad = this._quad;
- locQuad.bl.vertices = {x:x1, y:y1, z:0};
- locQuad.br.vertices = {x:x2, y:y1, z:0};
- locQuad.tl.vertices = {x:x1, y:y2, z:0};
- locQuad.tr.vertices = {x:x2, y:y2, z:0};
-
- this._quadDirty = true;
- }
- },
-
- _setTextureRectForCanvas: function (rect, rotated, untrimmedSize) {
- this._rectRotated = rotated || false;
- untrimmedSize = untrimmedSize || rect.size;
-
- this.setContentSize(untrimmedSize);
- this.setVertexRect(rect);
- //this._textureRect_Canvas = cc.RECT_POINTS_TO_PIXELS(rect); //this._setTextureCoords(rect);
- var locTextureRect = this._textureRect_Canvas;
- var scaleFactor = cc.CONTENT_SCALE_FACTOR();
- locTextureRect.x = 0|(rect.x * scaleFactor);
- locTextureRect.y = 0|(rect.y * scaleFactor);
- locTextureRect.width = 0|(rect.width * scaleFactor);
- locTextureRect.height = 0|(rect.height * scaleFactor);
-
- var relativeOffset = this._unflippedOffsetPositionFromCenter;
- if (this._flippedX)
- relativeOffset.x = -relativeOffset.x;
- if (this._flippedY)
- relativeOffset.y = -relativeOffset.y;
- this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - this._rect.width) / 2;
- this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - this._rect.height) / 2;
-
- // rendering using batch node
- if (this._batchNode) {
- // update dirty_, don't update recursiveDirty_
- //this.setDirty(true);
- this._dirty = true;
- }
- },
-
- // BatchNode methods
- /**
- * updates the quad according the the rotation, position, scale values.
- */
- updateTransform: null,
-
- _updateTransformForWebGL: function () {
- //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode");
-
- // recaculate matrix only if it is dirty
- if (this.isDirty()) {
- var locQuad = this._quad, locParent = this._parent;
- // If it is not visible, or one of its ancestors is not visible, then do nothing:
- if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) {
- locQuad.br.vertices = {x: 0, y: 0, z: 0};
- locQuad.tl.vertices = {x: 0, y: 0, z: 0};
- locQuad.tr.vertices = {x: 0, y: 0, z: 0};
- locQuad.bl.vertices = {x: 0, y: 0, z: 0};
- this._shouldBeHidden = true;
- } else {
- this._shouldBeHidden = false;
-
- if (!locParent || locParent == this._batchNode) {
- this._transformToBatch = this.nodeToParentTransform();
- } else {
- //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite");
- this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch);
- }
-
- //
- // calculate the Quad based on the Affine Matrix
- //
- var locTransformToBatch = this._transformToBatch;
- var size = this._rect.size;
- var x1 = this._offsetPosition.x;
- var y1 = this._offsetPosition.y;
-
- var x2 = x1 + size.width;
- var y2 = y1 + size.height;
- var x = locTransformToBatch.tx;
- var y = locTransformToBatch.ty;
-
- var cr = locTransformToBatch.a;
- var sr = locTransformToBatch.b;
- var cr2 = locTransformToBatch.d;
- var sr2 = -locTransformToBatch.c;
- var ax = x1 * cr - y1 * sr2 + x;
- var ay = x1 * sr + y1 * cr2 + y;
-
- var bx = x2 * cr - y1 * sr2 + x;
- var by = x2 * sr + y1 * cr2 + y;
-
- var cx = x2 * cr - y2 * sr2 + x;
- var cy = x2 * sr + y2 * cr2 + y;
-
- var dx = x1 * cr - y2 * sr2 + x;
- var dy = x1 * sr + y2 * cr2 + y;
-
- var locVertexZ = this._vertexZ;
- locQuad.bl.vertices = {x: cc.RENDER_IN_SUBPIXEL(ax), y: cc.RENDER_IN_SUBPIXEL(ay), z: locVertexZ};
- locQuad.br.vertices = {x: cc.RENDER_IN_SUBPIXEL(bx), y: cc.RENDER_IN_SUBPIXEL(by), z: locVertexZ};
- locQuad.tl.vertices = {x: cc.RENDER_IN_SUBPIXEL(dx), y: cc.RENDER_IN_SUBPIXEL(dy), z: locVertexZ};
- locQuad.tr.vertices = {x: cc.RENDER_IN_SUBPIXEL(cx), y: cc.RENDER_IN_SUBPIXEL(cy), z: locVertexZ};
- }
- this._textureAtlas.updateQuad(locQuad, this._atlasIndex);
- this._recursiveDirty = false;
- this.setDirty(false);
- }
-
- // recursively iterate over children
- if (this._hasChildren)
- this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform);
-
- if (cc.SPRITE_DEBUG_DRAW) {
- // draw bounding box
- var vertices = [
- cc.p(this._quad.bl.vertices.x, this._quad.bl.vertices.y),
- cc.p(this._quad.br.vertices.x, this._quad.br.vertices.y),
- cc.p(this._quad.tr.vertices.x, this._quad.tr.vertices.y),
- cc.p(this._quad.tl.vertices.x, this._quad.tl.vertices.y)
- ];
- cc.drawingUtil.drawPoly(vertices, 4, true);
- }
- },
-
- _updateTransformForCanvas: function () {
- //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode");
-
- // recaculate matrix only if it is dirty
- if (this._dirty) {
- // If it is not visible, or one of its ancestors is not visible, then do nothing:
- var locParent = this._parent;
- if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) {
- this._shouldBeHidden = true;
- } else {
- this._shouldBeHidden = false;
-
- if (!locParent || locParent == this._batchNode) {
- this._transformToBatch = this.nodeToParentTransform();
- } else {
- //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite");
- this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch);
- }
- }
- this._recursiveDirty = false;
- this._dirty = false;
- }
-
- // recursively iterate over children
- if (this._hasChildren)
- this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform);
- },
-
- /**
- * Add child to sprite (override cc.Node )
- * @param {cc.Sprite} child
- * @param {Number} zOrder child's zOrder
- * @param {String} tag child's tag
- * @override
- */
- addChild: null,
-
- _addChildForWebGL:function (child, zOrder, tag) {
- cc.Assert(child != null, "Argument must be non-NULL");
- if (zOrder == null)
- zOrder = child._zOrder;
- if (tag == null)
- tag = child._tag;
-
- if (this._batchNode) {
- cc.Assert((child instanceof cc.Sprite), "cc.Sprite only supports cc.Sprites as children when using cc.SpriteBatchNode");
- cc.Assert(child.getTexture()._webTextureObj === this._textureAtlas.getTexture()._webTextureObj, "");
-
- //put it in descendants array of batch node
- this._batchNode.appendChild(child);
- if (!this._reorderChildDirty)
- this._setReorderChildDirtyRecursively();
- }
-
- //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check
- cc.Node.prototype.addChild.call(this, child, zOrder, tag);
- this._hasChildren = true;
- },
-
- _addChildForCanvas: function (child, zOrder, tag) {
- cc.Assert(child != null, "Argument must be non-NULL");
- if (zOrder == null)
- zOrder = child._zOrder;
- if (tag == null)
- tag = child._tag;
-
- //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check
- cc.Node.prototype.addChild.call(this, child, zOrder, tag);
- this._hasChildren = true;
- },
-
- /**
- * Update sprite's color
- */
- updateColor:function () {
- var locDisplayedColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity;
- var color4 = {r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: locDisplayedOpacity};
- // special opacity for premultiplied textures
- if (this._opacityModifyRGB) {
- color4.r *= locDisplayedOpacity / 255.0;
- color4.g *= locDisplayedOpacity / 255.0;
- color4.b *= locDisplayedOpacity / 255.0;
- }
- var locQuad = this._quad;
- locQuad.bl.colors = color4;
- locQuad.br.colors = color4;
- locQuad.tl.colors = color4;
- locQuad.tr.colors = color4;
-
- // renders using Sprite Manager
- if (this._batchNode) {
- if (this._atlasIndex != cc.SPRITE_INDEX_NOT_INITIALIZED) {
- this._textureAtlas.updateQuad(locQuad, this._atlasIndex)
- } else {
- // no need to set it recursively
- // update dirty_, don't update recursiveDirty_
- //this.setDirty(true);
- this._dirty = true;
- }
- }
- // self render
- // do nothing
- this._quadDirty = true;
- },
-
- /**
- * opacity setter
- * @param {Number} opacity
- */
- setOpacity:null,
-
- _setOpacityForWebGL: function (opacity) {
- cc.NodeRGBA.prototype.setOpacity.call(this, opacity);
- this.updateColor();
- },
-
- _setOpacityForCanvas: function (opacity) {
- cc.NodeRGBA.prototype.setOpacity.call(this, opacity);
- this.setNodeDirty();
- },
-
- /**
- * color setter
- * @param {cc.Color3B} color3
- */
- setColor: null,
-
- _setColorForWebGL: function (color3) {
- cc.NodeRGBA.prototype.setColor.call(this, color3);
- this.updateColor();
- },
-
- _setColorForCanvas: function (color3) {
- var curColor = this.getColor();
- if ((curColor.r === color3.r) && (curColor.g === color3.g) && (curColor.b === color3.b))
- return;
-
- cc.NodeRGBA.prototype.setColor.call(this, color3);
- this._changeTextureColor();
- this.setNodeDirty();
- },
-
- updateDisplayedColor: null,
-
- _updateDisplayedColorForWebGL: function (parentColor) {
- cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor);
- this.updateColor();
- },
-
- _updateDisplayedColorForCanvas: function (parentColor) {
- cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor);
- this._changeTextureColor();
- this.setNodeDirty();
- },
-
- // Frames
- /**
- * Sets a new display frame to the cc.Sprite.
- * @param {cc.SpriteFrame} newFrame
- */
- setDisplayFrame: null,
-
- _setDisplayFrameForWebGL: function (newFrame) {
- this.setNodeDirty();
- var frameOffset = newFrame.getOffset();
- this._unflippedOffsetPositionFromCenter.x = frameOffset.x;
- this._unflippedOffsetPositionFromCenter.y = frameOffset.y;
-
- var pNewTexture = newFrame.getTexture();
- var locTextureLoaded = newFrame.textureLoaded();
- if (!locTextureLoaded) {
- this._textureLoaded = false;
- newFrame.addLoadedEventListener(function (sender) {
- this._textureLoaded = true;
- var locNewTexture = sender.getTexture();
- if (locNewTexture != this._texture)
- this.setTexture(locNewTexture);
- this.setTextureRect(sender.getRect(), sender._rectRotated, sender.getOriginalSize());
- this._callLoadedEventCallbacks();
- }, this);
- }
- // update texture before updating texture rect
- if (pNewTexture != this._texture)
- this.setTexture(pNewTexture);
-
- // update rect
- this._rectRotated = newFrame.isRotated();
- this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize());
- },
-
- _setDisplayFrameForCanvas: function (newFrame) {
- this.setNodeDirty();
-
- var frameOffset = newFrame.getOffset();
- this._unflippedOffsetPositionFromCenter.x = frameOffset.x;
- this._unflippedOffsetPositionFromCenter.y = frameOffset.y;
-
- // update rect
- this._rectRotated = newFrame.isRotated();
-
- var pNewTexture = newFrame.getTexture();
- var locTextureLoaded = newFrame.textureLoaded();
- if (!locTextureLoaded) {
- this._textureLoaded = false;
- newFrame.addLoadedEventListener(function (sender) {
- this._textureLoaded = true;
- var locNewTexture = sender.getTexture();
- if (locNewTexture != this._texture)
- this.setTexture(locNewTexture);
- this.setTextureRect(sender.getRect(), this._rectRotated, sender.getOriginalSize());
- this._callLoadedEventCallbacks();
- }, this);
- }
- // update texture before updating texture rect
- if (pNewTexture != this._texture)
- this.setTexture(pNewTexture);
-
- if (this._rectRotated)
- this._originalTexture = pNewTexture;
-
- this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize());
- this._colorized = false;
- if (locTextureLoaded) {
- var curColor = this.getColor();
- if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255)
- this._changeTextureColor();
- }
- },
-
- /**
- * Returns whether or not a cc.SpriteFrame is being displayed
- * @param {cc.SpriteFrame} frame
- * @return {Boolean}
- */
- isFrameDisplayed: null,
-
- _isFrameDisplayedForWebGL: function (frame) {
- return (cc.rectEqualToRect(frame.getRect(), this._rect) && frame.getTexture().getName() == this._texture.getName()
- && cc.pointEqualToPoint(frame.getOffset(), this._unflippedOffsetPositionFromCenter));
- },
-
- _isFrameDisplayedForCanvas: function (frame) {
- if (frame.getTexture() != this._texture)
- return false;
- return cc.rectEqualToRect(frame.getRect(), this._rect);
- },
-
- /**
- * Returns the current displayed frame.
- * @return {cc.SpriteFrame}
- */
- displayFrame: function () {
- return cc.SpriteFrame.createWithTexture(this._texture,
- cc.RECT_POINTS_TO_PIXELS(this._rect),
- this._rectRotated,
- cc.POINT_POINTS_TO_PIXELS(this._unflippedOffsetPositionFromCenter),
- cc.SIZE_POINTS_TO_PIXELS(this._contentSize));
- },
-
- /**
- * Sets the batch node to sprite
- * @param {cc.SpriteBatchNode|null} spriteBatchNode
- * @example
- * var batch = cc.SpriteBatchNode.create("Images/grossini_dance_atlas.png", 15);
- * var sprite = cc.Sprite.createWithTexture(batch.getTexture(), cc.rect(0, 0, 57, 57));
- * batch.addChild(sprite);
- * layer.addChild(batch);
- */
- setBatchNode:null,
-
- _setBatchNodeForWebGL:function (spriteBatchNode) {
- this._batchNode = spriteBatchNode; // weak reference
-
- // self render
- if (!this._batchNode) {
- this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED;
- this.setTextureAtlas(null);
- this._recursiveDirty = false;
- this.setDirty(false);
-
- var x1 = this._offsetPosition.x;
- var y1 = this._offsetPosition.y;
- var x2 = x1 + this._rect.width;
- var y2 = y1 + this._rect.height;
- var locQuad = this._quad;
- locQuad.bl.vertices = {x:x1, y:y1, z:0};
- locQuad.br.vertices = {x:x2, y:y1, z:0};
- locQuad.tl.vertices = {x:x1, y:y2, z:0};
- locQuad.tr.vertices = {x:x2, y:y2, z:0};
-
- this._quadDirty = true;
- } else {
- // using batch
- this._transformToBatch = cc.AffineTransformIdentity();
- this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref
- }
- },
-
- _setBatchNodeForCanvas:function (spriteBatchNode) {
- this._batchNode = spriteBatchNode; // weak reference
-
- // self render
- if (!this._batchNode) {
- this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED;
- this.setTextureAtlas(null);
- this._recursiveDirty = false;
- this.setDirty(false);
- } else {
- // using batch
- this._transformToBatch = cc.AffineTransformIdentity();
- this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref
- }
- },
-
- // CCTextureProtocol
- /**
- * Texture of sprite setter
- * @param {HTMLImageElement|HTMLCanvasElement|cc.Texture2D} texture
- */
- setTexture: null,
-
- _setTextureForWebGL: function (texture) {
- // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet
- cc.Assert(!texture || texture instanceof cc.Texture2D, "setTexture expects a CCTexture2D. Invalid argument");
-
- // If batchnode, then texture id should be the same
- cc.Assert(!this._batchNode, "cc.Sprite: Batched sprites should use the same texture as the batchnode");
-
- if (texture)
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
- else
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR));
-
- if (!this._batchNode && this._texture != texture) {
- this._texture = texture;
- this._updateBlendFunc();
- }
- },
-
- _setTextureForCanvas: function (texture) {
- // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet
- cc.Assert(!texture || texture instanceof cc.Texture2D, "setTexture expects a CCTexture2D. Invalid argument");
- if (this._texture != texture) {
- if (texture && texture.getHtmlElementObj() instanceof HTMLImageElement) {
- this._originalTexture = texture;
- }
- this._texture = texture;
- }
- },
-
- // Texture protocol
- _updateBlendFunc:function () {
- cc.Assert(!this._batchNode, "cc.Sprite: _updateBlendFunc doesn't work when the sprite is rendered using a cc.CCSpriteBatchNode");
- // it's possible to have an untextured sprite
- if (!this._texture || !this._texture.hasPremultipliedAlpha()) {
- this._blendFunc.src = gl.SRC_ALPHA;
- this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
- this.setOpacityModifyRGB(false);
- } else {
- this._blendFunc.src = cc.BLEND_SRC;
- this._blendFunc.dst = cc.BLEND_DST;
- this.setOpacityModifyRGB(true);
- }
- },
-
- _changeTextureColor: function () {
- var locElement, locTexture = this._texture, locRect = this._textureRect_Canvas; //this.getTextureRect();
- if (locTexture && locRect.width > 0 && this._originalTexture) {
- locElement = locTexture.getHtmlElementObj();
- if (!locElement)
- return;
-
- var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture.getHtmlElementObj());
- if (cacheTextureForColor) {
- this._colorized = true;
- //generate color texture cache
- if (locElement instanceof HTMLCanvasElement && !this._rectRotated && !this._newTextureWhenChangeColor)
- cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect, locElement);
- else {
- locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect);
- locTexture = new cc.Texture2D();
- locTexture.initWithElement(locElement);
- locTexture.handleLoadedTexture();
- this.setTexture(locTexture);
- }
- }
- }
- },
-
- _setTextureCoords:function (rect) {
- rect = cc.RECT_POINTS_TO_PIXELS(rect);
-
- var tex = this._batchNode ? this._textureAtlas.getTexture() : this._texture;
- if (!tex)
- return;
-
- var atlasWidth = tex.getPixelsWide();
- var atlasHeight = tex.getPixelsHigh();
-
- var left, right, top, bottom, tempSwap, locQuad = this._quad;
- if (this._rectRotated) {
- if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
- left = (2 * rect.x + 1) / (2 * atlasWidth);
- right = left + (rect.height * 2 - 2) / (2 * atlasWidth);
- top = (2 * rect.y + 1) / (2 * atlasHeight);
- bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight);
- } else {
- left = rect.x / atlasWidth;
- right = (rect.x + rect.height) / atlasWidth;
- top = rect.y / atlasHeight;
- bottom = (rect.y + rect.width) / atlasHeight;
- }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
-
- if (this._flippedX) {
- tempSwap = top;
- top = bottom;
- bottom = tempSwap;
- }
-
- if (this._flippedY) {
- tempSwap = left;
- left = right;
- right = tempSwap;
- }
-
- locQuad.bl.texCoords.u = left;
- locQuad.bl.texCoords.v = top;
- locQuad.br.texCoords.u = left;
- locQuad.br.texCoords.v = bottom;
- locQuad.tl.texCoords.u = right;
- locQuad.tl.texCoords.v = top;
- locQuad.tr.texCoords.u = right;
- locQuad.tr.texCoords.v = bottom;
- } else {
- if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
- left = (2 * rect.x + 1) / (2 * atlasWidth);
- right = left + (rect.width * 2 - 2) / (2 * atlasWidth);
- top = (2 * rect.y + 1) / (2 * atlasHeight);
- bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight);
- } else {
- left = rect.x / atlasWidth;
- right = (rect.x + rect.width) / atlasWidth;
- top = rect.y / atlasHeight;
- bottom = (rect.y + rect.height) / atlasHeight;
- } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
-
- if (this._flippedX) {
- tempSwap = left;
- left = right;
- right = tempSwap;
- }
-
- if (this._flippedY) {
- tempSwap = top;
- top = bottom;
- bottom = tempSwap;
- }
-
- locQuad.bl.texCoords.u = left;
- locQuad.bl.texCoords.v = bottom;
- locQuad.br.texCoords.u = right;
- locQuad.br.texCoords.v = bottom;
- locQuad.tl.texCoords.u = left;
- locQuad.tl.texCoords.v = top;
- locQuad.tr.texCoords.u = right;
- locQuad.tr.texCoords.v = top;
- }
- this._quadDirty = true;
- },
- /**
- * draw sprite to canvas
- */
- draw: null,
-
- _drawForWebGL: function () {
- if (!this._textureLoaded)
- return;
-
- var gl = cc.renderContext, locTexture = this._texture;
- //cc.Assert(!this._batchNode, "If cc.Sprite is being rendered by cc.SpriteBatchNode, cc.Sprite#draw SHOULD NOT be called");
-
- if (locTexture) {
- if (locTexture._isLoaded) {
- this._shaderProgram.use();
- this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
-
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
- //optimize performance for javascript
- cc.glBindTexture2DN(0, locTexture); // = cc.glBindTexture2D(locTexture);
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX);
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer);
- if (this._quadDirty) {
- gl.bufferData(gl.ARRAY_BUFFER, this._quad.arrayBuffer, gl.DYNAMIC_DRAW);
- this._quadDirty = false;
- }
- gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 24, 0); //cc.VERTEX_ATTRIB_POSITION
- gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 24, 12); //cc.VERTEX_ATTRIB_COLOR
- gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 24, 16); //cc.VERTEX_ATTRIB_TEX_COORDS
-
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- }
- } else {
- this._shaderProgram.use();
- this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
-
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
- cc.glBindTexture2D(null);
-
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR);
-
- gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer);
- if (this._quadDirty) {
- cc.renderContext.bufferData(cc.renderContext.ARRAY_BUFFER, this._quad.arrayBuffer, cc.renderContext.STATIC_DRAW);
- this._quadDirty = false;
- }
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0);
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- }
- cc.g_NumberOfDraws++;
- if (cc.SPRITE_DEBUG_DRAW === 0)
- return;
-
- if (cc.SPRITE_DEBUG_DRAW === 1) {
- // draw bounding box
- var locQuad = this._quad;
- var verticesG1 = [
- cc.p(locQuad.tl.vertices.x, locQuad.tl.vertices.y),
- cc.p(locQuad.bl.vertices.x, locQuad.bl.vertices.y),
- cc.p(locQuad.br.vertices.x, locQuad.br.vertices.y),
- cc.p(locQuad.tr.vertices.x, locQuad.tr.vertices.y)
- ];
- cc.drawingUtil.drawPoly(verticesG1, 4, true);
- } else if (cc.SPRITE_DEBUG_DRAW === 2) {
- // draw texture box
- var drawSizeG2 = this.getTextureRect().size;
- var offsetPixG2 = this.getOffsetPosition();
- var verticesG2 = [cc.p(offsetPixG2.x, offsetPixG2.y), cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y),
- cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y + drawSizeG2.height), cc.p(offsetPixG2.x, offsetPixG2.y + drawSizeG2.height)];
- cc.drawingUtil.drawPoly(verticesG2, 4, true);
- } // CC_SPRITE_DEBUG_DRAW
- },
-
- _drawForCanvas: function (ctx) {
- if (!this._textureLoaded)
- return;
-
- var context = ctx || cc.renderContext;
- if (this._isLighterMode)
- context.globalCompositeOperation = 'lighter';
-
- var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY();
-
- context.globalAlpha = this._displayedOpacity / 255;
- var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition, locDrawSizeCanvas = this._drawSize_Canvas;
- var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height, locTextureCoord = this._textureRect_Canvas;
- locDrawSizeCanvas.width = locRect.width * locEGL_ScaleX;
- locDrawSizeCanvas.height = locRect.height * locEGL_ScaleY;
-
- if (this._flippedX || this._flippedY) {
- context.save();
- if (this._flippedX) {
- flipXOffset = -locOffsetPosition.x - locRect.width;
- context.scale(-1, 1);
- }
- if (this._flippedY) {
- flipYOffset = locOffsetPosition.y;
- context.scale(1, -1);
- }
- }
-
- flipXOffset *= locEGL_ScaleX;
- flipYOffset *= locEGL_ScaleY;
-
- if (this._texture && locRect.width > 0) {
- var image = this._texture.getHtmlElementObj();
- if (this._colorized) {
- context.drawImage(image,
- 0, 0, locTextureCoord.width, locTextureCoord.height,
- flipXOffset, flipYOffset, locDrawSizeCanvas.width, locDrawSizeCanvas.height);
- } else {
- context.drawImage(image,
- locTextureCoord.x, locTextureCoord.y, locTextureCoord.width, locTextureCoord.height,
- flipXOffset, flipYOffset, locDrawSizeCanvas.width , locDrawSizeCanvas.height);
- }
- } else if (locContentSize.width !== 0) {
- var curColor = this.getColor();
- context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)";
- context.fillRect(flipXOffset, flipYOffset, locContentSize.width * locEGL_ScaleX, locContentSize.height * locEGL_ScaleY);
- }
-
- if (cc.SPRITE_DEBUG_DRAW === 1) {
- // draw bounding box
- context.strokeStyle = "rgba(0,255,0,1)";
- flipXOffset /= locEGL_ScaleX;
- flipYOffset /= locEGL_ScaleY;
- flipYOffset = -flipYOffset;
- var vertices1 = [cc.p(flipXOffset, flipYOffset),
- cc.p(flipXOffset + locRect.width, flipYOffset),
- cc.p(flipXOffset + locRect.width, flipYOffset - locRect.height),
- cc.p(flipXOffset, flipYOffset - locRect.height)];
- cc.drawingUtil.drawPoly(vertices1, 4, true);
- } else if (cc.SPRITE_DEBUG_DRAW === 2) {
- // draw texture box
- context.strokeStyle = "rgba(0,255,0,1)";
- var drawSize = this._rect.size;
- flipYOffset = -flipYOffset;
- var vertices2 = [cc.p(flipXOffset, flipYOffset), cc.p(flipXOffset + drawSize.width, flipYOffset),
- cc.p(flipXOffset + drawSize.width, flipYOffset - drawSize.height), cc.p(flipXOffset, flipYOffset - drawSize.height)];
- cc.drawingUtil.drawPoly(vertices2, 4, true);
- }
- if (this._flippedX || this._flippedY)
- context.restore();
- cc.g_NumberOfDraws++;
- }
-});
-
-if(cc.Browser.supportWebGL){
- cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForWebGL;
- cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForWebGL;
- cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForWebGL;
- cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForWebGL;
- cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForWebGL;
- cc.Sprite.prototype.init = cc.Sprite.prototype._initForWebGL;
- cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForWebGL;
- cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForWebGL;
- cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForWebGL;
- cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForWebGL;
- cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForWebGL;
- cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForWebGL;
- cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForWebGL;
- cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForWebGL;
- cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForWebGL;
- cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForWebGL;
- cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForWebGL;
- cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForWebGL;
- cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForWebGL;
-}else{
- cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForCanvas;
- cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForCanvas;
- cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForCanvas;
- cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForCanvas;
- cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForCanvas;
- cc.Sprite.prototype.init = cc.Sprite.prototype._initForCanvas;
- cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForCanvas;
- cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForCanvas;
- cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForCanvas;
- cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForCanvas;
- cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForCanvas;
- cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForCanvas;
- cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForCanvas;
- cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForCanvas;
- cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForCanvas;
- cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForCanvas;
- cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForCanvas;
- cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForCanvas;
- cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForCanvas;
-}
-
-/**
- *
- * Creates a sprite with an exsiting texture contained in a CCTexture2D object
- * After creation, the rect will be the size of the texture, and the offset will be (0,0).
- *
- * @constructs
- * @param {cc.Texture2D} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites.
- * @param {cc.Rect} rect Only the contents inside the rect of this texture will be applied for this sprite.
- * @return {cc.Sprite} A valid sprite object
- * @example
- * //get an image
- * var img = cc.TextureCache.getInstance().addImage("HelloHTML5World.png");
- *
- * //create a sprite with texture
- * var sprite1 = cc.Sprite.createWithTexture(img);
- *
- * //create a sprite with texture and rect
- * var sprite2 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320));
- *
- */
-cc.Sprite.createWithTexture = function (texture, rect) {
- var argnum = arguments.length;
- var sprite = new cc.Sprite();
- switch (argnum) {
- case 1:
- /** Creates an sprite with a texture.
- The rect used will be the size of the texture.
- The offset will be (0,0).
- */
- if (sprite && sprite.initWithTexture(texture))
- return sprite;
- return null;
- break;
-
- case 2:
- /** Creates an sprite with a texture and a rect.
- The offset will be (0,0).
- */
- if (sprite && sprite.initWithTexture(texture, rect))
- return sprite;
- return null;
- break;
-
- default:
- throw "Sprite.createWithTexture(): Argument must be non-nil ";
- break;
- }
-};
-
-/**
- * Create a sprite with filename and rect
- * @constructs
- * @param {String} fileName The string which indicates a path to image file, e.g., "scene1/monster.png".
- * @param {cc.Rect} rect Only the contents inside rect of pszFileName's texture will be applied for this sprite.
- * @return {cc.Sprite} A valid sprite object
- * @example
- * //create a sprite with filename
- * var sprite1 = cc.Sprite.create("HelloHTML5World.png");
- *
- * //create a sprite with filename and rect
- * var sprite2 = cc.Sprite.create("HelloHTML5World.png",cc.rect(0,0,480,320));
- */
-cc.Sprite.create = function (fileName, rect) {
- var argnum = arguments.length;
- var sprite = new cc.Sprite();
- if (argnum === 0) {
- if (sprite.init())
- return sprite;
- } else {
- /** Creates an sprite with an image filename.
- If the rect equal undefined, the rect used will be the size of the image.
- The offset will be (0,0).
- */
- if (sprite && sprite.init(fileName, rect))
- return sprite;
- }
- return null;
-};
-
-/**
- *
- * Creates a sprite with a sprite frame.
- *
- * A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param.
- * If the CCSpriteFrame doesn't exist it will raise an exception.
- *
- * @param {String} spriteFrameName A sprite frame which involves a texture and a rect
- * @return {cc.Sprite} A valid sprite object
- * @example
- *
- * //create a sprite with a sprite frame
- * var sprite = cc.Sprite.createWithSpriteFrameName('grossini_dance_01.png');
- */
-cc.Sprite.createWithSpriteFrameName = function (spriteFrameName) {
- var spriteFrame = null;
- if (typeof(spriteFrameName) == 'string') {
- spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName);
- if (!spriteFrame) {
- cc.log("Invalid spriteFrameName: " + spriteFrameName);
- return null;
- }
- } else {
- cc.log("Invalid argument. Expecting string.");
- return null;
- }
- var sprite = new cc.Sprite();
- if (sprite && sprite.initWithSpriteFrame(spriteFrame)) {
- return sprite;
- }
- return null;
-};
-
-/**
- *
- * Creates a sprite with a sprite frame.
- *
- * A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param.
- * If the CCSpriteFrame doesn't exist it will raise an exception.
- *
- * @param {cc.SpriteFrame} spriteFrame A sprite frame which involves a texture and a rect
- * @return {cc.Sprite} A valid sprite object
- * @example
- * //get a sprite frame
- * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png");
- *
- * //create a sprite with a sprite frame
- * var sprite = cc.Sprite.createWithSpriteFrame(spriteFrame);
- */
-cc.Sprite.createWithSpriteFrame = function (spriteFrame) {
- var sprite = new cc.Sprite();
- if (sprite && sprite.initWithSpriteFrame(spriteFrame)) {
- return sprite;
- }
- return null;
-};
diff --git a/cocos2d/sprite_nodes/CCSpriteBatchNode.js b/cocos2d/sprite_nodes/CCSpriteBatchNode.js
deleted file mode 100644
index 535d3e7ae3..0000000000
--- a/cocos2d/sprite_nodes/CCSpriteBatchNode.js
+++ /dev/null
@@ -1,1048 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * @constant
- * @type Number
- */
-cc.DEFAULT_SPRITE_BATCH_CAPACITY = 29;
-
-/**
- *
- * In Canvas render mode ,cc.SpriteBatchNodeCanvas is like a normal node: if it contains children.
- * If its _useCache is set to true, it can cache the result that all children of SpriteBatchNode to a canvas
- * (often known as "batch draw").
- *
- * A cc.SpriteBatchNode can reference one and only one texture (one image file, one texture atlas).
- * Only the cc.Sprites that are contained in that texture can be added to the cc.SpriteBatchNode.
- * All cc.Sprites added to a cc.SpriteBatchNode are drawn in one WebGL draw call.
- * If the cc.Sprites are not added to a cc.SpriteBatchNode then an WebGL draw call will be needed for each one, which is less efficient.
- *
- * Limitations:
- * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is cc.Sprite or any subclass of cc.Sprite.
- * eg: particles, labels and layer can't be added to a cc.SpriteBatchNode.
- * - Either all its children are Aliased or Antialiased. It can't be a mix.
- * This is because "alias" is a property of the texture, and all the sprites share the same texture.
- *
- * @class
- * @extends cc.Node
- * @example
- * //create a SpriteBatchNode
- * var parent2 = cc.SpriteBatchNode.create("res/animations/grossini.png", 50);
- */
-cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{
- _textureAtlas:null,
- _blendFunc:null,
- // all descendants: chlidren, gran children, etc...
- _descendants:null,
-
- /**
- *
- * This is the opposite of "addQuadFromSprite.
- * It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas
- *
- * @param {cc.Sprite} child
- * @param {Number} z zOrder
- * @param {Number} aTag
- * @return {cc.SpriteBatchNode}
- */
- addSpriteWithoutQuad:function (child, z, aTag) {
- cc.Assert(child != null, "SpriteBatchNode.addQuadFromSprite():Argument must be non-nil");
- cc.Assert((child instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children");
-
- // quad index is Z
- child.setAtlasIndex(z);
-
- // XXX: optimize with a binary search
- var i = 0, locDescendants = this._descendants;
- if (locDescendants && locDescendants.length > 0) {
- for (var index = 0; index < locDescendants.length; index++) {
- var obj = locDescendants[index];
- if (obj && (obj.getAtlasIndex() >= z))
- ++i;
- }
- }
- this._descendants = cc.ArrayAppendObjectToIndex(locDescendants, child, i);
-
- // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array
- cc.Node.prototype.addChild.call(this, child, z, aTag);
-
- //#issue 1262 don't use lazy sorting, tiles are added as quads not as sprites, so sprites need to be added in order
- this.reorderBatch(false);
- return this;
- },
-
- // property
- /**
- * Return TextureAtlas of cc.SpriteBatchNode
- * @return {cc.TextureAtlas}
- */
- getTextureAtlas:function () {
- return this._textureAtlas;
- },
-
- /**
- * TextureAtlas of cc.SpriteBatchNode setter
- * @param {cc.TextureAtlas} textureAtlas
- */
- setTextureAtlas:function (textureAtlas) {
- if (textureAtlas != this._textureAtlas) {
- this._textureAtlas = textureAtlas;
- }
- },
-
- /**
- * Return Descendants of cc.SpriteBatchNode
- * @return {Array}
- */
- getDescendants:function () {
- return this._descendants;
- },
-
- /**
- *
- * initializes a cc.SpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- * The file will be loaded using the TextureMgr.
- *
- * @param {String} fileImage
- * @param {Number} capacity
- * @return {Boolean}
- */
- initWithFile:function (fileImage, capacity) {
- var texture2D = cc.TextureCache.getInstance().textureForKey(fileImage);
- if (!texture2D)
- texture2D = cc.TextureCache.getInstance().addImage(fileImage);
- return this.initWithTexture(texture2D, capacity);
- },
-
- _setNodeDirtyForCache:function () {
- this._cacheDirty = true;
- },
-
- /**
- *
- * initializes a cc.SpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- * The file will be loaded using the TextureMgr.
- *
- * @param {String} fileImage
- * @param {Number} capacity
- * @return {Boolean}
- */
- init:function (fileImage, capacity) {
- var texture2D = cc.TextureCache.getInstance().textureForKey(fileImage);
- if (!texture2D)
- texture2D = cc.TextureCache.getInstance().addImage(fileImage);
- return this.initWithTexture(texture2D, capacity);
- },
-
- /**
- * increase Atlas Capacity
- */
- increaseAtlasCapacity:function () {
- // if we're going beyond the current TextureAtlas's capacity,
- // all the previously initialized sprites will need to redo their texture coords
- // this is likely computationally expensive
- var locCapacity = this._textureAtlas.getCapacity();
- var quantity = Math.floor((locCapacity + 1) * 4 / 3);
-
- cc.log("cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from " + locCapacity + " to " + quantity + ".");
-
- if (!this._textureAtlas.resizeCapacity(quantity)) {
- // serious problems
- cc.log("cocos2d: WARNING: Not enough memory to resize the atlas");
- cc.Assert(false, "Not enough memory to resize the atla");
- }
- },
-
- /**
- * removes a child given a certain index. It will also cleanup the running actions depending on the cleanup parameter.
- * @warning Removing a child from a cc.SpriteBatchNode is very slow
- * @param {Number} index
- * @param {Boolean} doCleanup
- */
- removeChildAtIndex:function (index, doCleanup) {
- this.removeChild(this._children[index], doCleanup);
- },
-
- /**
- * rebuild index in order for child
- * @param {cc.Sprite} pobParent
- * @param {Number} index
- * @return {Number}
- */
- rebuildIndexInOrder:function (pobParent, index) {
- var children = pobParent.getChildren();
- if (children && children.length > 0) {
- for (var i = 0; i < children.length; i++) {
- var obj = children[i];
- if (obj && (obj.getZOrder() < 0)) {
- index = this.rebuildIndexInOrder(obj, index);
- }
- }
- }
- // ignore self (batch node)
- if (!pobParent == this) {
- pobParent.setAtlasIndex(index);
- index++;
- }
- if (children && children.length > 0) {
- for (i = 0; i < children.length; i++) {
- obj = children[i];
- if (obj && (obj.getZOrder() >= 0)) {
- index = this.rebuildIndexInOrder(obj, index);
- }
- }
- }
- return index;
- },
-
- /**
- * get highest atlas index in child
- * @param {cc.Sprite} sprite
- * @return {Number}
- */
- highestAtlasIndexInChild:function (sprite) {
- var children = sprite.getChildren();
-
- if (!children || children.length == 0)
- return sprite.getAtlasIndex();
- else
- return this.highestAtlasIndexInChild(children[children.length - 1]);
- },
-
- /**
- * get lowest atlas index in child
- * @param {cc.Sprite} sprite
- * @return {Number}
- */
- lowestAtlasIndexInChild:function (sprite) {
- var children = sprite.getChildren();
-
- if (!children || children.length == 0)
- return sprite.getAtlasIndex();
- else
- return this.lowestAtlasIndexInChild(children[children.length - 1]);
- },
-
- /**
- * get atlas index for child
- * @param {cc.Sprite} sprite
- * @param {Number} nZ
- * @return {Number}
- */
- atlasIndexForChild:function (sprite, nZ) {
- var brothers = sprite.getParent().getChildren();
- var childIndex = cc.ArrayGetIndexOfObject(brothers, sprite);
-
- // ignore parent Z if parent is spriteSheet
- var ignoreParent = sprite.getParent() == this;
- var previous = null;
- if (childIndex > 0 && childIndex < cc.UINT_MAX)
- previous = brothers[childIndex - 1];
-
- // first child of the sprite sheet
- if (ignoreParent) {
- if (childIndex == 0)
- return 0;
- return this.highestAtlasIndexInChild(previous) + 1;
- }
-
- // parent is a cc.Sprite, so, it must be taken into account
- // first child of an cc.Sprite ?
- var selParent;
- if (childIndex == 0) {
- selParent = sprite.getParent();
-
- // less than parent and brothers
- if (nZ < 0)
- return selParent.getAtlasIndex();
- else
- return selParent.getAtlasIndex() + 1;
- } else {
- // previous & sprite belong to the same branch
- if ((previous.getZOrder() < 0 && nZ < 0) || (previous.getZOrder() >= 0 && nZ >= 0))
- return this.highestAtlasIndexInChild(previous) + 1;
-
- // else (previous < 0 and sprite >= 0 )
- selParent = sprite.getParent();
- return selParent.getAtlasIndex() + 1;
- }
- },
-
- /**
- * Sprites use this to start sortChildren, don't call this manually
- * @param {Boolean} reorder
- */
- reorderBatch:function (reorder) {
- this._reorderChildDirty = reorder;
- },
-
- /**
- * set the source blending function for the texture
- * @param {Number | cc.BlendFunc} src
- * @param {Number} dst
- */
- setBlendFunc:function (src, dst) {
- if (arguments.length == 1)
- this._blendFunc = src;
- else
- this._blendFunc = {src:src, dst:dst};
- },
-
- /**
- * returns the blending function used for the texture
- * @return {cc.BlendFunc}
- */
- getBlendFunc:function () {
- return this._blendFunc;
- },
-
- /**
- * (override reorderChild of cc.Node)
- * @override
- * @param {cc.Sprite} child
- * @param {Number} zOrder
- */
- reorderChild:function (child, zOrder) {
- cc.Assert(child != null, "SpriteBatchNode.addChild():the child should not be null");
- cc.Assert(this._children.indexOf(child) > -1, "SpriteBatchNode.addChild():Child doesn't belong to Sprite");
-
- if (zOrder === child.getZOrder())
- return;
-
- //set the z-order and sort later
- cc.Node.prototype.reorderChild.call(this, child, zOrder);
- this.setNodeDirty();
- },
-
- /**
- * remove child from cc.SpriteBatchNode (override removeChild of cc.Node)
- * @param {cc.Sprite} child
- * @param cleanup
- */
- removeChild:function (child, cleanup) {
- // explicit null handling
- if (child == null)
- return;
-
- cc.Assert(this._children.indexOf(child) > -1, "SpriteBatchNode.addChild():sprite batch node should contain the child");
-
- // cleanup before removing
- this.removeSpriteFromAtlas(child);
- cc.Node.prototype.removeChild.call(this, child, cleanup);
- },
-
- _mvpMatrix:null,
- _textureForCanvas:null,
- _useCache:false,
- _originalTexture:null,
-
- /**
- * Constructor
- * @param {String} fileImage
- */
- ctor: null,
-
- _ctorForCanvas: function (fileImage) {
- cc.Node.prototype.ctor.call(this);
- if (fileImage)
- this.init(fileImage, cc.DEFAULT_SPRITE_BATCH_CAPACITY);
- },
-
- _ctorForWebGL: function (fileImage) {
- cc.Node.prototype.ctor.call(this);
- this._mvpMatrix = new cc.kmMat4();
- if (fileImage)
- this.init(fileImage, cc.DEFAULT_SPRITE_BATCH_CAPACITY);
- },
-
-
- /**
- *
- * Updates a quad at a certain index into the texture atlas. The CCSprite won't be added into the children array.
- * This method should be called only when you are dealing with very big AtlasSrite and when most of the cc.Sprite won't be updated.
- * For example: a tile map (cc.TMXMap) or a label with lots of characters (BitmapFontAtlas)
- *
- * @param {cc.Sprite} sprite
- * @param {Number} index
- */
- updateQuadFromSprite:null,
-
- _updateQuadFromSpriteForCanvas:function (sprite, index) {
- cc.Assert(sprite != null, "SpriteBatchNode.addQuadFromSprite():Argument must be non-nil");
- cc.Assert((sprite instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children");
-
- //
- // update the quad directly. Don't add the sprite to the scene graph
- //
- sprite.setBatchNode(this);
- sprite.setAtlasIndex(index);
-
- sprite.setDirty(true);
- // UpdateTransform updates the textureAtlas quad
- sprite.updateTransform();
- },
-
- _updateQuadFromSpriteForWebGL:function (sprite, index) {
- cc.Assert(sprite != null, "SpriteBatchNode.addQuadFromSprite():Argument must be non-nil");
- cc.Assert((sprite instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children");
-
- // make needed room
- var locCapacity = this._textureAtlas.getCapacity();
- while (index >= locCapacity || locCapacity == this._textureAtlas.getTotalQuads()) {
- this.increaseAtlasCapacity();
- }
-
- //
- // update the quad directly. Don't add the sprite to the scene graph
- //
- sprite.setBatchNode(this);
- sprite.setAtlasIndex(index);
-
- sprite.setDirty(true);
- // UpdateTransform updates the textureAtlas quad
- sprite.updateTransform();
- },
-
- _swap:function (oldIndex, newIndex) {
- var locDescendants = this._descendants;
- var locTextureAtlas = this._textureAtlas;
- var quads = locTextureAtlas.getQuads();
- var tempItem = locDescendants[oldIndex];
- var tempIteQuad = cc.V3F_C4B_T2F_QuadCopy(quads[oldIndex]);
-
- //update the index of other swapped item
- locDescendants[newIndex].setAtlasIndex(oldIndex);
- locDescendants[oldIndex] = locDescendants[newIndex];
-
- locTextureAtlas.updateQuad(quads[newIndex], oldIndex);
- locDescendants[newIndex] = tempItem;
- locTextureAtlas.updateQuad(tempIteQuad, newIndex);
- },
-
- /**
- *
- * Inserts a quad at a certain index into the texture atlas. The cc.Sprite won't be added into the children array.
- * This method should be called only when you are dealing with very big AtlasSprite and when most of the cc.Sprite won't be updated.
- * For example: a tile map (cc.TMXMap) or a label with lots of characters (cc.LabelBMFont)
- *
- * @param {cc.Sprite} sprite
- * @param {Number} index
- */
- insertQuadFromSprite:null,
-
- _insertQuadFromSpriteForCanvas:function (sprite, index) {
- cc.Assert(sprite != null, "Argument must be non-NULL");
- cc.Assert(sprite instanceof cc.Sprite, "cc.SpriteBatchNode only supports cc.Sprites as children");
-
- //
- // update the quad directly. Don't add the sprite to the scene graph
- //
- sprite.setBatchNode(this);
- sprite.setAtlasIndex(index);
-
- // XXX: updateTransform will update the textureAtlas too, using updateQuad.
- // XXX: so, it should be AFTER the insertQuad
- sprite.setDirty(true);
- sprite.updateTransform();
- this._children = cc.ArrayAppendObjectToIndex(this._children, sprite, index);
- },
-
- _insertQuadFromSpriteForWebGL:function (sprite, index) {
- cc.Assert(sprite != null, "Argument must be non-NULL");
- cc.Assert(sprite instanceof cc.Sprite, "cc.SpriteBatchNode only supports cc.Sprites as children");
-
- // make needed room
- var locTextureAtlas = this._textureAtlas;
- while (index >= locTextureAtlas.getCapacity() || locTextureAtlas.getCapacity() === locTextureAtlas.getTotalQuads())
- this.increaseAtlasCapacity();
-
- //
- // update the quad directly. Don't add the sprite to the scene graph
- //
- sprite.setBatchNode(this);
- sprite.setAtlasIndex(index);
- locTextureAtlas.insertQuad(sprite.getQuad(), index);
-
- // XXX: updateTransform will update the textureAtlas too, using updateQuad.
- // XXX: so, it should be AFTER the insertQuad
- sprite.setDirty(true);
- sprite.updateTransform();
- },
-
- _updateAtlasIndex:function (sprite, curIndex) {
- var count = 0;
- var pArray = sprite.getChildren();
- if (pArray)
- count = pArray.length;
-
- var oldIndex = 0;
- if (count === 0) {
- oldIndex = sprite.getAtlasIndex();
- sprite.setAtlasIndex(curIndex);
- sprite.setOrderOfArrival(0);
- if (oldIndex != curIndex)
- this._swap(oldIndex, curIndex);
- curIndex++;
- } else {
- var needNewIndex = true;
- if (pArray[0].getZOrder() >= 0) {
- //all children are in front of the parent
- oldIndex = sprite.getAtlasIndex();
- sprite.setAtlasIndex(curIndex);
- sprite.setOrderOfArrival(0);
- if (oldIndex != curIndex)
- this._swap(oldIndex, curIndex);
- curIndex++;
- needNewIndex = false;
- }
- for (var i = 0; i < pArray.length; i++) {
- var child = pArray[i];
- if (needNewIndex && child.getZOrder() >= 0) {
- oldIndex = sprite.getAtlasIndex();
- sprite.setAtlasIndex(curIndex);
- sprite.setOrderOfArrival(0);
- if (oldIndex != curIndex) {
- this._swap(oldIndex, curIndex);
- }
- curIndex++;
- needNewIndex = false;
- }
- curIndex = this._updateAtlasIndex(child, curIndex);
- }
-
- if (needNewIndex) {
- //all children have a zOrder < 0)
- oldIndex = sprite.getAtlasIndex();
- sprite.setAtlasIndex(curIndex);
- sprite.setOrderOfArrival(0);
- if (oldIndex != curIndex) {
- this._swap(oldIndex, curIndex);
- }
- curIndex++;
- }
- }
-
- return curIndex;
- },
-
- _updateBlendFunc:function () {
- if (!this._textureAtlas.getTexture().hasPremultipliedAlpha()) {
- this._blendFunc.src = gl.SRC_ALPHA;
- this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA;
- }
- },
-
- /**
- *
- * initializes a CCSpriteBatchNode with a texture2d and capacity of children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- *
- * @param {cc.Texture2D} tex
- * @param {Number} [capacity]
- * @return {Boolean}
- */
- initWithTexture:null,
-
- _initWithTextureForCanvas:function (tex, capacity) {
- this._children = [];
- this._descendants = [];
-
- this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
-
- this._originalTexture = tex;
- this._textureForCanvas = tex;
- return true;
- },
-
- _initWithTextureForWebGL:function (tex, capacity) {
- this._children = [];
- this._descendants = [];
-
- this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
- capacity = capacity || cc.DEFAULT_SPRITE_BATCH_CAPACITY;
- this._textureAtlas = new cc.TextureAtlas();
- this._textureAtlas.initWithTexture(tex, capacity);
- this._updateBlendFunc();
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR));
- return true;
- },
-
- /**
- * add child helper
- * @param {cc.Sprite} sprite
- * @param {Number} index
- */
- insertChild:function (sprite, index) {
- sprite.setBatchNode(this);
- sprite.setAtlasIndex(index);
- sprite.setDirty(true);
-
- var locTextureAtlas = this._textureAtlas;
- if (locTextureAtlas.getTotalQuads() >= locTextureAtlas.getCapacity())
- this.increaseAtlasCapacity();
-
- locTextureAtlas.insertQuad(sprite.getQuad(), index);
- this._descendants = cc.ArrayAppendObjectToIndex(this._descendants, sprite, index);
-
- // update indices
- var i = index + 1, locDescendant = this._descendants;
- if (locDescendant && locDescendant.length > 0) {
- for (; i < locDescendant.length; i++)
- locDescendant[i].setAtlasIndex(locDescendant[i].getAtlasIndex() + 1);
- }
-
- // add children recursively
- var locChildren = sprite.getChildren();
- if (locChildren && locChildren.length > 0) {
- for (i = 0; i < locChildren.length; i++) {
- if (locChildren[i]) {
- var getIndex = this.atlasIndexForChild(locChildren[i], locChildren[i].getZOrder());
- this.insertChild(locChildren[i], getIndex);
- }
- }
- }
- },
-
- /**
- * addChild helper, faster than insertChild
- * @param {cc.Sprite} sprite
- */
- appendChild:null,
-
- _appendChildForCanvas:function (sprite) {
- this._reorderChildDirty = true;
- sprite.setBatchNode(this);
- sprite.setDirty(true);
-
- this._descendants.push(sprite);
- var index = this._descendants.length - 1;
- sprite.setAtlasIndex(index);
-
- // add children recursively
- var children = sprite.getChildren();
- for (var i = 0; i < children.length; i++)
- this.appendChild(children[i]);
- },
-
- _appendChildForWebGL:function (sprite) {
- this._reorderChildDirty = true;
- sprite.setBatchNode(this);
- sprite.setDirty(true);
-
- this._descendants.push(sprite);
- var index = this._descendants.length - 1;
- sprite.setAtlasIndex(index);
-
- var locTextureAtlas = this._textureAtlas;
- if (locTextureAtlas.getTotalQuads() == locTextureAtlas.getCapacity())
- this.increaseAtlasCapacity();
- locTextureAtlas.insertQuad(sprite.getQuad(), index);
-
- // add children recursively
- var children = sprite.getChildren();
- for (var i = 0; i < children.length; i++)
- this.appendChild(children[i]);
- },
-
- /**
- * remove sprite from TextureAtlas
- * @param {cc.Sprite} sprite
- */
- removeSpriteFromAtlas:null,
-
- _removeSpriteFromAtlasForCanvas:function (sprite) {
- // Cleanup sprite. It might be reused (issue #569)
- sprite.setBatchNode(null);
- var locDescendants = this._descendants;
- var index = cc.ArrayGetIndexOfObject(locDescendants, sprite);
- if (index != -1) {
- cc.ArrayRemoveObjectAtIndex(locDescendants, index);
-
- // update all sprites beyond this one
- var len = locDescendants.length;
- for (; index < len; ++index) {
- var s = locDescendants[index];
- s.setAtlasIndex(s.getAtlasIndex() - 1);
- }
- }
-
- // remove children recursively
- var children = sprite.getChildren();
- if (children && children.length > 0) {
- for (var i = 0; i < children.length; i++)
- if (children[i])
- this.removeSpriteFromAtlas(children[i]);
- }
- },
-
- _removeSpriteFromAtlasForWebGL:function (sprite) {
- this._textureAtlas.removeQuadAtIndex(sprite.getAtlasIndex()); // remove from TextureAtlas
-
- // Cleanup sprite. It might be reused (issue #569)
- sprite.setBatchNode(null);
-
- var locDescendants = this._descendants;
- var index = cc.ArrayGetIndexOfObject(locDescendants, sprite);
- if (index != -1) {
- cc.ArrayRemoveObjectAtIndex(locDescendants, index);
-
- // update all sprites beyond this one
-
- var len = locDescendants.length;
- for (; index < len; ++index) {
- var s = locDescendants[index];
- s.setAtlasIndex(s.getAtlasIndex() - 1);
- }
- }
-
- // remove children recursively
- var children = sprite.getChildren();
- if (children && children.length > 0) {
- for (var i = 0; i < children.length; i++)
- if (children[i])
- this.removeSpriteFromAtlas(children[i]);
- }
- },
- // CCTextureProtocol
- /**
- * Return texture of cc.SpriteBatchNode
- * @return {cc.Texture2D|HTMLImageElement|HTMLCanvasElement}
- */
- getTexture:null,
-
- _getTextureForCanvas:function () {
- return this._textureForCanvas;
- },
-
- _getTextureForWebGL:function () {
- return this._textureAtlas.getTexture();
- },
-
- /**
- * texture of cc.SpriteBatchNode setter
- * @param {cc.Texture2D} texture
- */
- setTexture:null,
-
- _setTextureForCanvas:function (texture) {
- this._textureForCanvas = texture;
- var locChildren = this._children;
- for (var i = 0; i < locChildren.length; i++)
- locChildren[i].setTexture(texture);
- },
-
- _setTextureForWebGL:function (texture) {
- this._textureAtlas.setTexture(texture);
- this._updateBlendFunc();
- },
-
- /**
- * don't call visit on it's children ( override visit of cc.Node )
- * @override
- * @param {CanvasRenderingContext2D} ctx
- */
- visit:null,
-
- _visitForCanvas:function (ctx) {
- var context = ctx || cc.renderContext;
- // quick return if not visible
- if (!this._visible)
- return;
-
- context.save();
- this.transform(ctx);
- var i, locChildren = this._children;
-
- if (locChildren) {
- this.sortAllChildren();
- for (i = 0; i < locChildren.length; i++) {
- if (locChildren[i])
- locChildren[i].visit(context);
- }
- }
-
- context.restore();
- },
-
- _visitForWebGL:function (ctx) {
- var gl = ctx || cc.renderContext;
-
- // CAREFUL:
- // This visit is almost identical to CocosNode#visit
- // with the exception that it doesn't call visit on it's children
- //
- // The alternative is to have a void CCSprite#visit, but
- // although this is less mantainable, is faster
- //
- if (!this._visible)
- return;
- cc.kmGLPushMatrix();
- var locGrid = this._grid;
- if (locGrid && locGrid.isActive()) {
- locGrid.beforeDraw();
- this.transformAncestors();
- }
- this.sortAllChildren();
- this.transform(gl);
- this.draw(gl);
- if (locGrid && locGrid.isActive())
- locGrid.afterDraw(this);
- cc.kmGLPopMatrix();
- this.setOrderOfArrival(0);
- },
-
- /**
- * add child to cc.SpriteBatchNode (override addChild of cc.Node)
- * @override
- * @param {cc.Sprite} child
- * @param {Number} [zOrder]
- * @param {Number} [tag]
- */
- addChild: null,
-
- _addChildForCanvas: function (child, zOrder, tag) {
- if (child == null)
- return;
-
- zOrder = (zOrder == null) ? child.getZOrder() : zOrder;
- tag = (tag == null) ? child.getTag() : tag;
-
- cc.Assert(child != null, "SpriteBatchNode.addChild():child should not be null");
- cc.Assert((child instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children");
-
- cc.Node.prototype.addChild.call(this, child, zOrder, tag);
- this.appendChild(child);
- this.setNodeDirty();
- },
-
- _addChildForWebGL: function (child, zOrder, tag) {
- if (child == null)
- return;
-
- zOrder = (zOrder == null) ? child.getZOrder() : zOrder;
- tag = (tag == null) ? child.getTag() : tag;
-
- cc.Assert(child != null, "SpriteBatchNode.addChild():child should not be null");
- cc.Assert((child instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children");
-
- // check cc.Sprite is using the same texture id
- cc.Assert(child.getTexture() == this._textureAtlas.getTexture(),
- "SpriteBatchNode.addChild():cc.Sprite is not using the same texture id");
- cc.Node.prototype.addChild.call(this, child, zOrder, tag);
- this.appendChild(child);
- this.setNodeDirty();
- },
-
- /**
- * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
- * (override removeAllChildren of cc.Node)
- * @param {Boolean} cleanup
- */
- removeAllChildren:null,
-
- _removeAllChildrenForCanvas:function (cleanup) {
- // Invalidate atlas index. issue #569
- // useSelfRender should be performed on all descendants. issue #1216
- var locDescendants = this._descendants;
- if (locDescendants && locDescendants.length > 0) {
- for (var i = 0, len = locDescendants.length; i < len; i++) {
- if (locDescendants[i])
- locDescendants[i].setBatchNode(null);
- }
- }
-
- cc.Node.prototype.removeAllChildren.call(this, cleanup);
- this._descendants = [];
- },
-
- _removeAllChildrenForWebGL:function (cleanup) {
- // Invalidate atlas index. issue #569
- // useSelfRender should be performed on all descendants. issue #1216
- var locDescendants = this._descendants;
- if (locDescendants && locDescendants.length > 0) {
- for (var i = 0, len = locDescendants.length; i < len; i++) {
- if (locDescendants[i])
- locDescendants[i].setBatchNode(null);
- }
- }
- cc.Node.prototype.removeAllChildren.call(this, cleanup);
- this._descendants = [];
- this._textureAtlas.removeAllQuads();
- },
-
- sortAllChildren:null,
-
- _sortAllChildrenForCanvas:function () {
- if (this._reorderChildDirty) {
- var i, j = 0, locChildren = this._children;
- var length = locChildren.length, tempChild;
- //insertion sort
- for (i = 1; i < length; i++) {
- var tempItem = locChildren[i];
- j = i - 1;
- tempChild = locChildren[j];
-
- //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
- while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder ||
- ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) {
- locChildren[j + 1] = tempChild;
- j = j - 1;
- tempChild = locChildren[j];
- }
- locChildren[j + 1] = tempItem;
- }
-
- //sorted now check all children
- if (locChildren.length > 0) {
- //first sort all children recursively based on zOrder
- this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren);
- }
- this._reorderChildDirty = false;
- }
- },
-
- _sortAllChildrenForWebGL:function () {
- if (this._reorderChildDirty) {
- var childrenArr = this._children;
- var i, j = 0, length = childrenArr.length, tempChild;
- //insertion sort
- for (i = 1; i < length; i++) {
- var tempItem = childrenArr[i];
- j = i - 1;
- tempChild = childrenArr[j];
-
- //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
- while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder ||
- ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) {
- childrenArr[j + 1] = tempChild;
- j = j - 1;
- tempChild = childrenArr[j];
- }
- childrenArr[j + 1] = tempItem;
- }
-
- //sorted now check all children
- if (childrenArr.length > 0) {
- //first sort all children recursively based on zOrder
- this._arrayMakeObjectsPerformSelector(childrenArr, cc.Node.StateCallbackType.sortAllChildren);
-
- var index = 0;
- //fast dispatch, give every child a new atlasIndex based on their relative zOrder (keep parent -> child relations intact)
- // and at the same time reorder descedants and the quads to the right index
- for (i = 0; i < childrenArr.length; i++)
- index = this._updateAtlasIndex(childrenArr[i], index);
- }
- this._reorderChildDirty = false;
- }
- },
- /**
- * draw cc.SpriteBatchNode (override draw of cc.Node)
- */
- draw:null,
-
- _drawForWebGL:function () {
- // Optimization: Fast Dispatch
- if (this._textureAtlas.getTotalQuads() === 0)
- return;
-
- //cc.NODE_DRAW_SETUP(this);
- this._shaderProgram.use();
- this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4();
- this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform);
- cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
-
- this._textureAtlas.drawQuads();
- }
-});
-
-if(cc.Browser.supportWebGL){
- cc.SpriteBatchNode.prototype.ctor = cc.SpriteBatchNode.prototype._ctorForWebGL;
- cc.SpriteBatchNode.prototype.updateQuadFromSprite = cc.SpriteBatchNode.prototype._updateQuadFromSpriteForWebGL;
- cc.SpriteBatchNode.prototype.insertQuadFromSprite = cc.SpriteBatchNode.prototype._insertQuadFromSpriteForWebGL;
- cc.SpriteBatchNode.prototype.initWithTexture = cc.SpriteBatchNode.prototype._initWithTextureForWebGL;
- cc.SpriteBatchNode.prototype.appendChild = cc.SpriteBatchNode.prototype._appendChildForWebGL;
- cc.SpriteBatchNode.prototype.removeSpriteFromAtlas = cc.SpriteBatchNode.prototype._removeSpriteFromAtlasForWebGL;
- cc.SpriteBatchNode.prototype.getTexture = cc.SpriteBatchNode.prototype._getTextureForWebGL;
- cc.SpriteBatchNode.prototype.setTexture = cc.SpriteBatchNode.prototype._setTextureForWebGL;
- cc.SpriteBatchNode.prototype.visit = cc.SpriteBatchNode.prototype._visitForWebGL;
- cc.SpriteBatchNode.prototype.addChild = cc.SpriteBatchNode.prototype._addChildForWebGL;
- cc.SpriteBatchNode.prototype.removeAllChildren = cc.SpriteBatchNode.prototype._removeAllChildrenForWebGL;
- cc.SpriteBatchNode.prototype.sortAllChildren = cc.SpriteBatchNode.prototype._sortAllChildrenForWebGL;
- cc.SpriteBatchNode.prototype.draw = cc.SpriteBatchNode.prototype._drawForWebGL;
-} else {
- cc.SpriteBatchNode.prototype.ctor = cc.SpriteBatchNode.prototype._ctorForCanvas;
- cc.SpriteBatchNode.prototype.updateQuadFromSprite = cc.SpriteBatchNode.prototype._updateQuadFromSpriteForCanvas;
- cc.SpriteBatchNode.prototype.insertQuadFromSprite = cc.SpriteBatchNode.prototype._insertQuadFromSpriteForCanvas;
- cc.SpriteBatchNode.prototype.initWithTexture = cc.SpriteBatchNode.prototype._initWithTextureForCanvas;
- cc.SpriteBatchNode.prototype.appendChild = cc.SpriteBatchNode.prototype._appendChildForCanvas;
- cc.SpriteBatchNode.prototype.removeSpriteFromAtlas = cc.SpriteBatchNode.prototype._removeSpriteFromAtlasForCanvas;
- cc.SpriteBatchNode.prototype.getTexture = cc.SpriteBatchNode.prototype._getTextureForCanvas;
- cc.SpriteBatchNode.prototype.setTexture = cc.SpriteBatchNode.prototype._setTextureForCanvas;
- cc.SpriteBatchNode.prototype.visit = cc.SpriteBatchNode.prototype._visitForCanvas;
- cc.SpriteBatchNode.prototype.removeAllChildren = cc.SpriteBatchNode.prototype._removeAllChildrenForCanvas;
- cc.SpriteBatchNode.prototype.addChild = cc.SpriteBatchNode.prototype._addChildForCanvas;
- cc.SpriteBatchNode.prototype.sortAllChildren = cc.SpriteBatchNode.prototype._sortAllChildrenForCanvas;
- cc.SpriteBatchNode.prototype.draw = cc.Node.prototype.draw;
-}
-
-/**
- *
- * creates a cc.SpriteBatchNodeCanvas with a file image (.png, .jpg etc) with a default capacity of 29 children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- * The file will be loaded using the TextureMgr.
- *
- * @param {String} fileImage
- * @param {Number} capacity
- * @return {cc.SpriteBatchNode}
- * @example
- * //create a SpriteBatchNode
- * var parent2 = cc.SpriteBatchNode.create("res/animations/grossini.png", 50);
- */
-cc.SpriteBatchNode.create = function (fileImage, capacity) {
- capacity = capacity || cc.DEFAULT_SPRITE_BATCH_CAPACITY;
- var batchNode = new cc.SpriteBatchNode();
- batchNode.init(fileImage, capacity);
- return batchNode;
-};
-
-/**
- *
- * creates a cc.SpriteBatchNodeCanvas with a texture2d and a default capacity of 29 children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- *
- * @param {cc.Texture2D} texture
- * @param {Number} capacity
- * @return {cc.SpriteBatchNode}
- */
-cc.SpriteBatchNode.createWithTexture = function (texture, capacity) {
- capacity = capacity || cc.DEFAULT_SPRITE_BATCH_CAPACITY;
- var batchNode = new cc.SpriteBatchNode();
- batchNode.initWithTexture(texture, capacity);
- return batchNode;
-};
\ No newline at end of file
diff --git a/cocos2d/sprite_nodes/CCSpriteFrame.js b/cocos2d/sprite_nodes/CCSpriteFrame.js
deleted file mode 100644
index d23e9aa6c6..0000000000
--- a/cocos2d/sprite_nodes/CCSpriteFrame.js
+++ /dev/null
@@ -1,424 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- *
- * A cc.SpriteFrame has:
- * - texture: A cc.Texture2D that will be used by the cc.Sprite
- * - rectangle: A rectangle of the texture
- *
- * You can modify the frame of a cc.Sprite by doing:
- *
- * @class
- * @extends cc.Class
- *
- * @example
- * var texture = cc.TextureCache.getInstance().addImage(s_dragon_animation);
- * var frame0 = cc.SpriteFrame.createWithTexture(texture, cc.rect(132 * 0, 132 * 0, 132, 132));
- */
-cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{
- _offset:null,
- _originalSize:null,
- _rectInPixels:null,
- _rotated:false,
- _rect:null,
- _offsetInPixels:null,
- _originalSizeInPixels:null,
- _texture:null,
- _textureFilename:"",
- _textureLoaded:false,
- _eventListeners:null,
-
- ctor:function () {
- this._offset = cc.p(0, 0);
- this._offsetInPixels = cc.p(0, 0);
- this._originalSize = cc.size(0, 0);
- this._rectInPixels = cc.rect(0, 0, 0, 0);
- this._rotated = false;
- this._rect = cc.rect(0, 0, 0, 0);
- this._originalSizeInPixels = cc.size(0, 0);
- this._textureFilename = "";
- this._texture = null;
- this._textureLoaded = false;
- this._eventListeners = [];
- },
-
- // attributes
- textureLoaded:function(){
- return this._textureLoaded;
- },
-
- addLoadedEventListener:function(callback, target){
- this._eventListeners.push({eventCallback:callback, eventTarget:target});
- },
-
- _callLoadedEventCallbacks:function(){
- var locListeners = this._eventListeners;
- for(var i = 0, len = locListeners.length; i < len; i++){
- var selCallback = locListeners[i];
- selCallback.eventCallback.call(selCallback.eventTarget, this);
- }
- locListeners.length = 0;
- },
-
- /**
- * @return {cc.Rect}
- */
- getRectInPixels:function () {
- var locRectInPixels = this._rectInPixels;
- return cc.rect(locRectInPixels.x, locRectInPixels.y, locRectInPixels.width, locRectInPixels.height);
- },
-
- /**
- * @param {cc.Rect} rectInPixels
- */
- setRectInPixels:function (rectInPixels) {
- this._rectInPixels.x = rectInPixels.x;
- this._rectInPixels.y = rectInPixels.y;
- this._rectInPixels.width = rectInPixels.width;
- this._rectInPixels.height = rectInPixels.height;
- this._rect = cc.RECT_PIXELS_TO_POINTS(rectInPixels);
- },
-
- /**
- *
- * return is rotated of SpriteFrame.
- *
- * @return {Boolean}
- */
- isRotated:function () {
- return this._rotated;
- },
-
- /**
- * set SpriteFrame is rotated
- * @param {Boolean} bRotated
- */
- setRotated:function (bRotated) {
- this._rotated = bRotated;
- },
-
- /**
- * get rect of the frame
- * @return {cc.Rect}
- */
- getRect:function () {
- var locRect = this._rect;
- return cc.rect(locRect.x, locRect.y, locRect.width, locRect.height);
- },
-
- /**
- * set rect of the frame
- * @param {cc.Rect} rect
- */
- setRect:function (rect) {
- this._rect.x = rect.x;
- this._rect.y = rect.y;
- this._rect.width = rect.width;
- this._rect.height = rect.height;
- this._rectInPixels = cc.RECT_POINTS_TO_PIXELS(this._rect);
- },
-
- /**
- * get offset of the frame
- * @return {cc.Point}
- */
- getOffsetInPixels:function () {
- return cc.p(this._offsetInPixels.x, this._offsetInPixels.y);
- },
-
- /**
- * set offset of the frame
- * @param {cc.Point} offsetInPixels
- */
- setOffsetInPixels:function (offsetInPixels) {
- this._offsetInPixels.x = offsetInPixels.x;
- this._offsetInPixels.y = offsetInPixels.y;
- this._offset = cc.POINT_PIXELS_TO_POINTS(this._offsetInPixels);
- },
-
- /**
- * get original size of the trimmed image
- * @const
- * @return {cc.Size}
- */
- getOriginalSizeInPixels:function () {
- return cc.size(this._originalSizeInPixels.width, this._originalSizeInPixels.height);
- },
-
- /**
- * set original size of the trimmed image
- * @param {cc.Size} sizeInPixels
- */
- setOriginalSizeInPixels:function (sizeInPixels) {
- this._originalSizeInPixels.width = sizeInPixels.width;
- this._originalSizeInPixels.height = sizeInPixels.height;
- },
-
- /**
- * get original size of the trimmed image
- * @const
- * @return {cc.Size}
- */
- getOriginalSize:function () {
- return cc.size(this._originalSize.width, this._originalSize.height);
- },
-
- /**
- * set original size of the trimmed image
- * @param {cc.Size} sizeInPixels
- */
- setOriginalSize:function (sizeInPixels) {
- this._originalSize.width = sizeInPixels.width;
- this._originalSize.height = sizeInPixels.height;
- },
-
- /**
- * get texture of the frame
- * @return {cc.Texture2D}
- */
- getTexture:function () {
- if (this._texture)
- return this._texture;
- if (this._textureFilename !== "") {
- var locTexture = cc.TextureCache.getInstance().addImage(this._textureFilename);
- if (locTexture)
- this._textureLoaded = locTexture.isLoaded();
- return locTexture;
- }
- return null;
- },
-
- /**
- * set texture of the frame, the texture is retained
- * @param {cc.Texture2D} texture
- */
- setTexture:function (texture) {
- if (this._texture != texture) {
- var locLoaded = texture.isLoaded();
- this._textureLoaded = locLoaded;
- this._texture = texture;
- if(!locLoaded){
- texture.addLoadedEventListener(function(sender){
- this._textureLoaded = true;
- if(this._rotated){
- var tempElement = sender.getHtmlElementObj();
- tempElement = cc.cutRotateImageToCanvas(tempElement, this.getRect());
- var tempTexture = new cc.Texture2D();
- tempTexture.initWithElement(tempElement);
- tempTexture.handleLoadedTexture();
- this.setTexture(tempTexture);
-
- var rect = this.getRect();
- this.setRect(cc.rect(0, 0, rect.width, rect.height));
- }
- var locRect = this._rect;
- if(locRect.width === 0 && locRect.height === 0){
- var locContentSize = sender.getContentSize();
- this._rect.width = locContentSize.width;
- this._rect.height = locContentSize.height;
- this._rectInPixels = cc.RECT_POINTS_TO_PIXELS(this._rect);
- this._originalSizeInPixels.width = this._rectInPixels.width;
- this._originalSizeInPixels.height = this._rectInPixels.height;
- this._originalSize.width = locContentSize.width;
- this._originalSize.height = locContentSize.height;
- }
- this._callLoadedEventCallbacks();
- }, this);
- }
- }
- },
-
- /**
- * Offset getter
- * @const
- * @return {cc.Point}
- */
- getOffset:function () {
- return cc.p(this._offset.x, this._offset.y);
- },
-
- /**
- * offset setter
- * @param {cc.Point} offsets
- */
- setOffset:function (offsets) {
- this._offset.x = offsets.x;
- this._offset.y = offsets.y;
- },
-
- clone: function(){
- var frame = new cc.SpriteFrame();
- frame.initWithTextureFilename(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels);
- frame.setTexture(this._texture);
- return frame;
- },
-
- /**
- * copy a new SpriteFrame
- * @return {cc.SpriteFrame}
- */
- copyWithZone:function () {
- var copy = new cc.SpriteFrame();
- copy.initWithTextureFilename(this._textureFilename, this._rectInPixels, this._rotated, this._offsetInPixels, this._originalSizeInPixels);
- copy.setTexture(this._texture);
- return copy;
- },
-
- copy:function () {
- return this.copyWithZone();
- },
-
- /**
- * Initializes SpriteFrame with Texture, rect, rotated, offset and originalSize in pixels.
- * @param {cc.Texture2D} texture
- * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels
- * @param {Boolean} [rotated=false]
- * @param {cc.Point} [offset=cc.size(0,0)]
- * @param {cc.Size} [originalSize=rect.size]
- * @return {Boolean}
- */
- initWithTexture:function (texture, rect, rotated, offset, originalSize) {
- if(arguments.length === 2)
- rect = cc.RECT_POINTS_TO_PIXELS(rect);
-
- offset = offset || cc.size(0, 0);
- originalSize = originalSize || rect.size;
-
- this.setTexture(texture);
- this._rectInPixels = rect;
- this._rect = cc.RECT_PIXELS_TO_POINTS(rect);
- this._offsetInPixels = offset;
- this._offset = cc.POINT_PIXELS_TO_POINTS(offset);
- this._originalSizeInPixels = originalSize;
- this._originalSize = cc.SIZE_PIXELS_TO_POINTS(originalSize);
- this._rotated = rotated || false;
- return true;
- },
-
- /**
- *
- * Initializes a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
- * The originalSize is the size in pixels of the frame before being trimmed.
- *
- * @param {string} filename
- * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels
- * @param {Boolean} rotated
- * @param {cc.Point} [offset=cc.size(0,0)]
- * @param {cc.Size} [originalSize=rect.size]
- */
- initWithTextureFilename:function (filename, rect, rotated, offset, originalSize) {
- if(arguments.length === 2)
- rect = cc.RECT_POINTS_TO_PIXELS(rect);
-
- offset = offset || cc.size(0, 0);
- originalSize = originalSize || rect.size;
-
- this._texture = null;
- this._textureFilename = filename;
- this._rectInPixels = rect;
- this._rect = cc.RECT_PIXELS_TO_POINTS(rect);
- this._rotated = rotated || false;
- this._offsetInPixels = offset;
- this._offset = cc.POINT_PIXELS_TO_POINTS(offset);
- this._originalSizeInPixels = originalSize;
- this._originalSize = cc.SIZE_PIXELS_TO_POINTS(originalSize);
-
- return true;
- }
-});
-
-/**
- *
- * Create a cc.SpriteFrame with a texture filename, rect, rotated, offset and originalSize in pixels.
- * The originalSize is the size in pixels of the frame before being trimmed.
- *
- * @param {string} filename
- * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels
- * @param {Boolean} rotated
- * @param {cc.Point} offset
- * @param {cc.Size} originalSize
- * @return {cc.SpriteFrame}
- */
-cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) {
- var spriteFrame = new cc.SpriteFrame();
- switch (arguments.length) {
- case 2:
- spriteFrame.initWithTextureFilename(filename, rect);
- break;
- case 5:
- spriteFrame.initWithTextureFilename(filename, rect, rotated, offset, originalSize);
- break;
- default:
- throw "Argument must be non-nil ";
- break;
- }
- return spriteFrame;
-};
-
-/**
- * Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
- * @param {cc.Texture2D} texture
- * @param {cc.Rect} rect if parameters' length equal 2, rect in points, else rect in pixels
- * @param {Boolean} [rotated=]
- * @param {cc.Point} [offset=]
- * @param {cc.Size} [originalSize=]
- * @return {cc.SpriteFrame}
- * @example
- * //Create a cc.SpriteFrame with a texture, rect in texture.
- * var frame1 = cc.SpriteFrame.createWithTexture("grossini_dance.png",cc.rect(0,0,90,128));
- *
- * //Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels.
- * var frame2 = cc.SpriteFrame.createWithTexture(texture, frameRect, rotated, offset, sourceSize);
- */
-cc.SpriteFrame.createWithTexture = function (texture, rect, rotated, offset, originalSize) {
- var spriteFrame = new cc.SpriteFrame();
- switch (arguments.length) {
- case 2:
- spriteFrame.initWithTexture(texture, rect);
- break;
- case 5:
- spriteFrame.initWithTexture(texture, rect, rotated, offset, originalSize);
- break;
- default:
- throw "Argument must be non-nil ";
- break;
- }
- return spriteFrame;
-};
-
-cc.SpriteFrame._frameWithTextureForCanvas = function (texture, rect, rotated, offset, originalSize) {
- var spriteFrame = new cc.SpriteFrame();
- spriteFrame._texture = texture;
- spriteFrame._rectInPixels = rect;
- spriteFrame._rect = cc.RECT_PIXELS_TO_POINTS(rect);
- spriteFrame._offsetInPixels = offset;
- spriteFrame._offset = cc.POINT_PIXELS_TO_POINTS(spriteFrame._offsetInPixels);
- spriteFrame._originalSizeInPixels = originalSize;
- spriteFrame._originalSize = cc.SIZE_PIXELS_TO_POINTS(spriteFrame._originalSizeInPixels);
- spriteFrame._rotated = rotated;
- return spriteFrame;
-};
diff --git a/cocos2d/sprite_nodes/CCSpriteFrameCache.js b/cocos2d/sprite_nodes/CCSpriteFrameCache.js
deleted file mode 100644
index cf8f4fad58..0000000000
--- a/cocos2d/sprite_nodes/CCSpriteFrameCache.js
+++ /dev/null
@@ -1,425 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Singleton that handles the loading of the sprite frames. It saves in a cache the sprite frames.
- * @class
- * @extends cc.Class
- * @example
- * // add SpriteFrames to SpriteFrameCache With File
- * cc.SpriteFrameCache.getInstance().addSpriteFrames(s_grossiniPlist);
- */
-cc.SpriteFrameCache = cc.Class.extend(/** @lends cc.SpriteFrameCache# */{
- _spriteFrames:null,
- _spriteFramesAliases:null,
- _loadedFileNames:null,
-
- /**
- * Constructor
- */
- ctor:function () {
- this._spriteFrames = {};
- this._spriteFramesAliases = {};
- this._loadedFileNames = [];
- },
-
- /**
- * Adds multiple Sprite Frames with a dictionary. The texture will be associated with the created sprite frames.
- * @param {object} dictionary
- * @param {HTMLImageElement|cc.Texture2D} texture
- */
- _addSpriteFramesWithDictionary:function (dictionary, texture) {
- var metadataDict = dictionary["metadata"];
- var framesDict = dictionary["frames"];
- var format = 0;
- // get the format
- if (metadataDict != null) {
- format = parseInt(this._valueForKey("format", metadataDict));
- }
-
- // check the format
- cc.Assert(format >= 0 && format <= 3, "format is not supported for cc.SpriteFrameCache addSpriteFramesWithDictionary:textureFilename:");
-
- for (var key in framesDict) {
- var frameDict = framesDict[key];
- if (frameDict) {
- var spriteFrame = this._spriteFrames[key];
- if (spriteFrame) {
- continue;
- }
-
- if (format == 0) {
- var x = parseFloat(this._valueForKey("x", frameDict));
- var y = parseFloat(this._valueForKey("y", frameDict));
- var w = parseFloat(this._valueForKey("width", frameDict));
- var h = parseFloat(this._valueForKey("height", frameDict));
- var ox = parseFloat(this._valueForKey("offsetX", frameDict));
- var oy = parseFloat(this._valueForKey("offsetY", frameDict));
- var ow = parseInt(this._valueForKey("originalWidth", frameDict));
- var oh = parseInt(this._valueForKey("originalHeight", frameDict));
- // check ow/oh
- if (!ow || !oh) {
- cc.log("cocos2d: WARNING: originalWidth/Height not found on the cc.SpriteFrame. AnchorPoint won't work as expected. Regenrate the .plist");
- }
- // Math.abs ow/oh
- ow = Math.abs(ow);
- oh = Math.abs(oh);
- // create frame
- spriteFrame = new cc.SpriteFrame();
- spriteFrame.initWithTexture(texture, cc.rect(x, y, w, h), false, cc.p(ox, oy), cc.size(ow, oh));
- } else if (format == 1 || format == 2) {
- var frame = cc.RectFromString(this._valueForKey("frame", frameDict));
- var rotated = false;
-
- // rotation
- if (format == 2) {
- rotated = this._valueForKey("rotated", frameDict) == "true";
- }
- var offset = cc.PointFromString(this._valueForKey("offset", frameDict));
- var sourceSize = cc.SizeFromString(this._valueForKey("sourceSize", frameDict));
- // create frame
- spriteFrame = new cc.SpriteFrame();
- spriteFrame.initWithTexture(texture, frame, rotated, offset, sourceSize);
- } else if (format == 3) {
- // get values
- var spriteSize, spriteOffset, spriteSourceSize, textureRect, textureRotated;
- spriteSize = cc.SizeFromString(this._valueForKey("spriteSize", frameDict));
- spriteOffset = cc.PointFromString(this._valueForKey("spriteOffset", frameDict));
- spriteSourceSize = cc.SizeFromString(this._valueForKey("spriteSourceSize", frameDict));
- textureRect = cc.RectFromString(this._valueForKey("textureRect", frameDict));
- textureRotated = this._valueForKey("textureRotated", frameDict) == "true";
-
- // get aliases
- var aliases = frameDict["aliases"];
- var frameKey = key.toString();
-
- for (var aliasKey in aliases) {
- if (this._spriteFramesAliases.hasOwnProperty(aliases[aliasKey])) {
- cc.log("cocos2d: WARNING: an alias with name " + aliasKey + " already exists");
- }
- this._spriteFramesAliases[aliases[aliasKey]] = frameKey;
- }
-
- // create frame
- spriteFrame = new cc.SpriteFrame();
- if (frameDict.hasOwnProperty("spriteSize")) {
- spriteFrame.initWithTexture(texture,
- cc.rect(textureRect.x, textureRect.y, spriteSize.width, spriteSize.height),
- textureRotated,
- spriteOffset,
- spriteSourceSize);
- } else {
- spriteFrame.initWithTexture(texture, spriteSize, textureRotated, spriteOffset, spriteSourceSize);
- }
- }
-
- if(cc.renderContextType === cc.CANVAS && spriteFrame.isRotated()){
- //clip to canvas
- var locTexture = spriteFrame.getTexture();
- if(locTexture.isLoaded()){
- var tempElement = spriteFrame.getTexture().getHtmlElementObj();
- tempElement = cc.cutRotateImageToCanvas(tempElement, spriteFrame.getRectInPixels());
- var tempTexture = new cc.Texture2D();
- tempTexture.initWithElement(tempElement);
- tempTexture.handleLoadedTexture();
- spriteFrame.setTexture(tempTexture);
-
- var rect = spriteFrame._rect;
- spriteFrame.setRect(cc.rect(0, 0, rect.width, rect.height));
- }
- }
-
- // add sprite frame
- this._spriteFrames[key] = spriteFrame;
- }
- }
- },
-
- /**
- * Adds multiple Sprite Frames from a json file. A texture will be loaded automatically.
- * @param {object} jsonData
- * @deprecated
- */
- addSpriteFramesWithJson:function (jsonData) {
- cc.log("addSpriteFramesWithJson is deprecated, because Json format doesn't support on JSB. Use XML format instead");
- var dict = jsonData;
- var texturePath = "";
-
- var metadataDict = dict["metadata"];
- if (metadataDict) {
- // try to read texture file name from meta data
- texturePath = this._valueForKey("textureFileName", metadataDict);
- texturePath = texturePath.toString();
- }
-
- var texture = cc.TextureCache.getInstance().addImage(texturePath);
- if (texture) {
- this._addSpriteFramesWithDictionary(dict, texture);
- }
- else {
- cc.log("cocos2d: cc.SpriteFrameCache: Couldn't load texture");
- }
- },
-
- /**
- *
- * Adds multiple Sprite Frames from a plist file.
- * A texture will be loaded automatically. The texture name will composed by replacing the .plist suffix with .png
- * If you want to use another texture, you should use the addSpriteFrames:texture method.
- *
- * @param {String} plist plist filename
- * @param {HTMLImageElement|cc.Texture2D} texture
- * @example
- * // add SpriteFrames to SpriteFrameCache With File
- * cc.SpriteFrameCache.getInstance().addSpriteFrames(s_grossiniPlist);
- */
- addSpriteFrames:function (plist, texture) {
- var fileUtils = cc.FileUtils.getInstance();
- var fullPath = fileUtils.fullPathForFilename(plist);
- var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(fullPath);
-
- switch (arguments.length) {
- case 1:
- cc.Assert(plist, "plist filename should not be NULL");
- if (!cc.ArrayContainsObject(this._loadedFileNames, plist)) {
- var texturePath = "";
- var metadataDict = dict["metadata"];
- if (metadataDict) {
- // try to read texture file name from meta data
- texturePath = this._valueForKey("textureFileName", metadataDict).toString();
- }
- if (texturePath != "") {
- // build texture path relative to plist file
- texturePath = fileUtils.fullPathFromRelativeFile(texturePath, plist);
- } else {
- // build texture path by replacing file extension
- texturePath = plist;
-
- // remove .xxx
- var startPos = texturePath.lastIndexOf(".", texturePath.length);
- texturePath = texturePath.substr(0, startPos);
-
- // append .png
- texturePath = texturePath + ".png";
- }
-
- var getTexture = cc.TextureCache.getInstance().addImage(texturePath);
- if (getTexture) {
- this._addSpriteFramesWithDictionary(dict, getTexture);
- } else {
- cc.log("cocos2d: cc.SpriteFrameCache: Couldn't load texture");
- }
- }
- break;
- case 2:
- //if ((texture instanceof cc.Texture2D) || (texture instanceof HTMLImageElement) || (texture instanceof HTMLCanvasElement)) {
- if (texture instanceof cc.Texture2D) {
- /** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames. */
- this._addSpriteFramesWithDictionary(dict, texture);
- } else {
- /** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames.
- @since v0.99.5
- */
- var textureFileName = texture;
- cc.Assert(textureFileName, "texture name should not be null");
- var gTexture = cc.TextureCache.getInstance().addImage(textureFileName);
-
- if (gTexture) {
- this._addSpriteFramesWithDictionary(dict, gTexture);
- } else {
- cc.log("cocos2d: cc.SpriteFrameCache: couldn't load texture file. File not found " + textureFileName);
- }
- }
- break;
- default:
- throw "Argument must be non-nil ";
- }
- },
-
- /**
- *
- * Adds an sprite frame with a given name.
- * If the name already exists, then the contents of the old name will be replaced with the new one.
- *
- * @param {cc.SpriteFrame} frame
- * @param {String} frameName
- */
- addSpriteFrame:function (frame, frameName) {
- this._spriteFrames[frameName] = frame;
- },
-
- /**
- *
- * Purges the dictionary of loaded sprite frames.
- * Call this method if you receive the "Memory Warning".
- * In the short term: it will free some resources preventing your app from being killed.
- * In the medium term: it will allocate more resources.
- * In the long term: it will be the same.
- *
- */
- removeSpriteFrames:function () {
- this._spriteFrames = [];
- this._spriteFramesAliases = [];
- this._loadedFileNames = {};
- },
-
- /**
- * Deletes an sprite frame from the sprite frame cache.
- * @param {String} name
- */
- removeSpriteFrameByName:function (name) {
- // explicit nil handling
- if (!name) {
- return;
- }
-
- // Is this an alias ?
- if (this._spriteFramesAliases.hasOwnProperty(name)) {
- delete(this._spriteFramesAliases[name]);
- }
- if (this._spriteFrames.hasOwnProperty(name)) {
- delete(this._spriteFrames[name]);
- }
- // XXX. Since we don't know the .plist file that originated the frame, we must remove all .plist from the cache
- this._loadedFileNames = {};
- },
-
- /**
- *
- * Removes multiple Sprite Frames from a plist file.
- * Sprite Frames stored in this file will be removed.
- * It is convinient to call this method when a specific texture needs to be removed.
- *
- * @param {String} plist plist filename
- */
- removeSpriteFramesFromFile:function (plist) {
- var fileUtils = cc.FileUtils.getInstance();
- var path = fileUtils.fullPathForFilename(plist);
- var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(path);
-
- this._removeSpriteFramesFromDictionary(dict);
-
- //remove it from the cache
- if (cc.ArrayContainsObject(this._loadedFileNames, plist)) {
- cc.ArrayRemoveObject(plist);
- }
- },
-
- /**
- * Removes multiple Sprite Frames from Dictionary.
- * @param {object} dictionary SpriteFrame of Dictionary
- */
- _removeSpriteFramesFromDictionary:function (dictionary) {
- var framesDict = dictionary["frames"];
-
- for (var key in framesDict) {
- if (this._spriteFrames.hasOwnProperty(key)) {
- delete(this._spriteFrames[key]);
- }
- }
- },
-
- /**
- *
- * Removes all Sprite Frames associated with the specified textures.
- * It is convinient to call this method when a specific texture needs to be removed.
- *
- * @param {HTMLImageElement|HTMLCanvasElement|cc.Texture2D} texture
- */
- removeSpriteFramesFromTexture:function (texture) {
- for (var key in this._spriteFrames) {
- var frame = this._spriteFrames[key];
- if (frame && (frame.getTexture() == texture)) {
- delete(this._spriteFrames[key]);
- }
- }
- },
-
- /**
- *
- * Returns an Sprite Frame that was previously added.
- * If the name is not found it will return nil.
- * You should retain the returned copy if you are going to use it.
- *
- * @param {String} name name of SpriteFrame
- * @return {cc.SpriteFrame}
- * @example
- * //get a SpriteFrame by name
- * var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png");
- */
- getSpriteFrame:function (name) {
- var frame;
- if (this._spriteFrames.hasOwnProperty(name)) {
- frame = this._spriteFrames[name];
- }
-
- if (!frame) {
- // try alias dictionary
- var key;
- if (this._spriteFramesAliases.hasOwnProperty(name)) {
- key = this._spriteFramesAliases[name];
- }
- if (key) {
- if (this._spriteFrames.hasOwnProperty(key.toString())) {
- frame = this._spriteFrames[key.toString()];
- }
- if (!frame) {
- cc.log("cocos2d: cc.SpriteFrameCahce: Frame " + name + " not found");
- }
- }
- }
- return frame;
- },
-
- _valueForKey:function (key, dict) {
- if (dict) {
- if (dict.hasOwnProperty(key)) {
- return dict[key].toString();
- }
- }
- return "";
- }
-});
-
-cc.s_sharedSpriteFrameCache = null;
-
-/**
- * Returns the shared instance of the Sprite Frame cache
- * @return {cc.SpriteFrameCache}
- */
-cc.SpriteFrameCache.getInstance = function () {
- if (!cc.s_sharedSpriteFrameCache) {
- cc.s_sharedSpriteFrameCache = new cc.SpriteFrameCache();
- }
- return cc.s_sharedSpriteFrameCache;
-};
-
-/**
- * Purges the cache. It releases all the Sprite Frames and the retained instance.
- */
-cc.SpriteFrameCache.purgeSharedSpriteFrameCache = function () {
- cc.s_sharedSpriteFrameCache = null;
-};
diff --git a/cocos2d/support/CCNotificationCenter.js b/cocos2d/support/CCNotificationCenter.js
deleted file mode 100644
index 60188057bf..0000000000
--- a/cocos2d/support/CCNotificationCenter.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.s_sharedNotificationCenter = null;
-
-cc.NotificationCenter = cc.Class.extend({
- ctor:function() {
- this._observers = [];
- },
-
- /**
- * @param {cc.Class} target
- * @param {String} selector
- * @param {String} name
- * @param {cc.Class} obj
- */
- addObserver:function(target, selector, name, obj) {
- if (this._observerExisted(target, name))
- return;
-
- var observer = new cc.NotificationObserver(target, selector, name, obj);
- if (!observer)
- return;
-
- this._observers.push(observer);
- },
-
- /**
- * Removes the observer by the specified target and name.
- * @param {cc.Class} target
- * @param {String} name
- */
- removeObserver:function(target, name) {
- for (var i = 0; i < this._observers.length; i++) {
- var observer = this._observers[i];
- if (!observer)
- continue;
- if (observer.getName() == name && observer.getTarget() == target) {
- this._observers.splice(i, 1);
- return;
- }
- }
- },
-
- /**
- * Removes all notifications registered by this target
- * @param {cc.Class} target The target of this notification.
- * @returns {number} the number of observers removed
- */
- removeAllObservers:function(target){
- var removes = [];
- for(var i = 0; i< this._observers.length;i++){
- var selObserver = this._observers[i];
- if(selObserver.getTarget() == target)
- removes.push(selObserver);
- }
- cc.ArrayRemoveArray(this._observers, removes);
- return removes.length;
- },
-
- /**
- * @param {String} name
- * @param {cc.Class} object
- */
- postNotification:function(name, object) {
- for (var i = 0; i < this._observers.length; i++) {
- var observer = this._observers[i];
- if (!observer)
- continue;
- if (observer.getName() == name)
- observer.performSelector(object);
- }
- },
-
- /**
- * @param {cc.Class} target
- * @param {String} name
- * @return {Boolean}
- * @private
- */
- _observerExisted:function(target, name) {
- for (var i = 0; i < this._observers.length; i++)
- {
- var observer = this._observers[i];
- if (!observer)
- continue;
- if (observer.getName() == name && observer.getTarget() == target)
- return true;
- }
- return false;
- },
- _observers:null
-});
-
-/**
- * @return {cc.NotificationCenter}
- */
-cc.NotificationCenter.getInstance = function() {
- if (!cc.s_sharedNotificationCenter) {
- cc.s_sharedNotificationCenter = new cc.NotificationCenter();
- }
- return cc.s_sharedNotificationCenter;
-};
-
-cc.NotificationObserver = cc.Class.extend({
- /**
- * @param {cc.Class} target
- * @param {String} selector
- * @param {String} name
- * @param {cc.Class} obj
- */
- ctor:function (target, selector, name, obj) {
- this._target = target;
- this._selector = selector;
- this._name = name;
- this._object = obj;
- },
-
- /**
- * @param {cc.Class} obj
- */
- performSelector:function (obj) {
- if (this._target && (typeof(this._selector) == "string")) {
- this._target[this._selector](obj);
- } else if (this._target && (typeof(this._selector) == "function")) {
- this._selector.call(this._target, obj);
- } else {
- this._selector(obj);
- }
- },
-
- _target:null,
- _selector:null,
- _name:null,
- _object:null,
-
- /**
- * @return {cc.Class}
- */
- getTarget:function () {
- return this._target;
- },
-
- /**
- * @return {String}
- */
- getSelector:function () {
- return this._selector;
- },
-
- /**
- * @return {String}
- */
- getName:function () {
- return this._name;
- },
-
- /**
- * @return {cc.Class}
- */
- getObject:function () {
- return this._object;
- }
-});
\ No newline at end of file
diff --git a/cocos2d/support/CCUserDefault.js b/cocos2d/support/CCUserDefault.js
deleted file mode 100644
index fd53f8c3d0..0000000000
--- a/cocos2d/support/CCUserDefault.js
+++ /dev/null
@@ -1,277 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * cc.UserDefault acts as a tiny localStorage. You can save and get base type values by it.
- * For example, setBoolForKey("played", true) will add a bool value true into the localStorage.
- * Its key is "played". You can get the value of the key by getBoolForKey("played").
- *
- * It supports the following base types:
- * bool, int, float, double, string
- *
- * @class
- * @extends cc.Class
- */
-
-cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{
- _db:null,
- /*
- * init user default
- * */
- init:function () {
- this._db = this._getLocalStorage();
- return true;
- },
-
- _getLocalStorage:function () {
- try {
- if (!!sys.localStorage) {
- return sys.localStorage;
- }
- } catch (e) {
- return undefined;
- }
- },
-
- _getWebSqlDatabase:function () {
-
- },
-
- /**
- * Get bool value by key, if the key doesn't exist, a default value will return.
- * You can set the default value, or it is false.
- *
- * @param {String} key
- * @param {Boolean} defaultValue
- * @return {Boolean}
- */
- getBoolForKey:function (key, defaultValue) {
- cc.log("getBoolForKey is deprecated. Use sys.localStorage.getItem instead.");
- var value = this._getValueForKey(key);
- var ret = defaultValue || false;
- if (value == "true") {
- return true;
- }
- else if (value == "false") {
- return false;
- }
- else if (value) {
- return Boolean(value);
- }
-
- return ret;
- },
-
- /**
- * Get integer value by key, if the key doesn't exist, a default value will return.
- * You can set the default value, or it is 0.
- *
- * @param {String} key
- * @param {Number} defaultValue
- * @return {Number}
- */
- getIntegerForKey:function (key, defaultValue) {
- cc.log("getIntegerForKey is deprecated. Use sys.localStorage.getItem instead.");
- var value = this._getValueForKey(key);
- var ret = defaultValue || 0;
-
- if (value) {
- return parseInt(value);
- }
-
- return ret;
- },
-
- /**
- * Get float value by key, if the key doesn't exist, a default value will return.
- * You can set the default value, or it is 0.0f.
- *
- * @param {String} key
- * @param {Number} defaultValue
- * @return {Number}
- */
- getFloatForKey:function (key, defaultValue) {
- cc.log("getFloatForKey is deprecated. Use sys.localStorage.getItem instead.");
- var value = this._getValueForKey(key);
- var ret = defaultValue || 0;
-
- if (value) {
- return parseFloat(value);
- }
-
- return ret;
- },
-
- /**
- * Get double value by key, if the key doesn't exist, a default value will return.
- * You can set the default value, or it is 0.0.
- *
- * @param {String} key
- * @param {Number} defaultValue
- * @return {Number}
- */
- getDoubleForKey:function (key, defaultValue) {
- cc.log("getDoubleForKey is deprecated. Use sys.localStorage.getItem instead.");
- return this.getFloatForKey(key, defaultValue);
- },
-
- /**
- * Get string value by key, if the key doesn't exist, a default value will return.
- * You can set the default value, or it is "".
- *
- * @param {String} key
- * @param {String} defaultValue
- * @return {String}
- */
- getStringForKey:function (key, defaultValue) {
- cc.log("getStringForKey is deprecated. Use sys.localStorage.getItem instead.");
- var value = this._getValueForKey(key);
- var ret = defaultValue || "";
-
- if (value) {
- return String(value);
- }
-
- return ret;
- },
-
- _getValueForKey:function (key) {
- var ret;
- if (this._db) {
- ret = this._db.getItem(key);
- }
-
- return ret;
- },
-
- /**
- * Set bool value by key.
- *
- * @param {String} key
- * @param {Boolean} value
- */
- setBoolForKey:function (key, value) {
- cc.log("setBoolForKey is deprecated. Use sys.localStorage.setItem instead.");
- // save bool value as sring
- this.setStringForKey(key, String(value));
- },
-
- /**
- * Set integer value by key.
- *
- * @param {String} key
- * @param {Number} value
- */
- setIntegerForKey:function (key, value) {
- cc.log("setIntegerForKey is deprecated. Use sys.localStorage.setItem instead.");
- // check key
- if (!key) {
- return;
- }
-
- this._setValueForKey(key, parseInt(value));
- },
-
- /**
- * Set float value by key.
- *
- * @param {String} key
- * @param {Number} value
- */
- setFloatForKey:function (key, value) {
- cc.log("setFloatForKey is deprecated. Use sys.localStorage.setItem instead.");
- // check key
- if (!key) {
- return;
- }
-
- this._setValueForKey(key, parseFloat(value));
- },
-
- /**
- * Set double value by key.
- *
- * @param {String} key
- * @param {Number} value
- */
- setDoubleForKey:function (key, value) {
- cc.log("setDoubleForKey is deprecated. Use sys.localStorage.setItem instead.");
- return this.setFloatForKey(key, value);
- },
-
- /**
- * Set string value by key.
- *
- * @param {String} key
- * @param {String} value
- */
- setStringForKey:function (key, value) {
- cc.log("setStringForKey is deprecated. Use sys.localStorage.setItem instead.");
- // check key
- if (!key) {
- return;
- }
-
- this._setValueForKey(key, String(value));
- },
-
- _setValueForKey:function (key, value) {
- if (this._db) {
- this._db.setItem(key, value);
- }
- }
-});
-
-/**
- * returns a shared instance of the UserDefault
- * @function
- * @return {cc.UserDefault|}
- */
-cc.UserDefault.getInstance = function () {
- cc.log("cc.UserDefault is deprecated. Use sys.localStorage instead.");
- if (!this._sUserDefault) {
- this._sUserDefault = new cc.UserDefault();
- this._sUserDefault.init();
- }
-
- return this._sUserDefault;
-};
-
-/**
- * purge a shared instance of the UserDefault
- * @function
- * @return {cc.UserDefault|}
- */
-cc.UserDefault.purgeInstanceUserDefault = function () {
- if (cc.hasOwnProperty("Browser")) { //TODO: clear() is not implemented in JSB
- if (this._db) {
- this._db.clear();
- }
- }
-};
-
-cc.UserDefault._sUserDefault = null;
-cc.UserDefault._isFilePathInitialized = false;
\ No newline at end of file
diff --git a/cocos2d/text_input_node/CCIMEDispatcher.js b/cocos2d/text-input/CCIMEDispatcher.js
similarity index 72%
rename from cocos2d/text_input_node/CCIMEDispatcher.js
rename to cocos2d/text-input/CCIMEDispatcher.js
index 78543694bd..e22f6da1f1 100644
--- a/cocos2d/text_input_node/CCIMEDispatcher.js
+++ b/cocos2d/text-input/CCIMEDispatcher.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -31,8 +31,8 @@
* @param {Number} duration the soft keyboard animation duration
*/
cc.IMEKeyboardNotificationInfo = function (begin, end, duration) {
- this.begin = begin || cc.RectZero();
- this.end = end || cc.RectZero();
+ this.begin = begin || cc.rect(0, 0, 0, 0);
+ this.end = end || cc.rect(0, 0, 0, 0);
this.duration = duration || 0;
};
@@ -43,30 +43,30 @@ cc.IMEKeyboardNotificationInfo = function (begin, end, duration) {
*/
cc.IMEDelegate = cc.Class.extend(/** @lends cc.IMEDelegate# */{
/**
- * Constructor
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- ctor:function () {
- cc.IMEDispatcher.getInstance().addDelegate(this);
+ ctor: function () {
+ cc.imeDispatcher.addDelegate(this);
},
/**
* Remove delegate
*/
- removeDelegate:function () {
- cc.IMEDispatcher.getInstance().removeDelegate(this);
+ removeDelegate: function () {
+ cc.imeDispatcher.removeDelegate(this);
},
/**
* Remove delegate
* @return {Boolean}
*/
- attachWithIME:function () {
- return cc.IMEDispatcher.getInstance().attachDelegateWithIME(this);
+ attachWithIME: function () {
+ return cc.imeDispatcher.attachDelegateWithIME(this);
},
/**
* Detach with IME
* @return {Boolean}
*/
- detachWithIME:function () {
- return cc.IMEDispatcher.getInstance().detachDelegateWithIME(this);
+ detachWithIME: function () {
+ return cc.imeDispatcher.detachDelegateWithIME(this);
},
/**
@@ -74,83 +74,83 @@ cc.IMEDelegate = cc.Class.extend(/** @lends cc.IMEDelegate# */{
* Called by CCIMEDispatcher.
* @return {Boolean}
*/
- canAttachWithIME:function () {
+ canAttachWithIME: function () {
return false;
},
/**
* When the delegate detach with IME, this method call by CCIMEDispatcher.
*/
- didAttachWithIME:function () {
+ didAttachWithIME: function () {
},
/**
* Decide the delegate instance can stop receive ime message or not.
* @return {Boolean}
*/
- canDetachWithIME:function () {
+ canDetachWithIME: function () {
return false;
},
/**
* When the delegate detach with IME, this method call by CCIMEDispatcher.
*/
- didDetachWithIME:function () {
+ didDetachWithIME: function () {
},
/**
* Called by CCIMEDispatcher when some text input from IME.
*/
- insertText:function (text, len) {
+ insertText: function (text, len) {
},
/**
* Called by CCIMEDispatcher when user clicked the backward key.
*/
- deleteBackward:function () {
+ deleteBackward: function () {
},
/**
* Called by CCIMEDispatcher for get text which delegate already has.
* @return {String}
*/
- getContentText:function () {
+ getContentText: function () {
return "";
},
//////////////////////////////////////////////////////////////////////////
// keyboard show/hide notification
//////////////////////////////////////////////////////////////////////////
- keyboardWillShow:function (info) {
+ keyboardWillShow: function (info) {
},
- keyboardDidShow:function (info) {
+ keyboardDidShow: function (info) {
},
- keyboardWillHide:function (info) {
+ keyboardWillHide: function (info) {
},
- keyboardDidHide:function (info) {
+ keyboardDidHide: function (info) {
}
});
/**
- * Input Method Edit Message Dispatcher.
+ * cc.imeDispatcher is a singleton object which manage input message dispatching.
* @class
- * @extends cc.Class
+ * @name cc.imeDispatcher
*/
-cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
- _domInputControl:null,
- impl:null,
- _currentInputString:"",
- _lastClickPosition:null,
+cc.IMEDispatcher = cc.Class.extend(/** @lends cc.imeDispatcher# */{
+ _domInputControl: null,
+ impl: null,
+ _currentInputString: "",
+ _lastClickPosition: null,
/**
- * Constructor
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- ctor:function () {
+ ctor: function () {
this.impl = new cc.IMEDispatcher.Impl();
this._lastClickPosition = cc.p(0, 0);
},
- init:function () {
- if (cc.Browser.isMobile)
+ init: function () {
+ if (cc.sys.isMobile)
return;
this._domInputControl = cc.$("#imeDispatcherInput");
if (!this._domInputControl) {
@@ -178,7 +178,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
if (e.keyCode === cc.KEY.tab) {
e.stopPropagation();
e.preventDefault();
- } else if (e.keyCode == cc.KEY.enter) {
+ } else if (e.keyCode === cc.KEY.enter) {
selfPointer.dispatchInsertText("\n", 1);
e.stopPropagation();
e.preventDefault();
@@ -187,7 +187,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
if (/msie/i.test(navigator.userAgent)) {
this._domInputControl.addEventListener("keyup", function (e) {
- if (e.keyCode == cc.KEY.backspace) {
+ if (e.keyCode === cc.KEY.backspace) {
selfPointer._processDomInputString(selfPointer._domInputControl.value);
}
}, false);
@@ -197,11 +197,12 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
var tx = event.pageX || 0;
var ty = event.pageY || 0;
- selfPointer._lastClickPosition = cc.p(tx, ty);
+ selfPointer._lastClickPosition.x = tx;
+ selfPointer._lastClickPosition.y = ty;
}, false);
},
- _processDomInputString:function (text) {
+ _processDomInputString: function (text) {
var i, startPos;
var len = this._currentInputString.length < text.length ? this._currentInputString.length : text.length;
for (startPos = 0; startPos < len; startPos++) {
@@ -224,7 +225,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* @param {String} text
* @param {Number} len
*/
- dispatchInsertText:function (text, len) {
+ dispatchInsertText: function (text, len) {
if (!this.impl || !text || len <= 0)
return;
@@ -238,7 +239,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
/**
* Dispatch the delete backward operation
*/
- dispatchDeleteBackward:function () {
+ dispatchDeleteBackward: function () {
if (!this.impl) {
return;
}
@@ -254,7 +255,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* Get the content text, which current CCIMEDelegate which attached with IME has.
* @return {String}
*/
- getContentText:function () {
+ getContentText: function () {
if (this.impl && this.impl._delegateWithIme) {
var pszContentText = this.impl._delegateWithIme.getContentText();
return (pszContentText) ? pszContentText : "";
@@ -266,7 +267,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* Dispatch keyboard notification
* @param {cc.IMEKeyboardNotificationInfo} info
*/
- dispatchKeyboardWillShow:function (info) {
+ dispatchKeyboardWillShow: function (info) {
if (this.impl) {
for (var i = 0; i < this.impl._delegateList.length; i++) {
var delegate = this.impl._delegateList[i];
@@ -281,7 +282,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* Dispatch keyboard notification
* @param {cc.IMEKeyboardNotificationInfo} info
*/
- dispatchKeyboardDidShow:function (info) {
+ dispatchKeyboardDidShow: function (info) {
if (this.impl) {
for (var i = 0; i < this.impl._delegateList.length; i++) {
var delegate = this.impl._delegateList[i];
@@ -295,7 +296,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* Dispatch keyboard notification
* @param {cc.IMEKeyboardNotificationInfo} info
*/
- dispatchKeyboardWillHide:function (info) {
+ dispatchKeyboardWillHide: function (info) {
if (this.impl) {
for (var i = 0; i < this.impl._delegateList.length; i++) {
var delegate = this.impl._delegateList[i];
@@ -310,7 +311,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* Dispatch keyboard notification
* @param {cc.IMEKeyboardNotificationInfo} info
*/
- dispatchKeyboardDidHide:function (info) {
+ dispatchKeyboardDidHide: function (info) {
if (this.impl) {
for (var i = 0; i < this.impl._delegateList.length; i++) {
var delegate = this.impl._delegateList[i];
@@ -326,9 +327,9 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* @param {cc.IMEDelegate} delegate
* @example
* //example
- * cc.IMEDispatcher.getInstance().addDelegate(this);
+ * cc.imeDispatcher.addDelegate(this);
*/
- addDelegate:function (delegate) {
+ addDelegate: function (delegate) {
if (!delegate || !this.impl)
return;
@@ -336,7 +337,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
// delegate already in list
return;
}
- this.impl._delegateList = cc.ArrayAppendObjectToIndex(this.impl._delegateList, delegate, 0);
+ this.impl._delegateList.splice(0, 0, delegate);
},
/**
@@ -345,14 +346,14 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* @return {Boolean} If the old delegate can detattach with ime and the new delegate can attach with ime, return true, otherwise return false.
* @example
* //example
- * var ret = cc.IMEDispatcher.getInstance().attachDelegateWithIME(this);
+ * var ret = cc.imeDispatcher.attachDelegateWithIME(this);
*/
- attachDelegateWithIME:function (delegate) {
+ attachDelegateWithIME: function (delegate) {
if (!this.impl || !delegate)
return false;
// if delegate is not in delegate list, return
- if (this.impl._delegateList.indexOf(delegate) == -1)
+ if (this.impl._delegateList.indexOf(delegate) === -1)
return false;
if (this.impl._delegateWithIme) {
@@ -380,19 +381,28 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
return true;
},
- _focusDomInput:function (delegate) {
- if(cc.Browser.isMobile){
+ _focusDomInput: function (delegate) {
+ if (cc.sys.isMobile) {
this.impl._delegateWithIme = delegate;
delegate.didAttachWithIME();
//prompt
- this._currentInputString = delegate.getString ? delegate.getString() : "";
- var userInput = prompt("please enter your word:", this._currentInputString);
- if(userInput != null)
+ this._currentInputString = delegate.string || "";
+
+ var tipMessage = delegate.getTipMessage ? delegate.getTipMessage() : "please enter your word:";
+ // wechat cover the prompt function .So need use the Window.prototype.prompt
+ var userInput;
+ var win = window.Window;
+ if (win && win.prototype.prompt && win.prototype.prompt != prompt) {
+ userInput = win.prototype.prompt.call(window, tipMessage, this._currentInputString);
+ } else {
+ userInput = prompt(tipMessage, this._currentInputString);
+ }
+ if (userInput != null)
this._processDomInputString(userInput);
this.dispatchInsertText("\n", 1);
- }else{
+ } else {
this.impl._delegateWithIme = delegate;
- this._currentInputString = delegate.getString ? delegate.getString() : "";
+ this._currentInputString = delegate.string || "";
delegate.didAttachWithIME();
this._domInputControl.focus();
this._domInputControl.value = this._currentInputString;
@@ -400,7 +410,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
}
},
- _domInputControlTranslate:function () {
+ _domInputControlTranslate: function () {
if (/msie/i.test(navigator.userAgent)) {
this._domInputControl.style.left = this._lastClickPosition.x + "px";
this._domInputControl.style.top = this._lastClickPosition.y + "px";
@@ -415,14 +425,14 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* @return {Boolean} If the old delegate can detattach with ime and the new delegate can attach with ime, return true, otherwise return false.
* @example
* //example
- * var ret = cc.IMEDispatcher.getInstance().detachDelegateWithIME(this);
+ * var ret = cc.imeDispatcher.detachDelegateWithIME(this);
*/
- detachDelegateWithIME:function (delegate) {
+ detachDelegateWithIME: function (delegate) {
if (!this.impl || !delegate)
return false;
// if delegate is not the current delegate attached with ime, return
- if (this.impl._delegateWithIme != delegate)
+ if (this.impl._delegateWithIme !== delegate)
return false;
if (!delegate.canDetachWithIME())
@@ -430,7 +440,7 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
this.impl._delegateWithIme = null;
delegate.didDetachWithIME();
- cc.canvas.focus();
+ cc._canvas.focus();
return true;
},
@@ -439,22 +449,22 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* @param {cc.IMEDelegate} delegate
* @example
* //example
- * cc.IMEDispatcher.getInstance().removeDelegate(this);
+ * cc.imeDispatcher.removeDelegate(this);
*/
- removeDelegate:function (delegate) {
+ removeDelegate: function (delegate) {
if (!this.impl || !delegate)
return;
// if delegate is not in delegate list, return
- if (this.impl._delegateList.indexOf(delegate) == -1)
+ if (this.impl._delegateList.indexOf(delegate) === -1)
return;
if (this.impl._delegateWithIme) {
- if (delegate == this.impl._delegateWithIme) {
+ if (delegate === this.impl._delegateWithIme) {
this.impl._delegateWithIme = null;
}
}
- cc.ArrayRemoveObject(this.impl._delegateList, delegate);
+ cc.arrayRemoveObject(this.impl._delegateList, delegate);
},
/**
@@ -463,18 +473,18 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
* @example
* //example
* document.addEventListener("keydown", function (e) {
- * cc.IMEDispatcher.getInstance().processKeycode(e.keyCode);
+ * cc.imeDispatcher.processKeycode(e.keyCode);
* });
*/
- processKeycode:function (keyCode) {
+ processKeycode: function (keyCode) {
if (keyCode < 32) {
- if (keyCode == cc.KEY.backspace) {
+ if (keyCode === cc.KEY.backspace) {
this.dispatchDeleteBackward();
- } else if (keyCode == cc.KEY.enter) {
+ } else if (keyCode === cc.KEY.enter) {
this.dispatchInsertText("\n", 1);
- } else if (keyCode == cc.KEY.tab) {
+ } else if (keyCode === cc.KEY.tab) {
//tab input
- } else if (keyCode == cc.KEY.escape) {
+ } else if (keyCode === cc.KEY.escape) {
//ESC input
}
} else if (keyCode < 255) {
@@ -486,16 +496,19 @@ cc.IMEDispatcher = cc.Class.extend(/** @lends cc.IMEDispatcher# */{
});
/**
+ * Create the cc.IMEDispatcher.Imp Object.
+ * This is the inner class...
* @class
* @extends cc.Class
+ * @name cc.IMEDispatcher.Impl
*/
cc.IMEDispatcher.Impl = cc.Class.extend(/** @lends cc.IMEDispatcher.Impl# */{
- _delegateWithIme:null,
- _delegateList:null,
+ _delegateWithIme: null,
+ _delegateList: null,
/**
- * Constructor
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
*/
- ctor:function () {
+ ctor: function () {
this._delegateList = [];
},
/**
@@ -503,28 +516,20 @@ cc.IMEDispatcher.Impl = cc.Class.extend(/** @lends cc.IMEDispatcher.Impl# */{
* @param {cc.IMEDelegate} delegate
* @return {Number|Null}
*/
- findDelegate:function (delegate) {
+ findDelegate: function (delegate) {
for (var i = 0; i < this._delegateList.length; i++) {
- if (this._delegateList[i] == delegate)
+ if (this._delegateList[i] === delegate)
return i;
}
return null;
}
});
-/**
- * Returns the shared CCIMEDispatcher object for the system.
- * @return {cc.IMEDispatcher}
- */
-cc.IMEDispatcher.getInstance = function () {
- if (!cc.IMEDispatcher.instance) {
- cc.IMEDispatcher.instance = new cc.IMEDispatcher();
- cc.IMEDispatcher.instance.init();
- }
- return cc.IMEDispatcher.instance;
-};
+// Initialize imeDispatcher singleton
+cc.imeDispatcher = new cc.IMEDispatcher();
-/**
- * @type object
- */
-cc.IMEDispatcher.instance = null;
+document.body ?
+ cc.imeDispatcher.init() :
+ window.addEventListener('load', function () {
+ cc.imeDispatcher.init();
+ }, false);
diff --git a/cocos2d/text-input/CCTextFieldTTF.js b/cocos2d/text-input/CCTextFieldTTF.js
new file mode 100644
index 0000000000..c582afb199
--- /dev/null
+++ b/cocos2d/text-input/CCTextFieldTTF.js
@@ -0,0 +1,492 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * Text field delegate
+ * @class
+ * @extends cc.Class
+ */
+cc.TextFieldDelegate = cc.Class.extend(/** @lends cc.TextFieldDelegate# */{
+ /**
+ * If the sender doesn't want to attach with IME, return true;
+ * @param {cc.TextFieldTTF} sender
+ * @return {Boolean}
+ */
+ onTextFieldAttachWithIME: function (sender) {
+ return false;
+ },
+
+ /**
+ * If the sender doesn't want to detach with IME, return true;
+ * @param {cc.TextFieldTTF} sender
+ * @return {Boolean}
+ */
+ onTextFieldDetachWithIME: function (sender) {
+ return false;
+ },
+
+ /**
+ * If the sender doesn't want to insert the text, return true;
+ * @param {cc.TextFieldTTF} sender
+ * @param {String} text
+ * @param {Number} len
+ * @return {Boolean}
+ */
+ onTextFieldInsertText: function (sender, text, len) {
+ return false
+ },
+
+ /**
+ * If the sender doesn't want to delete the delText, return true;
+ * @param {cc.TextFieldTTF} sender
+ * @param {String} delText
+ * @param {Number} len
+ * @return {Boolean}
+ */
+ onTextFieldDeleteBackward: function (sender, delText, len) {
+ return false;
+ },
+
+ /**
+ * If doesn't want draw sender as default, return true.
+ * @param {cc.TextFieldTTF} sender
+ * @return {Boolean}
+ */
+ onDraw: function (sender) {
+ return false;
+ }
+});
+
+/**
+ * A simple text input field with TTF font.
+ * @class
+ * @extends cc.LabelTTF
+ *
+ * @property {cc.Node} delegate - Delegate
+ * @property {Number} charCount - <@readonly> Characators count
+ * @property {String} placeHolder - Place holder for the field
+ * @property {cc.Color} colorSpaceHolder
+ *
+ * @param {String} placeholder
+ * @param {cc.Size} dimensions
+ * @param {Number} alignment
+ * @param {String} fontName
+ * @param {Number} fontSize
+ *
+ * @example
+ * //example
+ * // When five parameters
+ * var textField = new cc.TextFieldTTF("", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32);
+ * // When three parameters
+ * var textField = new cc.TextFieldTTF("", "Arial", 32);
+ */
+cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{
+ delegate: null,
+ colorSpaceHolder: null,
+
+ _colorText: null,
+ _lens: null,
+ _inputText: "",
+ _placeHolder: "",
+ _charCount: 0,
+ _className: "TextFieldTTF",
+
+ /**
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * creates a cc.TextFieldTTF from a fontName, alignment, dimension and font size.
+ * @param {String} placeholder
+ * @param {cc.Size} dimensions
+ * @param {Number} alignment
+ * @param {String} fontName
+ * @param {Number} fontSize
+ */
+ ctor: function (placeholder, dimensions, alignment, fontName, fontSize) {
+ this.colorSpaceHolder = cc.color(127, 127, 127);
+ this._colorText = cc.color(255, 255, 255, 255);
+ cc.LabelTTF.prototype.ctor.call(this);
+
+ if (fontSize !== undefined) {
+ this.initWithPlaceHolder("", dimensions, alignment, fontName, fontSize);
+ if (placeholder)
+ this.setPlaceHolder(placeholder);
+ } else if (fontName === undefined && alignment !== undefined) {
+ this.initWithString("", arguments[1], arguments[2]);
+ if (placeholder)
+ this.setPlaceHolder(placeholder);
+ }
+ },
+
+ onEnter: function () {
+ cc.LabelTTF.prototype.onEnter.call(this);
+ cc.imeDispatcher.addDelegate(this);
+ },
+
+ onExit: function () {
+ cc.LabelTTF.prototype.onExit.call(this);
+ cc.imeDispatcher.removeDelegate(this);
+ },
+
+ /**
+ * Gets the delegate.
+ * @return {cc.Node}
+ */
+ getDelegate: function () {
+ return this.delegate;
+ },
+
+ /**
+ * Set the delegate.
+ * @param {cc.Node} value
+ */
+ setDelegate: function (value) {
+ this.delegate = value;
+ },
+
+ /**
+ * Gets the char count.
+ * @return {Number}
+ */
+ getCharCount: function () {
+ return this._charCount;
+ },
+
+ /**
+ * Returns the color of space holder.
+ * @return {cc.Color}
+ */
+ getColorSpaceHolder: function () {
+ return cc.color(this.colorSpaceHolder);
+ },
+
+ /**
+ * Sets the color of space holder.
+ * @param {cc.Color} value
+ */
+ setColorSpaceHolder: function (value) {
+ this.colorSpaceHolder.r = value.r;
+ this.colorSpaceHolder.g = value.g;
+ this.colorSpaceHolder.b = value.b;
+ this.colorSpaceHolder.a = cc.isUndefined(value.a) ? 255 : value.a;
+ if (!this._inputText.length)
+ this.setColor(this.colorSpaceHolder);
+ },
+
+ /**
+ * Sets the color of cc.TextFieldTTF's text.
+ * @param {cc.Color} textColor
+ */
+ setTextColor: function (textColor) {
+ this._colorText.r = textColor.r;
+ this._colorText.g = textColor.g;
+ this._colorText.b = textColor.b;
+ this._colorText.a = cc.isUndefined(textColor.a) ? 255 : textColor.a;
+ if (this._inputText.length)
+ this.setColor(this._colorText);
+ },
+
+ /**
+ * Initializes the cc.TextFieldTTF with a font name, alignment, dimension and font size
+ * @param {String} placeholder
+ * @param {cc.Size} dimensions
+ * @param {Number} alignment
+ * @param {String} fontName
+ * @param {Number} fontSize
+ * @return {Boolean}
+ * @example
+ * //example
+ * var textField = new cc.TextFieldTTF();
+ * // When five parameters
+ * textField.initWithPlaceHolder("", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32);
+ * // When three parameters
+ * textField.initWithPlaceHolder("", "Arial", 32);
+ */
+ initWithPlaceHolder: function (placeholder, dimensions, alignment, fontName, fontSize) {
+ switch (arguments.length) {
+ case 5:
+ if (placeholder)
+ this.setPlaceHolder(placeholder);
+ return this.initWithString(this._placeHolder, fontName, fontSize, dimensions, alignment);
+ break;
+ case 3:
+ if (placeholder)
+ this.setPlaceHolder(placeholder);
+ return this.initWithString(this._placeHolder, arguments[1], arguments[2]);
+ break;
+ default:
+ throw new Error("Argument must be non-nil ");
+ break;
+ }
+ },
+
+ /**
+ * Input text property
+ * @param {String} text
+ */
+ setString: function (text) {
+ text = String(text);
+ this._inputText = text || "";
+
+ // if there is no input text, display placeholder instead
+ if (!this._inputText.length) {
+ cc.LabelTTF.prototype.setString.call(this, this._placeHolder);
+ this.setColor(this.colorSpaceHolder);
+ } else {
+ cc.LabelTTF.prototype.setString.call(this, this._inputText);
+ this.setColor(this._colorText);
+ }
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ this._renderCmd._updateTexture();
+ this._charCount = this._inputText.length;
+ },
+
+ /**
+ * Gets the string
+ * @return {String}
+ */
+ getString: function () {
+ return this._inputText;
+ },
+
+ /**
+ * Set the place holder.
+ * display this string if string equal "".
+ * @param {String} text
+ */
+ setPlaceHolder: function (text) {
+ this._placeHolder = text || "";
+ if (!this._inputText.length) {
+ cc.LabelTTF.prototype.setString.call(this, this._placeHolder);
+ this.setColor(this.colorSpaceHolder);
+ }
+ },
+
+ /**
+ * Gets the place holder.
+ * default display string.
+ * @return {String}
+ */
+ getPlaceHolder: function () {
+ return this._placeHolder;
+ },
+
+ /**
+ * Render function using the canvas 2d context or WebGL context, internal usage only, please do not call this function.
+ * @param {CanvasRenderingContext2D | WebGLRenderingContext} ctx The render context
+ */
+ draw: function (ctx) {
+ //console.log("size",this._contentSize);
+ var context = ctx || cc._renderContext;
+ if (this.delegate && this.delegate.onDraw(this))
+ return;
+
+ cc.LabelTTF.prototype.draw.call(this, context);
+ },
+
+ //////////////////////////////////////////////////////////////////////////
+ // CCIMEDelegate interface
+ //////////////////////////////////////////////////////////////////////////
+ /**
+ * Open keyboard and receive input text.
+ * @return {Boolean}
+ */
+ attachWithIME: function () {
+ return cc.imeDispatcher.attachDelegateWithIME(this);
+ },
+
+ /**
+ * End text input and close keyboard.
+ * @return {Boolean}
+ */
+ detachWithIME: function () {
+ return cc.imeDispatcher.detachDelegateWithIME(this);
+ },
+
+ /**
+ * Return whether to allow attach with IME.
+ * @return {Boolean}
+ */
+ canAttachWithIME: function () {
+ return (this.delegate) ? (!this.delegate.onTextFieldAttachWithIME(this)) : true;
+ },
+
+ /**
+ * When the delegate detach with IME, this method call by CCIMEDispatcher.
+ */
+ didAttachWithIME: function () {
+ },
+
+ /**
+ * Return whether to allow detach with IME.
+ * @return {Boolean}
+ */
+ canDetachWithIME: function () {
+ return (this.delegate) ? (!this.delegate.onTextFieldDetachWithIME(this)) : true;
+ },
+
+ /**
+ * When the delegate detach with IME, this method call by CCIMEDispatcher.
+ */
+ didDetachWithIME: function () {
+ },
+
+ /**
+ * Delete backward
+ */
+ deleteBackward: function () {
+ var strLen = this._inputText.length;
+ if (strLen === 0)
+ return;
+
+ // get the delete byte number
+ var deleteLen = 1; // default, erase 1 byte
+
+ if (this.delegate && this.delegate.onTextFieldDeleteBackward(this, this._inputText[strLen - deleteLen], deleteLen)) {
+ // delegate don't want delete backward
+ return;
+ }
+
+ // if delete all text, show space holder string
+ if (strLen <= deleteLen) {
+ this._inputText = "";
+ this._charCount = 0;
+ cc.LabelTTF.prototype.setString.call(this, this._placeHolder);
+ this.setColor(this.colorSpaceHolder);
+ return;
+ }
+
+ // set new input text
+ this.string = this._inputText.substring(0, strLen - deleteLen);
+ },
+
+ /**
+ * Remove delegate
+ */
+ removeDelegate: function () {
+ cc.imeDispatcher.removeDelegate(this);
+ },
+
+ _tipMessage: "please enter your word:",
+ /**
+ * Sets the input tip message to show on mobile browser. (mobile Web only)
+ * @param {string} tipMessage
+ */
+ setTipMessage: function (tipMessage) {
+ if (tipMessage == null)
+ return;
+ this._tipMessage = tipMessage;
+ },
+
+ /**
+ * Gets the input tip message to show on mobile browser. (mobile Web only)
+ * @returns {string}
+ */
+ getTipMessage: function () {
+ return this._tipMessage;
+ },
+
+ /**
+ * Append the text.
+ * Input the character.
+ * @param {String} text
+ * @param {Number} len
+ */
+ insertText: function (text, len) {
+ var sInsert = text;
+
+ // insert \n means input end
+ var pos = sInsert.indexOf('\n');
+ if (pos > -1) {
+ sInsert = sInsert.substring(0, pos);
+ }
+
+ if (sInsert.length > 0) {
+ if (this.delegate && this.delegate.onTextFieldInsertText(this, sInsert, sInsert.length)) {
+ // delegate doesn't want insert text
+ return;
+ }
+
+ var sText = this._inputText + sInsert;
+ this._charCount = sText.length;
+ this.string = sText;
+ }
+
+ if (pos === -1)
+ return;
+
+ // '\n' has inserted, let delegate process first
+ if (this.delegate && this.delegate.onTextFieldInsertText(this, "\n", 1))
+ return;
+
+ // if delegate hasn't process, detach with ime as default
+ this.detachWithIME();
+ },
+
+ /**
+ * Gets the input text.
+ * @return {String}
+ */
+ getContentText: function () {
+ return this._inputText;
+ },
+
+ //////////////////////////////////////////////////////////////////////////
+ // keyboard show/hide notification
+ //////////////////////////////////////////////////////////////////////////
+ keyboardWillShow: function (info) {
+ },
+ keyboardDidShow: function (info) {
+ },
+ keyboardWillHide: function (info) {
+ },
+ keyboardDidHide: function (info) {
+ }
+});
+
+var _p = cc.TextFieldTTF.prototype;
+
+// Extended properties
+/** @expose */
+_p.charCount;
+cc.defineGetterSetter(_p, "charCount", _p.getCharCount);
+/** @expose */
+_p.placeHolder;
+cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder);
+
+/**
+ * Please use new TextFieldTTF instead.
+ * Creates a cc.TextFieldTTF from a fontName, alignment, dimension and font size.
+ * @deprecated since v3.0 Please use new TextFieldTTF instead.
+ * @param {String} placeholder
+ * @param {cc.Size} dimensions
+ * @param {Number} alignment
+ * @param {String} fontName
+ * @param {Number} fontSize
+ * @return {cc.TextFieldTTF|Null}
+ */
+cc.TextFieldTTF.create = function (placeholder, dimensions, alignment, fontName, fontSize) {
+ return new cc.TextFieldTTF(placeholder, dimensions, alignment, fontName, fontSize);
+};
+
diff --git a/cocos2d/text_input_node/CCTextFieldTTF.js b/cocos2d/text_input_node/CCTextFieldTTF.js
deleted file mode 100644
index e029b779ba..0000000000
--- a/cocos2d/text_input_node/CCTextFieldTTF.js
+++ /dev/null
@@ -1,417 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Text field delegate
- * @class
- * @extends cc.Class
- */
-cc.TextFieldDelegate = cc.Class.extend(/** @lends cc.TextFieldDelegate# */{
- /**
- * If the sender doesn't want to attach with IME, return true;
- * @param {cc.TextFieldTTF} sender
- * @return {Boolean}
- */
- onTextFieldAttachWithIME:function (sender) {
- return false;
- },
-
- /**
- * If the sender doesn't want to detach with IME, return true;
- * @param {cc.TextFieldTTF} sender
- * @return {Boolean}
- */
- onTextFieldDetachWithIME:function (sender) {
- return false;
- },
-
- /**
- * If the sender doesn't want to insert the text, return true;
- * @param {cc.TextFieldTTF} sender
- * @param {String} text
- * @param {Number} len
- * @return {Boolean}
- */
- onTextFieldInsertText:function (sender, text, len) {
- return false
- },
-
- /**
- * If the sender doesn't want to delete the delText, return true;
- * @param {cc.TextFieldTTF} sender
- * @param {String} delText
- * @param {Number} len
- * @return {Boolean}
- */
- onTextFieldDeleteBackward:function (sender, delText, len) {
- return false;
- },
-
- /**
- * If doesn't want draw sender as default, return true.
- * @param {cc.TextFieldTTF} sender
- * @return {Boolean}
- */
- onDraw:function (sender) {
- return false;
- }
-});
-
-/**
- * A simple text input field with TTF font.
- * @class
- * @extends cc.LabelTTF
- */
-cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{
- _lens:null,
- _inputText:"",
- _placeHolder:"",
- _charCount:0,
- _delegate:null,
- _ColorSpaceHolder:null,
- /**
- * Constructor
- */
- ctor:function () {
- this._ColorSpaceHolder = new cc.Color3B(127, 127, 127);
- cc.IMEDispatcher.getInstance().addDelegate(this);
- cc.LabelTTF.prototype.ctor.call(this);
- },
-
- /**
- * @return {cc.Node}
- */
- getDelegate:function () {
- return this._delegate;
- },
-
- /**
- * @param {cc.Node} value
- */
- setDelegate:function (value) {
- this._delegate = value;
- },
-
- /**
- * @return {Number}
- */
- getCharCount:function () {
- return this._charCount;
- },
-
- /**
- * @return {cc.Color3B}
- */
- getColorSpaceHolder:function () {
- return this._ColorSpaceHolder;
- },
-
- /**
- * @param {cc.Color3B} value
- */
- setColorSpaceHolder:function (value) {
- this._ColorSpaceHolder = value;
- },
- /**
- * Initializes the cc.TextFieldTTF with a font name, alignment, dimension and font size
- * @param {String} placeholder
- * @param {cc.Size} dimensions
- * @param {Number} alignment
- * @param {String} fontName
- * @param {Number} fontSize
- * @return {Boolean}
- * @example
- * //example
- * var textField = new cc.TextFieldTTF();
- * // When five parameters
- * textField.initWithPlaceHolder("", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32);
- * // When three parameters
- * textField.initWithPlaceHolder("", "Arial", 32);
- */
- initWithPlaceHolder:function (placeholder, dimensions, alignment, fontName, fontSize) {
- switch (arguments.length) {
- case 5:
- if (placeholder) {
- this._placeHolder = placeholder;
- }
- return this.initWithString(this._placeHolder,fontName, fontSize, dimensions, alignment);
- break;
- case 3:
- if (placeholder) {
- this._placeHolder = placeholder;
- }
- fontName = arguments[1];
- fontSize = arguments[2];
- return this.initWithString(this._placeHolder, fontName, fontSize);
- break;
- default:
- throw "Argument must be non-nil ";
- break;
- }
- },
-
- /**
- * Input text property
- * @param {String} text
- */
- setString:function (text) {
- text = String(text);
- this._inputText = text || "";
-
- // if there is no input text, display placeholder instead
- if (!this._inputText.length)
- cc.LabelTTF.prototype.setString.call(this, this._placeHolder);
- else
- cc.LabelTTF.prototype.setString.call(this,this._inputText);
- this._charCount = this._inputText.length;
- },
-
- /**
- * @return {String}
- */
- getString:function () {
- return this._inputText;
- },
-
- /**
- * @param {String} text
- */
- setPlaceHolder:function (text) {
- this._placeHolder = text || "";
- if (!this._inputText.length) {
- cc.LabelTTF.prototype.setString.call(this,this._placeHolder);
- }
- },
-
- /**
- * @return {String}
- */
- getPlaceHolder:function () {
- return this._placeHolder;
- },
-
- /**
- * @param {CanvasContext} ctx
- */
- draw:function (ctx) {
- //console.log("size",this._contentSize);
- var context = ctx || cc.renderContext;
- if (this._delegate && this._delegate.onDraw(this))
- return;
-
- if (this._inputText && this._inputText.length > 0) {
- cc.LabelTTF.prototype.draw.call(this, context);
- return;
- }
-
- // draw placeholder
- var color = this.getColor();
- this.setColor(this._ColorSpaceHolder);
- if(cc.renderContextType === cc.CANVAS)
- this._updateTexture();
- cc.LabelTTF.prototype.draw.call(this, context);
- this.setColor(color);
- },
-
- //////////////////////////////////////////////////////////////////////////
- // CCIMEDelegate interface
- //////////////////////////////////////////////////////////////////////////
- /**
- * Open keyboard and receive input text.
- * @return {Boolean}
- */
- attachWithIME:function () {
- return cc.IMEDispatcher.getInstance().attachDelegateWithIME(this);
- },
-
- /**
- * End text input and close keyboard.
- * @return {Boolean}
- */
- detachWithIME:function () {
- return cc.IMEDispatcher.getInstance().detachDelegateWithIME(this);
- },
-
- /**
- * @return {Boolean}
- */
- canAttachWithIME:function () {
- return (this._delegate) ? (!this._delegate.onTextFieldAttachWithIME(this)) : true;
- },
-
- /**
- * When the delegate detach with IME, this method call by CCIMEDispatcher.
- */
- didAttachWithIME:function () {
- },
-
- /**
- * @return {Boolean}
- */
- canDetachWithIME:function () {
- return (this._delegate) ? (!this._delegate.onTextFieldDetachWithIME(this)) : true;
- },
-
- /**
- * When the delegate detach with IME, this method call by CCIMEDispatcher.
- */
- didDetachWithIME:function () {
- },
-
- /**
- * Delete backward
- */
- deleteBackward:function () {
- var strLen = this._inputText.length;
- if (strLen == 0)
- return;
-
- // get the delete byte number
- var deleteLen = 1; // default, erase 1 byte
-
- if (this._delegate && this._delegate.onTextFieldDeleteBackward(this, this._inputText[strLen - deleteLen], deleteLen)) {
- // delegate don't want delete backward
- return;
- }
-
- // if delete all text, show space holder string
- if (strLen <= deleteLen) {
- this._inputText = "";
- this._charCount = 0;
- cc.LabelTTF.prototype.setString.call(this,this._placeHolder);
- return;
- }
-
- // set new input text
- var sText = this._inputText.substring(0, strLen - deleteLen);
- this.setString(sText);
- },
-
- /**
- * Remove delegate
- */
- removeDelegate:function () {
- cc.IMEDispatcher.getInstance().removeDelegate(this);
- },
-
- /**
- * @param {String} text
- * @param {Number} len
- */
- insertText:function (text, len) {
- var sInsert = text;
-
- // insert \n means input end
- var pos = sInsert.indexOf('\n');
- if (pos > -1) {
- sInsert = sInsert.substring(0, pos);
- }
-
- if (sInsert.length > 0) {
- if (this._delegate && this._delegate.onTextFieldInsertText(this, sInsert, sInsert.length)) {
- // delegate doesn't want insert text
- return;
- }
-
- var sText = this._inputText + sInsert;
- this._charCount = sText.length;
- this.setString(sText);
- }
-
- if (pos == -1)
- return;
-
- // '\n' has inserted, let delegate process first
- if (this._delegate && this._delegate.onTextFieldInsertText(this, "\n", 1))
- return;
-
- // if delegate hasn't process, detach with ime as default
- this.detachWithIME();
- },
- /**
- * @return {String}
- */
- getContentText:function () {
- return this._inputText;
- },
-
- //////////////////////////////////////////////////////////////////////////
- // keyboard show/hide notification
- //////////////////////////////////////////////////////////////////////////
- keyboardWillShow:function (info) {
- },
- keyboardDidShow:function (info) {
- },
- keyboardWillHide:function (info) {
- },
- keyboardDidHide:function (info) {
- }
-});
-
-/**
- * creates a cc.TextFieldTTF from a fontName, alignment, dimension and font size
- * @param {String} placeholder
- * @param {cc.Size} dimensions
- * @param {Number} alignment
- * @param {String} fontName
- * @param {Number} fontSize
- * @return {cc.TextFieldTTF|Null}
- * @example
- * //example
- * // When five parameters
- * var textField = cc.TextFieldTTF.create("", cc.size(100,50), cc.TEXT_ALIGNMENT_LEFT,"Arial", 32);
- * // When three parameters
- * var textField = cc.TextFieldTTF.create("", "Arial", 32);
- */
-cc.TextFieldTTF.create = function (placeholder, dimensions, alignment, fontName, fontSize) {
- var ret;
- switch (arguments.length) {
- case 5:
- ret = new cc.TextFieldTTF();
- if (ret && ret.initWithPlaceHolder("", dimensions, alignment, fontName, fontSize)) {
- if (placeholder)
- ret.setPlaceHolder(placeholder);
- return ret;
- }
- return null;
- break;
- case 3:
- ret = new cc.TextFieldTTF();
- fontName = arguments[1];
- fontSize = arguments[2];
- if (ret && ret.initWithString("", fontName, fontSize)) {
- if (placeholder)
- ret.setPlaceHolder(placeholder);
- return ret;
- }
- return null;
- break;
- default:
- throw "Argument must be non-nil ";
- break;
- }
-};
-
diff --git a/cocos2d/textures/CCTexture2D.js b/cocos2d/textures/CCTexture2D.js
deleted file mode 100644
index b9f12d0089..0000000000
--- a/cocos2d/textures/CCTexture2D.js
+++ /dev/null
@@ -1,1329 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-//CONSTANTS:
-
-//----------------------Possible texture pixel formats----------------------------
-/**
- * 32-bit texture: RGBA8888
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888 = 0;
-
-/**
- * 24-bit texture: RGBA888
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_RGB888 = 1;
-
-/**
- * 16-bit texture without Alpha channel
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_RGB565 = 2;
-
-/**
- * 8-bit textures used as masks
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_A8 = 3;
-
-/**
- * 8-bit intensity texture
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_I8 = 4;
-
-/**
- * 16-bit textures used as masks
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_AI88 = 5;
-
-/**
- * 16-bit textures: RGBA4444
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444 = 6;
-
-/**
- * 16-bit textures: RGB5A1
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1 = 7;
-
-/**
- * 4-bit PVRTC-compressed texture: PVRTC4
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC4 = 8;
-
-/**
- * 2-bit PVRTC-compressed texture: PVRTC2
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC2 = 9;
-
-/**
- * Default texture format: RGBA8888
- * @constant
- * @type {Number}
- */
-cc.TEXTURE_2D_PIXEL_FORMAT_DEFAULT = cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888;
-
-// If the image has alpha, you can create RGBA8 (32-bit) or RGBA4 (16-bit) or RGB5A1 (16-bit)
-// Default is: RGBA8888 (32-bit textures)
-cc._defaultAlphaPixelFormat = cc.TEXTURE_2D_PIXEL_FORMAT_DEFAULT;
-
-// By default PVR images are treated as if they don't have the alpha channel premultiplied
-cc.PVRHaveAlphaPremultiplied_ = false;
-
-/**
- Extension to set the Min / Mag filter
- */
-cc._texParams = function (minFilter, magFilter, wrapS, wrapT) {
- this.minFilter = minFilter || 0;
- this.magFilter = magFilter || 0;
- this.wrapS = wrapS || 0;
- this.wrapT = wrapT || 0;
-};
-
-/**
- *
- * This class allows to easily create OpenGL 2D textures from images, text or raw data.
- * The created cc.Texture2D object will always have power-of-two dimensions.
- * Depending on how you create the cc.Texture2D object, the actual image area of the texture might be smaller than the texture dimensions
- * i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).
- * Be aware that the content of the generated textures will be upside-down!
- * @class
- * @extends cc.Class
- */
-cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{
- // By default PVR images are treated as if they don't have the alpha channel premultiplied
- _pVRHaveAlphaPremultiplied:null,
- _pixelFormat:null,
- _pixelsWide:null,
- _pixelsHigh:null,
- _name:null,
- _contentSize:null,
- _maxS:null,
- _maxT:null,
- _hasPremultipliedAlpha:null,
- _hasMipmaps:false,
-
- _shaderProgram:null,
-
- _isLoaded:false,
- _htmlElementObj:null,
- _webTextureObj:null,
-
- _loadedEventListeners:null,
-
- /*public:*/
- ctor:function () {
- this._pixelsWide = 0;
- this._pixelsHigh = 0;
- this._name = "";
- this._maxS = 0;
- this._maxT = 0;
- this._hasPremultipliedAlpha = false;
- this._contentSize = cc.size(0, 0);
-
- this._hasMipmaps = false;
- this._pVRHaveAlphaPremultiplied = true;
- this._pixelFormat = cc.Texture2D.defaultAlphaPixelFormat();
-
- this._shaderProgram = null;
- this._isLoaded = false;
- this._htmlElementObj = null;
- this._webTextureObj = null;
- this._loadedEventListeners = [];
- },
-
- releaseTexture:function () {
- if (this._webTextureObj)
- cc.renderContext.deleteTexture(this._webTextureObj);
- },
-
- /**
- * pixel format of the texture
- * @return {Number}
- */
- getPixelFormat:function () {
- return this._pixelFormat;
- },
-
- /**
- * width in pixels
- * @return {Number}
- */
- getPixelsWide:function () {
- return this._pixelsWide;
- },
-
- /**
- * hight in pixels
- * @return {Number}
- */
- getPixelsHigh:function () {
- return this._pixelsHigh;
- },
-
- /**
- * get WebGLTexture Object
- * @return {WebGLTexture}
- */
- getName:function () {
- return this._webTextureObj;
- },
-
- /**
- * content size
- * @return {cc.Size}
- */
- getContentSize:function () {
- return cc.size(this._contentSize.width / cc.CONTENT_SCALE_FACTOR(), this._contentSize.height / cc.CONTENT_SCALE_FACTOR());
- },
-
- getContentSizeInPixels:function () {
- return this._contentSize;
- },
-
- /** texture max S */
- getMaxS:function () {
- return this._maxS;
- },
-
- setMaxS:function (maxS) {
- this._maxS = maxS;
- },
-
- /** texture max T */
- getMaxT:function () {
- return this._maxT;
- },
-
- setMaxT:function (maxT) {
- this._maxT = maxT;
- },
-
- /**
- * return shader program used by drawAtPoint and drawInRect
- * @return {cc.GLProgram}
- */
- getShaderProgram:function () {
- return this._shaderProgram;
- },
-
- /**
- * set shader program used by drawAtPoint and drawInRect
- * @param {cc.GLProgram} shaderProgram
- */
- setShaderProgram:function (shaderProgram) {
- this._shaderProgram = shaderProgram;
- },
-
- /**
- * whether or not the texture has their Alpha premultiplied
- * @return {Boolean}
- */
- hasPremultipliedAlpha:function () {
- return this._hasPremultipliedAlpha;
- },
-
- hasMipmaps:function () {
- return this._hasMipmaps;
- },
-
- description:function () {
- return "";
- },
-
- /**
- * These functions are needed to create mutable textures
- * @param {Array} data
- */
- releaseData:function (data) {
- data = null;
- },
-
- keepData:function (data, length) {
- //The texture data mustn't be saved becuase it isn't a mutable texture.
- return data;
- },
-
- /**
- * Intializes with a texture2d with data
- * @param {Array} data
- * @param {Number} pixelFormat
- * @param {Number} pixelsWide
- * @param {Number} pixelsHigh
- * @param {cc.Size} contentSize
- * @return {Boolean}
- */
- initWithData:function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
- var gl = cc.renderContext;
-
- var bitsPerPixel = 0;
- //Hack: bitsPerPixelForFormat returns wrong number for RGB_888 textures. See function.
- if (pixelFormat === cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888) {
- bitsPerPixel = 24;
- } else {
- bitsPerPixel = this.bitsPerPixelForFormat(pixelFormat);
- }
-
- var bytesPerRow = pixelsWide * bitsPerPixel / 8;
- if (bytesPerRow % 8 === 0) {
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8);
- } else if (bytesPerRow % 4 === 0) {
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
- } else if (bytesPerRow % 2 === 0) {
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2);
- } else {
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- }
-
- this._webTextureObj = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, this._webTextureObj);
-
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
-
- // Specify OpenGL texture image
- switch (pixelFormat) {
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
- break;
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB888:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_BYTE, data);
- break;
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, data);
- break;
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1, data);
- break;
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB565:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, data);
- break;
- case cc.TEXTURE_2D_PIXEL_FORMAT_AI88:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE_ALPHA, pixelsWide, pixelsHigh, 0, gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, data);
- break;
- case cc.TEXTURE_2D_PIXEL_FORMAT_A8:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, pixelsWide, pixelsHigh, 0, gl.ALPHA, gl.UNSIGNED_BYTE, data);
- break;
- case cc.TEXTURE_2D_PIXEL_FORMAT_I8:
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, pixelsWide, pixelsHigh, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data);
- break;
- default:
- cc.Assert(0, "NSInternalInconsistencyException");
- break;
- }
-
-
- this._contentSize = contentSize;
- this._pixelsWide = pixelsWide;
- this._pixelsHigh = pixelsHigh;
- this._pixelFormat = pixelFormat;
- this._maxS = contentSize.width / pixelsWide;
- this._maxT = contentSize.height / pixelsHigh;
-
- this._hasPremultipliedAlpha = false;
- this._hasMipmaps = false;
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE));
-
- this._isLoaded = true;
-
- return true;
- },
-
- /**
- Drawing extensions to make it easy to draw basic quads using a CCTexture2D object.
- These functions require gl.TEXTURE_2D and both gl.VERTEX_ARRAY and gl.TEXTURE_COORD_ARRAY client states to be enabled.
- */
-
- /**
- * draws a texture at a given point
- * @param {cc.Point} point
- */
- drawAtPoint:function (point) {
- var coordinates = [
- 0.0, this._maxT,
- this._maxS, this._maxT,
- 0.0, 0.0,
- this._maxS, 0.0 ];
-
- var width = this._pixelsWide * this._maxS,
- height = this._pixelsHigh * this._maxT;
-
- var vertices = [
- point.x, point.y, 0.0,
- width + point.x, point.y, 0.0,
- point.x, height + point.y, 0.0,
- width + point.x, height + point.y, 0.0 ];
-
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS);
- this._shaderProgram.use();
- this._shaderProgram.setUniformsForBuiltins();
-
- cc.glBindTexture2D(this);
-
- var gl = cc.renderContext;
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
-
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- },
-
- /**
- * draws a texture inside a rect
- * @param {cc.Rect} rect
- */
- drawInRect:function (rect) {
- var coordinates = [
- 0.0, this._maxT,
- this._maxS, this._maxT,
- 0.0, 0.0,
- this._maxS, 0.0];
-
- var vertices = [ rect.x, rect.y, /*0.0,*/
- rect.x + rect.width, rect.y, /*0.0,*/
- rect.x, rect.y + rect.height, /*0.0,*/
- rect.x + rect.width, rect.y + rect.height /*0.0*/ ];
-
- cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS);
- this._shaderProgram.use();
- this._shaderProgram.setUniformsForBuiltins();
-
- cc.glBindTexture2D(this);
-
- var gl = cc.renderContext;
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
- gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
-
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- },
-
- /**
- Extensions to make it easy to create a CCTexture2D object from an image file.
- Note that RGBA type textures will have their alpha premultiplied - use the blending mode (gl.ONE, gl.ONE_MINUS_SRC_ALPHA).
- */
-
- /**
- * Initializes a texture from a UIImage object
- * @param uiImage
- * @return {Boolean}
- */
- initWithImage:function (uiImage) {
- if (uiImage == null) {
- cc.log("cocos2d: cc.Texture2D. Can't create Texture. UIImage is nil");
- return false;
- }
-
- var imageWidth = uiImage.getWidth();
- var imageHeight = uiImage.getHeight();
-
- var conf = cc.Configuration.getInstance();
-
- var maxTextureSize = conf.getMaxTextureSize();
- if (imageWidth > maxTextureSize || imageHeight > maxTextureSize) {
- cc.log("cocos2d: WARNING: Image (" + imageWidth + " x " + imageHeight + ") is bigger than the supported " + maxTextureSize + " x " + maxTextureSize);
- return false;
- }
- this._isLoaded = true;
-
- // always load premultiplied images
- return this._initPremultipliedATextureWithImage(uiImage, imageWidth, imageHeight);
- },
-
- initWithElement:function (element) {
- if (!element)
- return;
- this._webTextureObj = cc.renderContext.createTexture();
- this._htmlElementObj = element;
- },
-
- /**
- * HTMLElement Object getter
- * @return {HTMLElement}
- */
- getHtmlElementObj:function(){
- return this._htmlElementObj;
- },
-
- isLoaded:function () {
- return this._isLoaded;
- },
-
- handleLoadedTexture:function () {
- this._isLoaded = true;
- //upload image to buffer
- var gl = cc.renderContext;
-
- cc.glBindTexture2D(this);
-
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
-
- // Specify OpenGL texture image
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._htmlElementObj);
-
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE));
- gl.bindTexture(gl.TEXTURE_2D, null);
-
- var pixelsWide = this._htmlElementObj.width;
- var pixelsHigh = this._htmlElementObj.height;
-
- this._contentSize = new cc.Size(pixelsWide, pixelsHigh);
- this._pixelsWide = pixelsWide;
- this._pixelsHigh = pixelsHigh;
- this._pixelFormat = cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888;
- this._maxS = 1;
- this._maxT = 1;
-
- this._hasPremultipliedAlpha = false;
- this._hasMipmaps = false;
-
- this._callLoadedEventCallbacks();
- },
-
- /**
- Extensions to make it easy to create a cc.Texture2D object from a string of text.
- Note that the generated textures are of type A8 - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
- */
- /**
- * Initializes a texture from a string with dimensions, alignment, font name and font size (note: initWithString does not support on HTML5)
- * @param {String} text
- * @param {String | cc.FontDefinition} fontName or fontDefinition
- * @param {Number} fontSize
- * @param {cc.Size} dimensions
- * @param {Number} hAlignment
- * @param {Number} vAlignment
- * @return {Boolean}
- */
- initWithString:function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
- if (arguments.length == 3) {
- fontName = arguments[1];
- fontSize = arguments[2];
- dimensions = cc.size(0, 0);
- hAlignment = cc.TEXT_ALIGNMENT_CENTER;
- vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
- }
-
- /*if (cc.ENABLE_CACHE_TEXTURE_DATA) {
- // cache the texture data
- cc.VolatileTexture.addStringTexture(this, text, dimensions, alignment, fontName, fontSize);
- }*/
-
- var image = new cc.Image();
- var eAlign;
-
- if (cc.VERTICAL_TEXT_ALIGNMENT_TOP === vAlignment) {
- eAlign = (cc.TEXT_ALIGNMENT_CENTER === hAlignment) ? cc.ALIGN_TOP
- : (cc.TEXT_ALIGNMENT_LEFT === hAlignment) ? cc.ALIGN_TOP_LEFT : cc.ALIGN_TOP_RIGHT;
- } else if (cc.VERTICAL_TEXT_ALIGNMENT_CENTER === vAlignment) {
- eAlign = (cc.TEXT_ALIGNMENT_CENTER === hAlignment) ? cc.ALIGN_CENTER
- : (cc.TEXT_ALIGNMENT_LEFT === hAlignment) ? cc.ALIGN_LEFT : cc.ALIGN_RIGHT;
- } else if (cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM === vAlignment) {
- eAlign = (cc.TEXT_ALIGNMENT_CENTER === hAlignment) ? cc.ALIGN_BOTTOM
- : (cc.TEXT_ALIGNMENT_LEFT === hAlignment) ? cc.ALIGN_BOTTOM_LEFT : cc.ALIGN_BOTTOM_RIGHT;
- } else {
- cc.Assert(false, "Not supported alignment format!");
- }
-
- if (!image.initWithString(text, dimensions.width, dimensions.height, eAlign, fontName, fontSize))
- return false;
-
- return this.initWithImage(image);
- },
-
- /**
- * Initializes a texture from a ETC file (note: initWithETCFile does not support on HTML5)
- * @note Compatible to Cocos2d-x
- * @param {String} file
- * @return {Boolean}
- */
- initWithETCFile:function (file) {
- return false;
- },
-
- /**
- * Initializes a texture from a PVR file
- * @param {String} file
- * @return {Boolean}
- */
- initWithPVRFile:function (file) {
- var ret = false;
- // nothing to do with cc.Object.init
-
- var pvr = new cc.TexturePVR;
- ret = pvr.initWithContentsOfFile(file);
-
- if (ret) {
- pvr.setRetainName(true); // don't dealloc texture on release
-
- this._name = pvr.getName();
- this._maxS = 1.0;
- this._maxT = 1.0;
- this._pixelsWide = pvr.getWidth();
- this._pixelsHigh = pvr.getHeight();
- this._contentSize = cc.size(this._pixelsWide, this._pixelsHigh);
- this._hasPremultipliedAlpha = cc.PVRHaveAlphaPremultiplied_;
- this._pixelFormat = pvr.getFormat();
-
- this.setAntiAliasTexParameters();
- } else {
- cc.log("cocos2d: Couldn't load PVR image " + file);
- }
- return ret;
- },
-
- /**
- Extensions to make it easy to create a cc.Texture2D object from a PVRTC file
- Note that the generated textures don't have their alpha premultiplied - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
- */
- /**
- * Initializes a texture from a PVRTC buffer
- * @note compatible to cocos2d-iphone interface.
- * @param {Array} data
- * @param {Number} level
- * @param {Number} bpp
- * @param {Boolean} hasAlpha
- * @param {Number} length
- * @param {Number} pixelFormat
- * @return {Boolean}
- */
- initWithPVRTCData:function (data, level, bpp, hasAlpha, length, pixelFormat) {
- if (!(cc.Configuration.getInstance().supportsPVRTC())) {
- cc.log("cocos2d: WARNING: PVRTC images is not supported.");
- return false;
- }
- return true;
- },
-
- /**
- * sets the min filter, mag filter, wrap s and wrap t texture parameters.
- * If the texture size is NPOT (non power of 2), then in can only use gl.CLAMP_TO_EDGE in gl.TEXTURE_WRAP_{S,T}.
- * @param texParams
- */
- setTexParameters:function (texParams) {
- var gl = cc.renderContext;
-
- cc.Assert((this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh)) ||
- (texParams.wrapS == gl.CLAMP_TO_EDGE && texParams.wrapT == gl.CLAMP_TO_EDGE),
- "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures");
-
- cc.glBindTexture2D(this);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT);
-
- //TODO
- //VolatileTexture::setTexParameters(this, texParams);
- },
-
- /**
- * sets antialias texture parameters:
- * - GL_TEXTURE_MIN_FILTER = GL_NEAREST
- * - GL_TEXTURE_MAG_FILTER = GL_NEAREST
- */
- setAntiAliasTexParameters:function () {
- var gl = cc.renderContext;
-
- cc.glBindTexture2D(this);
- if (!this._hasMipmaps)
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- else
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- //TODO
- /*#if CC_ENABLE_CACHE_TEXTURE_DATA
- ccTexParams texParams = {m_bHasMipmaps?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR,GL_LINEAR,GL_NONE,GL_NONE};
- VolatileTexture::setTexParameters(this, &texParams);
- #endif*/
- },
-
- /**
- * sets alias texture parameters:
- * GL_TEXTURE_MIN_FILTER = GL_NEAREST
- * GL_TEXTURE_MAG_FILTER = GL_NEAREST
- */
- setAliasTexParameters:function () {
- var gl = cc.renderContext;
-
- cc.glBindTexture2D(this);
- if (!this._hasMipmaps)
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- else
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-
- //TODO
- /*#if CC_ENABLE_CACHE_TEXTURE_DATA
- ccTexParams texParams = {m_bHasMipmaps?GL_NEAREST_MIPMAP_NEAREST:GL_NEAREST,GL_NEAREST,GL_NONE,GL_NONE};
- VolatileTexture::setTexParameters(this, &texParams);
- #endif*/
- },
-
- /**
- * Generates mipmap images for the texture.
- * It only works if the texture size is POT (power of 2).
- */
- generateMipmap:function () {
- cc.Assert(this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh), "Mimpap texture only works in POT textures");
-
- cc.glBindTexture2D(this);
- cc.renderContext.generateMipmap(cc.renderContext.TEXTURE_2D);
- this._hasMipmaps = true;
- },
-
- /**
- * returns the pixel format.
- * @return {String}
- */
- stringForFormat:function () {
- switch (this._pixelFormat) {
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888:
- return "RGBA8888";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB888:
- return "RGB888";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB565:
- return "RGB565";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444:
- return "RGBA4444";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1:
- return "RGB5A1";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_AI88:
- return "AI88";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_A8:
- return "A8";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_I8:
- return "I8";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC4:
- return "PVRTC4";
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC2:
- return "PVRTC2";
-
- default:
- cc.Assert(false, "unrecognized pixel format");
- cc.log("stringForFormat: " + this._pixelFormat + ", cannot give useful result");
- break;
- }
- return "";
- },
-
- /**
- * returns the bits-per-pixel of the in-memory OpenGL texture
- * @return {Number}
- */
- bitsPerPixelForFormat:function (format) {
- format = format || this._pixelFormat;
- switch (format) {
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888:
- return 32;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB888:
- return 32;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB565:
- return 16;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_A8:
- return 8;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444:
- return 16;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1:
- return 16;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC4:
- return 4;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_PVRTC2:
- return 2;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_I8:
- return 8;
-
- case cc.TEXTURE_2D_PIXEL_FORMAT_AI88:
- return 16;
-
- default:
- cc.Assert(false, "illegal pixel format");
- cc.log("bitsPerPixelForFormat: " + this._pixelFormat + ", cannot give useful result");
- return -1;
- }
- },
-
- _initPremultipliedATextureWithImage:function (uiImage, width, height) {
- var tempData = uiImage.getData();
- var inPixel32 = null;
- var inPixel8 = null;
- var outPixel16 = null;
- var hasAlpha = uiImage.hasAlpha();
- var imageSize = cc.size(uiImage.getWidth(), uiImage.getHeight());
- var pixelFormat = cc.TEXTURE_2D_PIXEL_FORMAT_DEFAULT;
- var bpp = uiImage.getBitsPerComponent();
- var i;
-
- // compute pixel format
- if (!hasAlpha) {
- if (bpp >= 8) {
- pixelFormat = cc.TEXTURE_2D_PIXEL_FORMAT_RGB888;
- } else {
- cc.log("cocos2d: cc.Texture2D: Using RGB565 texture since image has no alpha");
- pixelFormat = cc.TEXTURE_2D_PIXEL_FORMAT_RGB565;
- }
- }
-
- // Repack the pixel data into the right format
- var length = width * height;
-
- if (pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_RGB565) {
- if (hasAlpha) {
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
- tempData = new Uint16Array(width * height);
- inPixel32 = uiImage.getData();
-
- for (i = 0; i < length; ++i) {
- tempData[i] =
- ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) | // R
- ((((inPixel32[i] >> 8) & 0xFF) >> 2) << 5) | // G
- ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 0); // B
- }
- } else {
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB"
- tempData = new Uint16Array(width * height);
- inPixel8 = uiImage.getData();
-
- for (i = 0; i < length; ++i) {
- tempData[i] =
- (((inPixel8[i] & 0xFF) >> 3) << 11) | // R
- (((inPixel8[i] & 0xFF) >> 2) << 5) | // G
- (((inPixel8[i] & 0xFF) >> 3) << 0); // B
- }
- }
- } else if (pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444) {
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
- tempData = new Uint16Array(width * height);
- inPixel32 = uiImage.getData();
-
- for (i = 0; i < length; ++i) {
- tempData[i] =
- ((((inPixel32[i] >> 0) & 0xFF) >> 4) << 12) | // R
- ((((inPixel32[i] >> 8) & 0xFF) >> 4) << 8) | // G
- ((((inPixel32[i] >> 16) & 0xFF) >> 4) << 4) | // B
- ((((inPixel32[i] >> 24) & 0xFF) >> 4) << 0); // A
- }
- } else if (pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1) {
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA"
- tempData = new Uint16Array(width * height);
- inPixel32 = uiImage.getData();
-
- for (i = 0; i < length; ++i) {
- tempData[i] =
- ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) | // R
- ((((inPixel32[i] >> 8) & 0xFF) >> 3) << 6) | // G
- ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 1) | // B
- ((((inPixel32[i] >> 24) & 0xFF) >> 7) << 0); // A
- }
- } else if (pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_A8) {
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "AAAAAAAA"
- tempData = new Uint8Array(width * height);
- inPixel32 = uiImage.getData();
-
- for (i = 0; i < length; ++i) {
- tempData[i] = (inPixel32 >> 24) & 0xFF; // A
- }
- }
-
- if (hasAlpha && pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_RGB888) {
- // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBBB"
- inPixel32 = uiImage.getData();
- tempData = new Uint8Array(width * height * 3);
-
- for (i = 0; i < length; ++i) {
- tempData[i * 3] = (inPixel32 >> 0) & 0xFF; // R
- tempData[i * 3 + 1] = (inPixel32 >> 8) & 0xFF; // G
- tempData[i * 3 + 2] = (inPixel32 >> 16) & 0xFF; // B
- }
- }
-
- this.initWithData(tempData, pixelFormat, width, height, imageSize);
-
- if (tempData != uiImage.getData())
- tempData = null;
-
- this._hasPremultipliedAlpha = uiImage.isPremultipliedAlpha();
- return true;
- },
-
- addLoadedEventListener: function (callback, target) {
- this._loadedEventListeners.push({eventCallback: callback, eventTarget: target});
- },
-
- removeLoadedEventListener:function(target){
- var locListeners = this._loadedEventListeners;
- for(var i = 0; i < locListeners.length; i++){
- var selCallback = locListeners[i];
- if(selCallback.eventTarget == target){
- locListeners.splice(i, 1);
- }
- }
- },
-
- _callLoadedEventCallbacks: function () {
- var locListeners = this._loadedEventListeners;
- for (var i = 0, len = locListeners.length; i < len; i++) {
- var selCallback = locListeners[i];
- selCallback.eventCallback.call(selCallback.eventTarget, this);
- }
- locListeners.length = 0;
- }
-});
-
-/**
- *
- * This class allows to easily create Canvas 2D textures from images, text or raw data.
- * The created cc.Texture2D object will always have power-of-two dimensions.
- * Depending on how you create the cc.Texture2D object, the actual image area of the texture might be smaller than the texture dimensions
- * i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).
- * Be aware that the content of the generated textures will be upside-down!
- * @class
- * @extends cc.Class
- */
-cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{
- _contentSize:null,
- _isLoaded:false,
- _htmlElementObj:null,
-
- _loadedEventListeners:null,
- /*public:*/
- ctor:function () {
- this._contentSize = cc.size(0,0);
- this._isLoaded = false;
- this._htmlElementObj = null;
- this._loadedEventListeners = [];
- },
-
- /**
- * width in pixels
- * @return {Number}
- */
- getPixelsWide:function () {
- return this._contentSize.width;
- },
-
- /**
- * hight in pixels
- * @return {Number}
- */
- getPixelsHigh:function () {
- return this._contentSize.height;
- },
-
- /**
- * content size
- * @return {cc.Size}
- */
- getContentSize:function () {
- return cc.size(this._contentSize.width / cc.CONTENT_SCALE_FACTOR(), this._contentSize.height / cc.CONTENT_SCALE_FACTOR());
- },
-
- getContentSizeInPixels:function () {
- return this._contentSize;
- },
-
- initWithElement:function (element) {
- if (!element)
- return;
- this._htmlElementObj = element;
- },
-
- /**
- * HTMLElement Object getter
- * @return {HTMLElement}
- */
- getHtmlElementObj:function(){
- return this._htmlElementObj;
- },
-
- isLoaded:function () {
- return this._isLoaded;
- },
-
- handleLoadedTexture:function () {
- this._isLoaded = true;
- var locElement = this._htmlElementObj;
- this._contentSize = new cc.Size(locElement.width, locElement.height);
-
- this._callLoadedEventCallbacks();
- },
-
- description:function () {
- return "";
- },
-
- /**
- * Intializes with a texture2d with data
- * @param {Array} data
- * @param {Number} pixelFormat
- * @param {Number} pixelsWide
- * @param {Number} pixelsHigh
- * @param {cc.Size} contentSize
- * @return {Boolean}
- */
- initWithData:function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
- //support only in WebGl rendering mode
- return false;
- },
-
- /**
- Extensions to make it easy to create a CCTexture2D object from an image file.
- Note that RGBA type textures will have their alpha premultiplied - use the blending mode (gl.ONE, gl.ONE_MINUS_SRC_ALPHA).
- */
- /**
- * Initializes a texture from a UIImage object
- * @param uiImage
- * @return {Boolean}
- */
- initWithImage:function (uiImage) {
- //support only in WebGl rendering mode
- return false;
- },
-
- /**
- Extensions to make it easy to create a cc.Texture2D object from a string of text.
- Note that the generated textures are of type A8 - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
- */
- /**
- * Initializes a texture from a string with dimensions, alignment, font name and font size (note: initWithString does not support on HTML5)
- * @param {String} text
- * @param {String | cc.FontDefinition} fontName or fontDefinition
- * @param {Number} fontSize
- * @param {cc.Size} dimensions
- * @param {Number} hAlignment
- * @param {Number} vAlignment
- * @return {Boolean}
- */
- initWithString:function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
- //support only in WebGl rendering mode
- return false;
- },
-
- releaseTexture:function () {
- //support only in WebGl rendering mode
- },
-
- /**
- * get WebGLTexture Object
- * @return {WebGLTexture}
- */
- getName:function () {
- //support only in WebGl rendering mode
- return null;
- },
-
- /** texture max S */
- getMaxS:function () {
- //support only in WebGl rendering mode
- return 1;
- },
-
- setMaxS:function (maxS) {
- //support only in WebGl rendering mode
- },
-
- /** texture max T */
- getMaxT:function () {
- return 1;
- },
-
- setMaxT:function (maxT) {
- //support only in WebGl rendering mode
- },
-
- /**
- * return shader program used by drawAtPoint and drawInRect
- * @return {cc.GLProgram}
- */
- getShaderProgram:function () {
- //support only in WebGl rendering mode
- return null;
- },
-
- /**
- * set shader program used by drawAtPoint and drawInRect
- * @param {cc.GLProgram} shaderProgram
- */
- setShaderProgram:function (shaderProgram) {
- //support only in WebGl rendering mode
- },
-
- /**
- * whether or not the texture has their Alpha premultiplied
- * @return {Boolean}
- */
- hasPremultipliedAlpha:function () {
- //support only in WebGl rendering mode
- return false;
- },
-
- hasMipmaps:function () {
- //support only in WebGl rendering mode
- return false;
- },
-
- /**
- * These functions are needed to create mutable textures
- * @param {Array} data
- */
- releaseData:function (data) {
- //support only in WebGl rendering mode
- data = null;
- },
-
- keepData:function (data, length) {
- //support only in WebGl rendering mode
- return data;
- },
-
- /**
- Drawing extensions to make it easy to draw basic quads using a CCTexture2D object.
- These functions require gl.TEXTURE_2D and both gl.VERTEX_ARRAY and gl.TEXTURE_COORD_ARRAY client states to be enabled.
- */
-
- /**
- * draws a texture at a given point
- * @param {cc.Point} point
- */
- drawAtPoint:function (point) {
- //support only in WebGl rendering mode
- },
-
- /**
- * draws a texture inside a rect
- * @param {cc.Rect} rect
- */
- drawInRect:function (rect) {
- //support only in WebGl rendering mode
- },
-
- /**
- * Initializes a texture from a ETC file (note: initWithETCFile does not support on HTML5)
- * @note Compatible to Cocos2d-x
- * @param {String} file
- * @return {Boolean}
- */
- initWithETCFile:function (file) {
- //support only in WebGl rendering mode
- return false;
- },
-
- /**
- * Initializes a texture from a PVR file
- * @param {String} file
- * @return {Boolean}
- */
- initWithPVRFile:function (file) {
- //support only in WebGl rendering mode
- return false;
- },
-
- /**
- Extensions to make it easy to create a cc.Texture2D object from a PVRTC file
- Note that the generated textures don't have their alpha premultiplied - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
- */
- /**
- * Initializes a texture from a PVRTC buffer
- * @note compatible to cocos2d-iphone interface.
- * @param {Array} data
- * @param {Number} level
- * @param {Number} bpp
- * @param {Boolean} hasAlpha
- * @param {Number} length
- * @param {Number} pixelFormat
- * @return {Boolean}
- */
- initWithPVRTCData:function (data, level, bpp, hasAlpha, length, pixelFormat) {
- //support only in WebGl rendering mode
- return true;
- },
-
- /**
- * sets the min filter, mag filter, wrap s and wrap t texture parameters.
- * If the texture size is NPOT (non power of 2), then in can only use gl.CLAMP_TO_EDGE in gl.TEXTURE_WRAP_{S,T}.
- * @param texParams
- */
- setTexParameters:function (texParams) {
- //support only in WebGl rendering mode
- },
-
- /**
- * sets antialias texture parameters:
- * - GL_TEXTURE_MIN_FILTER = GL_NEAREST
- * - GL_TEXTURE_MAG_FILTER = GL_NEAREST
- */
- setAntiAliasTexParameters:function () {
- //support only in WebGl rendering mode
- },
-
- /**
- * sets alias texture parameters:
- * GL_TEXTURE_MIN_FILTER = GL_NEAREST
- * GL_TEXTURE_MAG_FILTER = GL_NEAREST
- */
- setAliasTexParameters:function () {
- //support only in WebGl rendering mode
- },
-
- /**
- * Generates mipmap images for the texture.
- * It only works if the texture size is POT (power of 2).
- */
- generateMipmap:function () {
- //support only in WebGl rendering mode
- },
-
- /**
- * returns the pixel format.
- * @return {String}
- */
- stringForFormat:function () {
- //support only in WebGl rendering mode
- return "";
- },
-
- /**
- * returns the bits-per-pixel of the in-memory OpenGL texture
- * @return {Number}
- */
- bitsPerPixelForFormat:function (format) {
- //support only in WebGl rendering mode
- return -1;
- },
-
- addLoadedEventListener:function(callback, target){
- this._loadedEventListeners.push({eventCallback:callback, eventTarget:target});
- },
-
- removeLoadedEventListener:function(target){
- var locListeners = this._loadedEventListeners;
- for(var i = 0; i < locListeners.length; i++){
- var selCallback = locListeners[i];
- if(selCallback.eventTarget == target){
- locListeners.splice(i, 1);
- }
- }
- },
-
- _callLoadedEventCallbacks:function(){
- var locListeners = this._loadedEventListeners;
- for(var i = 0, len = locListeners.length; i < len; i++){
- var selCallback = locListeners[i];
- selCallback.eventCallback.call(selCallback.eventTarget, this);
- }
- locListeners.length = 0;
- }
-});
-
-cc.Texture2D = cc.Browser.supportWebGL ? cc.Texture2DWebGL : cc.Texture2DCanvas;
-
-/**
- *
- * sets the default pixel format for UIImagescontains alpha channel.
- * If the UIImage contains alpha channel, then the options are:
- * - generate 32-bit textures: cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888 (default one)
- * - generate 24-bit textures: cc.TEXTURE_2D_PIXEL_FORMAT_RGB888
- * - generate 16-bit textures: cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444
- * - generate 16-bit textures: cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1
- * - generate 16-bit textures: cc.TEXTURE_2D_PIXEL_FORMAT_RGB565
- * - generate 8-bit textures: cc.TEXTURE_2D_PIXEL_FORMAT_A8 (only use it if you use just 1 color)
- *
- * How does it work ?
- * - If the image is an RGBA (with Alpha) then the default pixel format will be used (it can be a 8-bit, 16-bit or 32-bit texture)
- * - If the image is an RGB (without Alpha) then an RGB565 or RGB888 texture will be used (16-bit texture)
- *
- * @param {Number} format
- */
-cc.Texture2D.setDefaultAlphaPixelFormat = function (format) {
- cc._defaultAlphaPixelFormat = format;
-};
-
-/**
- * returns the alpha pixel format
- * @return {Number}
- */
-cc.Texture2D.defaultAlphaPixelFormat = function () {
- return cc._defaultAlphaPixelFormat;
-};
-
-cc.Texture2D.getDefaultAlphaPixelFormat = function () {
- return cc._defaultAlphaPixelFormat;
-};
-
-/**
- *
- * treats (or not) PVR files as if they have alpha premultiplied.
- * Since it is impossible to know at runtime if the PVR images have the alpha channel premultiplied, it is
- * possible load them as if they have (or not) the alpha channel premultiplied.
- *
- * By default it is disabled.
- *
- * @param haveAlphaPremultiplied
- * @constructor
- */
-cc.Texture2D.PVRImagesHavePremultipliedAlpha = function (haveAlphaPremultiplied) {
- cc.PVRHaveAlphaPremultiplied_ = haveAlphaPremultiplied;
-};
diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js
deleted file mode 100644
index 9bd22e8d34..0000000000
--- a/cocos2d/textures/CCTextureCache.js
+++ /dev/null
@@ -1,532 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * TextureCache - Alloc, Init & Dealloc
- * @type object
- */
-cc.g_sharedTextureCache = null;
-
-/**
- * Load the images to the cache
- * @param {String} imageUrl
- */
-cc.loadImage = function (imageUrl) {
- // compute image type
- var imageType = cc.computeImageFormatType(imageUrl);
- if (imageType == cc.FMT_UNKNOWN) {
- cc.log("unsupported format:" + imageUrl);
- return;
- }
- var image = new Image();
- image.src = imageUrl;
- image.addEventListener('load',function(){
- cc.TextureCache.getInstance().cacheImage(imageUrl, image);
- this.removeEventListener('load', arguments.callee, false);
- },false);
-};
-
-/**
- * Support image format type
- * @param {String} filename
- * @return {Number}
- */
-cc.computeImageFormatType = function (filename) {
- if (filename.toLowerCase().indexOf('.jpg') > 0 || filename.toLowerCase().indexOf('.jpeg') > 0) {
- return cc.FMT_JPG;
- } else if (filename.toLowerCase().indexOf('.png') > 0) {
- return cc.FMT_PNG;
- } else if (filename.toLowerCase().indexOf('.webp') > 0) {
- return cc.FMT_WEBP;
- }
-
- return cc.FMT_UNKNOWN;
-};
-
-/**
- * Implementation TextureCache
- * @class
- * @extends cc.Class
- */
-cc.TextureCache = cc.Class.extend(/** @lends cc.TextureCache# */{
- _textures:null,
- _textureColorsCache:null,
- _textureKeySeq:null,
-
- _rendererInitialized:false,
- _loadedTexturesBefore:null,
- _loadingTexturesBefore:null,
-
- /**
- * Constructor
- */
- ctor: function () {
- cc.Assert(cc.g_sharedTextureCache == null, "Attempted to allocate a second instance of a singleton.");
- this._textureKeySeq += (0 | Math.random() * 1000);
- this._textures = {};
- this._textureColorsCache = {};
- if(cc.renderContextType === cc.WEBGL){
- this._loadedTexturesBefore = {};
- this._loadingTexturesBefore = {};
- }
- },
-
- _addImageAsyncCallBack:function (target, selector) {
- if (target && (typeof(selector) === "string")) {
- target[selector]();
- } else if (target && (typeof(selector) === "function")) {
- selector.call(target);
- }
- },
-
- _initializingRenderer : function(){
- this._rendererInitialized = true;
-
- var selPath;
- //init texture from _loadedTexturesBefore
- var locLoadedTexturesBefore = this._loadedTexturesBefore, locTextures = this._textures;
- for(selPath in locLoadedTexturesBefore){
- var htmlImage = locLoadedTexturesBefore[selPath];
-
- var texture2d = new cc.Texture2D();
- texture2d.initWithElement(htmlImage);
- texture2d.handleLoadedTexture();
- locTextures[selPath] = texture2d;
- }
- this._loadedTexturesBefore = {};
- },
-
- /**
- *
- * Returns a Texture2D object given an PVR filename
- * If the file image was not previously loaded, it will create a new CCTexture2D
- * object and it will return it. Otherwise it will return a reference of a previously loaded image
- * note: AddPVRTCImage does not support on HTML5
- *
- * @param {String} filename
- * @return {cc.Texture2D}
- */
- addPVRTCImage:function (filename) {
- cc.Assert(0, "TextureCache:addPVRTCImage does not support on HTML5");
- },
-
-
- /**
- *
- * Returns a Texture2D object given an ETC filename
- * If the file image was not previously loaded, it will create a new CCTexture2D
- * object and it will return it. Otherwise it will return a reference of a previously loaded image
- * note:addETCImage does not support on HTML5
- *
- * @param {String} filename
- * @return {cc.Texture2D}
- */
- addETCImage:function (filename) {
- cc.Assert(0, "TextureCache:addPVRTCImage does not support on HTML5");
- },
-
- /**
- * Description
- * @return {String}
- */
- description:function () {
- return "";
- },
-
- /**
- * Returns an already created texture. Returns null if the texture doesn't exist.
- * @param {String} textureKeyName
- * @return {cc.Texture2D|Null}
- * @example
- * //example
- * var key = cc.TextureCache.getInstance().textureForKey("hello.png");
- */
- textureForKey:function (textureKeyName) {
- var fullPath = cc.FileUtils.getInstance().fullPathForFilename(textureKeyName);
- if (this._textures.hasOwnProperty(fullPath))
- return this._textures[fullPath];
- return null;
- },
-
- /**
- * @param {Image} texture
- * @return {String|Null}
- * @example
- * //example
- * var key = cc.TextureCache.getInstance().getKeyByTexture(texture);
- */
- getKeyByTexture:function (texture) {
- for (var key in this._textures) {
- if (this._textures[key] == texture) {
- return key;
- }
- }
- return null;
- },
-
- _generalTextureKey:function () {
- this._textureKeySeq++;
- return "_textureKey_" + this._textureKeySeq;
- },
-
- /**
- * @param {Image} texture
- * @return {Array}
- * @example
- * //example
- * var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(texture);
- */
- getTextureColors:function (texture) {
- var key = this.getKeyByTexture(texture);
- if (!key) {
- if (texture instanceof HTMLImageElement)
- key = texture.src;
- else
- key = this._generalTextureKey();
- }
-
- if (!this._textureColorsCache.hasOwnProperty(key))
- this._textureColorsCache[key] = cc.generateTextureCacheForColor(texture);
- return this._textureColorsCache[key];
- },
-
- /**
- * Returns a Texture2D object given an PVR filename
- * If the file image was not previously loaded, it will create a new Texture2D
- * object and it will return it. Otherwise it will return a reference of a previously loaded image
- * @param {String} path
- * @return {cc.Texture2D}
- */
- addPVRImage:function (path) {
- cc.Assert(path != null, "TextureCache: file image MUST not be null");
-
- path = cc.FileUtils.getInstance().fullPathForFilename(path);
-
- var key = path;
-
- if (this._textures[key] != null) {
- return this._textures[key];
- }
-
- // Split up directory and filename
- var tex = new cc.Texture2D();
- if (tex.initWithPVRFile(key)) {
- this._textures[key] = tex;
- } else {
- cc.log("cocos2d: Couldn't add PVRImage:" + key + " in TextureCache");
- }
- return tex;
- },
-
- /**
- * Purges the dictionary of loaded textures.
- * Call this method if you receive the "Memory Warning"
- * In the short term: it will free some resources preventing your app from being killed
- * In the medium term: it will allocate more resources
- * In the long term: it will be the same
- * @example
- * //example
- * cc.TextureCache.getInstance().removeAllTextures();
- */
- removeAllTextures:function () {
- var locTextures = this._textures;
- for (var selKey in locTextures) {
- if(locTextures[selKey])
- locTextures[selKey].releaseTexture();
- }
- this._textures = {};
- },
-
- /**
- * Deletes a texture from the cache given a texture
- * @param {Image} texture
- * @example
- * //example
- * cc.TextureCache.getInstance().removeTexture(texture);
- */
- removeTexture:function (texture) {
- if (!texture)
- return;
-
- var locTextures = this._textures;
- for (var selKey in locTextures) {
- if (locTextures[selKey] == texture) {
- locTextures[selKey].releaseTexture();
- delete(locTextures[selKey]);
- }
- }
- },
-
- /**
- * Deletes a texture from the cache given a its key name
- * @param {String} textureKeyName
- * @example
- * //example
- * cc.TextureCache.getInstance().removeTexture("hello.png");
- */
- removeTextureForKey:function (textureKeyName) {
- if (textureKeyName == null)
- return;
- var fullPath = cc.FileUtils.getInstance().fullPathForFilename(textureKeyName);
- if (this._textures[fullPath])
- delete(this._textures[fullPath]);
- },
-
- /**
- * Loading the images asynchronously
- * @param {String} path
- * @param {cc.Node} target
- * @param {Function} selector
- * @return {cc.Texture2D}
- * @example
- * //example
- * cc.TextureCache.getInstance().addImageAsync("hello.png", this, this.loadingCallBack);
- */
- addImageAsync:function (path, target, selector) {
- cc.Assert(path != null, "TextureCache: path MUST not be null");
- path = cc.FileUtils.getInstance().fullPathForFilename(path);
- var texture = this._textures[path];
- var image,that;
- if (texture) {
- if(texture.isLoaded()){
- this._addImageAsyncCallBack(target, selector);
- }else{
- that = this;
- image = texture.getHtmlElementObj();
- image.addEventListener("load", function () {
- texture.handleLoadedTexture();
- that._addImageAsyncCallBack(target, selector);
- this.removeEventListener('load', arguments.callee, false);
- });
- }
- } else {
- image = new Image();
- image.crossOrigin = "Anonymous";
-
- that = this;
- image.addEventListener("load", function () {
- if (that._textures.hasOwnProperty(path))
- that._textures[path].handleLoadedTexture();
- that._addImageAsyncCallBack(target, selector);
- this.removeEventListener('load', arguments.callee, false);
- this.removeEventListener('error', arguments.callee, false);
- });
- image.addEventListener("error", function () {
- cc.Loader.getInstance().onResLoadingErr(path);
- //remove from cache
- if (that._textures.hasOwnProperty(path))
- delete that._textures[path];
-
- this.removeEventListener('error', arguments.callee, false);
- });
- image.src = path;
- var texture2d = new cc.Texture2D();
- texture2d.initWithElement(image);
- this._textures[path] = texture2d;
- }
- return this._textures[path];
- },
-
- _addImageBeforeRenderer:function(path){
- var texture = new Image();
- texture.crossOrigin = "Anonymous";
- var that = this;
- texture.addEventListener("load", function () {
- cc.Loader.getInstance().onResLoaded();
- that._loadedTexturesBefore[path] = texture;
- delete that._loadingTexturesBefore[path];
-
- this.removeEventListener('load', arguments.callee, false);
- this.removeEventListener('error', arguments.callee, false);
- });
- texture.addEventListener("error", function () {
- cc.Loader.getInstance().onResLoadingErr(path);
- delete that._loadingTexturesBefore[path];
-
- this.removeEventListener('error', arguments.callee, false);
- });
- texture.src = path;
- this._loadingTexturesBefore[path] = texture;
- },
-
- /**
- * Returns a Texture2D object given an file image
- * If the file image was not previously loaded, it will create a new Texture2D
- * object and it will return it. It will use the filename as a key.
- * Otherwise it will return a reference of a previously loaded image.
- * Supported image extensions: .png, .jpg, .gif
- * @param {String} path
- * @return {cc.Texture2D}
- * @example
- * //example
- * cc.TextureCache.getInstance().addImage("hello.png");
- */
- addImage:function (path) {
- cc.Assert(path != null, "TextureCache: path MUST not be null");
- if(cc.renderContextType === cc.WEBGL){
- if (!this._rendererInitialized)
- return this._addImageBeforeRenderer(path);
- }
-
- path = cc.FileUtils.getInstance().fullPathForFilename(path);
-
- var texture = this._textures[path];
- var image;
- if (texture) {
- if (texture.isLoaded()) {
- cc.Loader.getInstance().onResLoaded();
- } else {
- image = texture.getHtmlElementObj();
- image.addEventListener("load", function () {
- texture.handleLoadedTexture();
- cc.Loader.getInstance().onResLoaded();
- this.removeEventListener('load', arguments.callee, false);
- });
- }
- } else {
- image = new Image();
- image.crossOrigin = "Anonymous";
-
- var that = this;
- image.addEventListener("load", function () {
- cc.Loader.getInstance().onResLoaded();
- if (that._textures.hasOwnProperty(path))
- that._textures[path].handleLoadedTexture();
- this.removeEventListener('load', arguments.callee, false);
- this.removeEventListener('error', arguments.callee, false);
- });
- image.addEventListener("error", function () {
- cc.Loader.getInstance().onResLoadingErr(path);
- //remove from cache
- if (that._textures.hasOwnProperty(path))
- delete that._textures[path];
-
- this.removeEventListener('error', arguments.callee, false);
- });
- image.src = path;
- var texture2d = new cc.Texture2D();
- texture2d.initWithElement(image);
- this._textures[path] = texture2d;
- }
-
- return this._textures[path];
- },
-
- /**
- * Cache the image data
- * @param {String} path
- * @param {Image|HTMLImageElement|HTMLCanvasElement} texture
- */
- cacheImage:function (path, texture) {
- if(texture instanceof cc.Texture2D){
- this._textures[path] = texture;
- return ;
- }
- var texture2d = new cc.Texture2D();
- texture2d.initWithElement(texture);
- texture2d.handleLoadedTexture();
- this._textures[path] = texture2d;
- },
-
- /**
- * Returns a Texture2D object given an UIImage image
- * If the image was not previously loaded, it will create a new Texture2D object and it will return it.
- * Otherwise it will return a reference of a previously loaded image
- * The "key" parameter will be used as the "key" for the cache.
- * If "key" is null, then a new texture will be created each time.
- * @param {HTMLImageElement|HTMLCanvasElement} image
- * @param {String} key
- * @return {cc.Texture2D}
- */
- addUIImage:function (image, key) {
- cc.Assert(image != null, "TextureCache: image MUST not be nulll");
-
- if (key) {
- if (this._textures.hasOwnProperty(key) && this._textures[key])
- return this._textures[key];
- }
-
- // prevents overloading the autorelease pool
- var texture = new cc.Texture2D();
- texture.initWithImage(image);
- if ((key != null) && (texture != null))
- this._textures[key] = texture;
- else
- cc.log("cocos2d: Couldn't add UIImage in TextureCache");
- return texture;
- },
-
- /**
- * Output to cc.log the current contents of this TextureCache
- * This will attempt to calculate the size of each texture, and the total texture memory in use.
- */
- dumpCachedTextureInfo:function () {
- var count = 0;
- var totalBytes = 0, locTextures = this._textures;
-
- for (var key in locTextures) {
- var selTexture = locTextures[key];
- count++;
- if (selTexture.getHtmlElementObj() instanceof HTMLImageElement)
- cc.log("cocos2d: '" + key + "' id=" + selTexture.getHtmlElementObj().src + " " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh());
- else {
- cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh());
- }
- totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4;
- }
-
- var locTextureColorsCache = this._textureColorsCache;
- for (key in locTextureColorsCache) {
- var selCanvasColorsArr = locTextureColorsCache[key];
- for (var selCanvasKey in selCanvasColorsArr){
- var selCanvas = selCanvasColorsArr[selCanvasKey];
- count++;
- cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selCanvas.width + " x " + selCanvas.height);
- totalBytes += selCanvas.width * selCanvas.height * 4;
- }
-
- }
- cc.log("cocos2d: TextureCache dumpDebugInfo: " + count + " textures, HTMLCanvasElement for "
- + (totalBytes / 1024) + " KB (" + (totalBytes / (1024.0 * 1024.0)).toFixed(2) + " MB)");
- }
-});
-
-/**
- * Return ths shared instance of the cache
- * @return {cc.TextureCache}
- */
-cc.TextureCache.getInstance = function () {
- if (!cc.g_sharedTextureCache)
- cc.g_sharedTextureCache = new cc.TextureCache();
- return cc.g_sharedTextureCache;
-};
-
-/**
- * Purges the cache. It releases the retained instance.
- */
-cc.TextureCache.purgeSharedTextureCache = function () {
- cc.g_sharedTextureCache = null;
-};
diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js
deleted file mode 100644
index 6b580b2972..0000000000
--- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js
+++ /dev/null
@@ -1,897 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * cc.TMXLayer represents the TMX layer.
- *
- * It is a subclass of cc.SpriteBatchNode. By default the tiles are rendered using a cc.TextureAtlas.
- * If you modify a tile on runtime, then, that tile will become a cc.Sprite, otherwise no cc.Sprite objects are created.
- * The benefits of using cc.Sprite objects as tiles are:
- * - tiles (cc.Sprite) can be rotated/scaled/moved with a nice API
- *
- * If the layer contains a property named "cc.vertexz" with an integer (in can be positive or negative),
- * then all the tiles belonging to the layer will use that value as their OpenGL vertex Z for depth.
- *
- * On the other hand, if the "cc.vertexz" property has the "automatic" value, then the tiles will use an automatic vertex Z value.
- * Also before drawing the tiles, GL_ALPHA_TEST will be enabled, and disabled after drawing them. The used alpha func will be:
- *
- * glAlphaFunc( GL_GREATER, value )
- *
- * "value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer.
- * The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a different value, like 0.5.
- * @class
- * @extends cc.SpriteBatchNode
- */
-cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{
- //size of the layer in tiles
- _layerSize: null,
- _mapTileSize: null,
- _tiles: null,
- _tileSet: null,
- _layerOrientation: null,
- _properties: null,
- //name of the layer
- _layerName: "",
- //TMX Layer supports opacity
- _opacity: 255,
- _minGID: null,
- _maxGID: null,
- //Only used when vertexZ is used
- _vertexZvalue: null,
- _useAutomaticVertexZ: null,
- _alphaFuncValue: null,
- //used for optimization
- _reusedTile: null,
- _atlasIndexArray: null,
- //used for retina display
- _contentScaleFactor: null,
-
- _cacheCanvas:null,
- _cacheContext:null,
- _cacheTexture:null,
-
- /**
- * Constructor
- */
- ctor:function () {
- cc.SpriteBatchNode.prototype.ctor.call(this);
- this._children = [];
- this._descendants = [];
-
- this._layerSize = cc.SizeZero();
- this._mapTileSize = cc.SizeZero();
-
- if(cc.renderContextType === cc.CANVAS){
- var locCanvas = cc.canvas;
- var tmpCanvas = document.createElement('canvas');
- tmpCanvas.width = locCanvas.width;
- tmpCanvas.height = locCanvas.height;
- this._cacheCanvas = tmpCanvas;
- this._cacheContext = this._cacheCanvas.getContext('2d');
- var tempTexture = new cc.Texture2D();
- tempTexture.initWithElement(tmpCanvas);
- tempTexture.handleLoadedTexture();
- this._cacheTexture = tempTexture;
- this.setContentSize(cc.size(locCanvas.width, locCanvas.height));
- }
- },
-
- setContentSize:function (size) {
- if (!size)
- return;
- cc.Node.prototype.setContentSize.call(this, size);
-
- if(cc.renderContextType === cc.CANVAS){
- var locCanvas = this._cacheCanvas;
- locCanvas.width = 0|(size.width * 1.5);
- locCanvas.height = 0|(size.height * 1.5);
- this._cacheContext.translate(0, locCanvas.height);
- var locContentSize = this._cacheTexture._contentSize;
- locContentSize.width = locCanvas.width;
- locContentSize.height = locCanvas.height;
- }
- },
-
- /**
- * Return texture of cc.SpriteBatchNode
- * @return {cc.Texture2D}
- */
- getTexture:function () {
- if(cc.renderContextType === cc.CANVAS)
- return this._cacheTexture;
- else
- return cc.SpriteBatchNode.prototype.getTexture.call(this);
- },
-
- /**
- * don't call visit on it's children ( override visit of cc.Node )
- * @override
- * @param {CanvasRenderingContext2D} ctx
- */
- visit:function (ctx) {
- if (cc.renderContextType === cc.WEBGL) {
- cc.SpriteBatchNode.prototype.visit.call(this, ctx);
- return;
- }
- var context = ctx || cc.renderContext;
- // quick return if not visible
- if (!this._visible)
- return;
-
- context.save();
- this.transform(ctx);
- var i, locChildren = this._children;
-
- if (this._cacheDirty) {
- //add dirty region
- var locCacheContext = this._cacheContext, locCacheCanvas = this._cacheCanvas;
- locCacheContext.clearRect(0, 0, locCacheCanvas.width, -locCacheCanvas.height);
- locCacheContext.save();
- locCacheContext.translate(this._anchorPointInPoints.x, -(this._anchorPointInPoints.y ));
- if (locChildren) {
- this.sortAllChildren();
- for (i = 0; i < locChildren.length; i++) {
- if (locChildren[i])
- locChildren[i].visit(locCacheContext);
- }
- }
- locCacheContext.restore();
- this._cacheDirty = false;
- }
- // draw RenderTexture
- this.draw(ctx);
- context.restore();
- },
-
- /**
- * draw cc.SpriteBatchNode (override draw of cc.Node)
- * @param {CanvasRenderingContext2D} ctx
- */
- draw:null,
-
- _drawForCanvas:function (ctx) {
- var context = ctx || cc.renderContext;
- //context.globalAlpha = this._opacity / 255;
- var posX = 0 | ( -this._anchorPointInPoints.x), posY = 0 | ( -this._anchorPointInPoints.y);
- var locCacheCanvas = this._cacheCanvas;
- //direct draw image by canvas drawImage
- if (locCacheCanvas)
- context.drawImage(locCacheCanvas, posX, -(posY + locCacheCanvas.height));
- },
-
- /**
- * @return {cc.Size}
- */
- getLayerSize:function () {
- return cc.size(this._layerSize.width, this._layerSize.height);
- },
-
- /**
- * @param {cc.Size} Var
- */
- setLayerSize:function (Var) {
- this._layerSize.width = Var.width;
- this._layerSize.height = Var.height;
- },
-
- /**
- * Size of the map's tile (could be different from the tile's size)
- * @return {cc.Size}
- */
- getMapTileSize:function () {
- return cc.size(this._mapTileSize.width,this._mapTileSize.height);
- },
-
- /**
- * @param {cc.Size} Var
- */
- setMapTileSize:function (Var) {
- this._mapTileSize.width = Var.width;
- this._mapTileSize.height = Var.height;
- },
-
- /**
- * Pointer to the map of tiles
- * @return {Array}
- */
- getTiles:function () {
- return this._tiles;
- },
-
- /**
- * @param {Array} Var
- */
- setTiles:function (Var) {
- this._tiles = Var;
- },
-
- /**
- * Tile set information for the layer
- * @return {cc.TMXTilesetInfo}
- */
- getTileSet:function () {
- return this._tileSet;
- },
-
- /**
- * @param {cc.TMXTilesetInfo} Var
- */
- setTileSet:function (Var) {
- this._tileSet = Var;
- },
-
- /**
- * Layer orientation, which is the same as the map orientation
- * @return {Number}
- */
- getLayerOrientation:function () {
- return this._layerOrientation;
- },
-
- /**
- * @param {Number} Var
- */
- setLayerOrientation:function (Var) {
- this._layerOrientation = Var;
- },
-
- /**
- * properties from the layer. They can be added using Tiled
- * @return {Array}
- */
- getProperties:function () {
- return this._properties;
- },
-
- /**
- * @param {Array} Var
- */
- setProperties:function (Var) {
- this._properties = Var;
- },
-
- /**
- * Initializes a cc.TMXLayer with a tileset info, a layer info and a map info
- * @param {cc.TMXTilesetInfo} tilesetInfo
- * @param {cc.TMXLayerInfo} layerInfo
- * @param {cc.TMXMapInfo} mapInfo
- * @return {Boolean}
- */
- initWithTilesetInfo:function (tilesetInfo, layerInfo, mapInfo) {
- // XXX: is 35% a good estimate ?
- var size = layerInfo._layerSize;
- var totalNumberOfTiles = parseInt(size.width * size.height);
- var capacity = totalNumberOfTiles * 0.35 + 1; // 35 percent is occupied ?
- var texture;
- if (tilesetInfo)
- texture = cc.TextureCache.getInstance().addImage(tilesetInfo.sourceImage);
-
- if (this.initWithTexture(texture, capacity)) {
- // layerInfo
- this._layerName = layerInfo.name;
- this._layerSize = size;
- this._tiles = layerInfo._tiles;
- this._minGID = layerInfo._minGID;
- this._maxGID = layerInfo._maxGID;
- this._opacity = layerInfo._opacity;
- this.setProperties(layerInfo.getProperties());
- this._contentScaleFactor = cc.Director.getInstance().getContentScaleFactor();
-
- // tilesetInfo
- this._tileSet = tilesetInfo;
-
- // mapInfo
- this._mapTileSize = mapInfo.getTileSize();
- this._layerOrientation = mapInfo.getOrientation();
-
- // offset (after layer orientation is set);
- var offset = this._calculateLayerOffset(layerInfo.offset);
- this.setPosition(cc.POINT_PIXELS_TO_POINTS(offset));
-
- this._atlasIndexArray = [];
- this.setContentSize(cc.SIZE_PIXELS_TO_POINTS(cc.size(this._layerSize.width * this._mapTileSize.width,
- this._layerSize.height * this._mapTileSize.height)));
- this._useAutomaticVertexZ = false;
- this._vertexZvalue = 0;
- return true;
- }
- return false;
- },
-
- /**
- * Dealloc the map that contains the tile position from memory.
- * Unless you want to know at runtime the tiles positions, you can safely call this method.
- * If you are going to call layer.getTileGIDAt() then, don't release the map
- */
- releaseMap:function () {
- if (this._tiles)
- this._tiles = null;
-
- if (this._atlasIndexArray)
- this._atlasIndexArray = null;
- },
-
- /**
- * Returns the tile (cc.Sprite) at a given a tile coordinate.
- * The returned cc.Sprite will be already added to the cc.TMXLayer. Don't add it again.
- * The cc.Sprite can be treated like any other cc.Sprite: rotated, scaled, translated, opacity, color, etc.
- * You can remove either by calling:
- * - layer.removeChild(sprite, cleanup);
- * - or layer.removeTileAt(ccp(x,y));
- * @param {cc.Point} pos
- * @return {cc.Sprite}
- */
- getTileAt: function (pos) {
- cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position");
- cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released");
-
- var tile = null;
- var gid = this.getTileGIDAt(pos);
-
- // if GID == 0, then no tile is present
- if (gid === 0)
- return tile;
-
- var z = 0 | (pos.x + pos.y * this._layerSize.width);
- tile = this.getChildByTag(z);
- // tile not created yet. create it
- if (!tile) {
- var rect = this._tileSet.rectForGID(gid);
- rect = cc.RECT_PIXELS_TO_POINTS(rect);
-
- tile = new cc.Sprite();
- tile.initWithTexture(this.getTexture(), rect);
- tile.setBatchNode(this);
- tile.setPosition(this.getPositionAt(pos));
- tile.setVertexZ(this._vertexZForPos(pos));
- tile.setAnchorPoint(cc.PointZero());
- tile.setOpacity(this._opacity);
-
- var indexForZ = this._atlasIndexForExistantZ(z);
- this.addSpriteWithoutQuad(tile, indexForZ, z);
- }
- return tile;
- },
-
- /**
- * Returns the tile gid at a given tile coordinate.
- * if it returns 0, it means that the tile is empty.
- * This method requires the the tile map has not been previously released (eg. don't call layer.releaseMap())
- * @param {cc.Point} pos
- * @return {Number}
- */
- getTileGIDAt:function (pos) {
- cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position");
- cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released");
-
- var idx = 0 | (pos.x + pos.y * this._layerSize.width);
- // Bits on the far end of the 32-bit global tile ID are used for tile flags
- var tile = this._tiles[idx];
-
- return (tile & cc.TMX_TILE_FLIPPED_MASK) >>> 0;
- },
- // XXX: deprecated
- // tileGIDAt:getTileGIDAt,
-
- /**
- * lipped tiles can be changed dynamically
- * @param {cc.Point} pos
- * @return {Number}
- */
- getTileFlagsAt:function (pos) {
- cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position");
- cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released");
-
- var idx = 0 | (pos.x + pos.y * this._layerSize.width);
- // Bits on the far end of the 32-bit global tile ID are used for tile flags
- var tile = this._tiles[idx];
-
- return (tile & cc.TMX_TILE_FLIPPED_ALL) >>> 0;
- },
- // XXX: deprecated
- // tileFlagAt:getTileFlagsAt,
-
- /**
- * Sets the tile gid (gid = tile global id) at a given tile coordinate.
- * The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor . Tileset Mgr +1.
- * If a tile is already placed at that position, then it will be removed.
- * @param {Number} gid
- * @param {cc.Point} pos
- * @param {Number} flags
- */
- setTileGID:function (gid, pos, flags) {
- cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position");
- cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released");
- cc.Assert(gid !== 0 || !(gid >= this._tileSet.firstGid), "TMXLayer: invalid gid:" + gid);
-
- flags = flags || 0;
- this._setNodeDirtyForCache();
-
- var currentFlags = this.getTileFlagsAt(pos);
- var currentGID = this.getTileGIDAt(pos);
-
- if (currentGID != gid || currentFlags != flags) {
- var gidAndFlags = (gid | flags) >>> 0;
- // setting gid=0 is equal to remove the tile
- if (gid === 0)
- this.removeTileAt(pos);
- else if (currentGID === 0) // empty tile. create a new one
- this._insertTileForGID(gidAndFlags, pos);
- else { // modifying an existing tile with a non-empty tile
- var z = pos.x + pos.y * this._layerSize.width;
- var sprite = this.getChildByTag(z);
- if (sprite) {
- var rect = this._tileSet.rectForGID(gid);
- rect = cc.RECT_PIXELS_TO_POINTS(rect);
-
- sprite.setTextureRect(rect, false, rect.size);
- if (flags != null)
- this._setupTileSprite(sprite, pos, gidAndFlags);
-
- this._tiles[z] = gidAndFlags;
- } else
- this._updateTileForGID(gidAndFlags, pos);
- }
- }
- },
-
- /**
- * Removes a tile at given tile coordinate
- * @param {cc.Point} pos
- */
- removeTileAt:function (pos) {
- cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position");
- cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released");
-
- var gid = this.getTileGIDAt(pos);
- if (gid !== 0) {
- if (cc.renderContextType === cc.CANVAS)
- this._setNodeDirtyForCache();
- var z = 0 | (pos.x + pos.y * this._layerSize.width);
- var atlasIndex = this._atlasIndexForExistantZ(z);
- // remove tile from GID map
- this._tiles[z] = 0;
-
- // remove tile from atlas position array
- cc.ArrayRemoveObjectAtIndex(this._atlasIndexArray, atlasIndex);
-
- // remove it from sprites and/or texture atlas
- var sprite = this.getChildByTag(z);
-
- if (sprite)
- cc.SpriteBatchNode.prototype.removeChild.call(this, sprite, true); //this.removeChild(sprite, true);
- else {
- if(cc.renderContextType === cc.WEBGL)
- this._textureAtlas.removeQuadAtIndex(atlasIndex);
-
- // update possible children
- if (this._children) {
- var locChildren = this._children;
- for (var i = 0, len = locChildren.length; i < len; i++) {
- var child = locChildren[i];
- if (child) {
- var ai = child.getAtlasIndex();
- if (ai >= atlasIndex)
- child.setAtlasIndex(ai - 1);
- }
- }
- }
- }
- }
- },
-
- /**
- * Returns the position in pixels of a given tile coordinate
- * @param {cc.Point} pos
- * @return {cc.Point}
- */
- getPositionAt:function (pos) {
- var ret = cc.PointZero();
- switch (this._layerOrientation) {
- case cc.TMX_ORIENTATION_ORTHO:
- ret = this._positionForOrthoAt(pos);
- break;
- case cc.TMX_ORIENTATION_ISO:
- ret = this._positionForIsoAt(pos);
- break;
- case cc.TMX_ORIENTATION_HEX:
- ret = this._positionForHexAt(pos);
- break;
- }
- return cc.POINT_PIXELS_TO_POINTS(ret);
- },
- // XXX: Deprecated. For backward compatibility only
- // positionAt:getPositionAt,
-
- /**
- * Return the value for the specific property name
- * @param {String} propertyName
- * @return {*}
- */
- getProperty:function (propertyName) {
- return this._properties[propertyName];
- },
-
- /**
- * Creates the tiles
- */
- setupTiles:function () {
- // Optimization: quick hack that sets the image size on the tileset
- if (cc.renderContextType === cc.CANVAS) {
- this._tileSet.imageSize = this._originalTexture.getContentSizeInPixels();
- } else {
- this._tileSet.imageSize = this._textureAtlas.getTexture().getContentSizeInPixels();
-
- // By default all the tiles are aliased
- // pros:
- // - easier to render
- // cons:
- // - difficult to scale / rotate / etc.
- this._textureAtlas.getTexture().setAliasTexParameters();
- }
-
- // Parse cocos2d properties
- this._parseInternalProperties();
- if (cc.renderContextType === cc.CANVAS)
- this._setNodeDirtyForCache();
-
- var locLayerHeight = this._layerSize.height, locLayerWidth = this._layerSize.width;
- for (var y = 0; y < locLayerHeight; y++) {
- for (var x = 0; x < locLayerWidth; x++) {
- var pos = x + locLayerWidth * y;
- var gid = this._tiles[pos];
-
- // XXX: gid == 0 -. empty tile
- if (gid !== 0) {
- this._appendTileForGID(gid, cc.p(x, y));
- // Optimization: update min and max GID rendered by the layer
- this._minGID = Math.min(gid, this._minGID);
- this._maxGID = Math.max(gid, this._maxGID);
- }
- }
- }
-
- if (!((this._maxGID >= this._tileSet.firstGid) && (this._minGID >= this._tileSet.firstGid))) {
- cc.log("cocos2d:TMX: Only 1 tileset per layer is supported");
- }
- },
-
- /**
- * cc.TMXLayer doesn't support adding a cc.Sprite manually.
- * @warning addChild(child); is not supported on cc.TMXLayer. Instead of setTileGID.
- * @param {cc.Node} child
- * @param {number} zOrder
- * @param {number} tag
- */
- addChild:function (child, zOrder, tag) {
- cc.Assert(0, "addChild: is not supported on cc.TMXLayer. Instead use setTileGID:at:/tileAt:");
- },
-
- /**
- * Remove child
- * @param {cc.Sprite} sprite
- * @param {Boolean} cleanup
- */
- removeChild:function (sprite, cleanup) {
- // allows removing nil objects
- if (!sprite)
- return;
-
- cc.Assert(cc.ArrayContainsObject(this._children, sprite), "Tile does not belong to TMXLayer");
-
- if (cc.renderContextType === cc.CANVAS)
- this._setNodeDirtyForCache();
- var atlasIndex = sprite.getAtlasIndex(); //cc.ArrayGetIndexOfObject(this._children, sprite);
- var zz = this._atlasIndexArray[atlasIndex];
- this._tiles[zz] = 0;
- cc.ArrayRemoveObjectAtIndex(this._atlasIndexArray, atlasIndex);
- cc.SpriteBatchNode.prototype.removeChild.call(this, sprite, cleanup);
- },
-
- /**
- * @return {String}
- */
- getLayerName:function () {
- return this._layerName.toString();
- },
-
- /**
- * @param {String} layerName
- */
- setLayerName:function (layerName) {
- this._layerName = layerName;
- },
-
- _positionForIsoAt:function (pos) {
- return cc.p(this._mapTileSize.width / 2 * ( this._layerSize.width + pos.x - pos.y - 1),
- this._mapTileSize.height / 2 * (( this._layerSize.height * 2 - pos.x - pos.y) - 2));
- },
-
- _positionForOrthoAt:function (pos) {
- return cc.p(pos.x * this._mapTileSize.width,
- (this._layerSize.height - pos.y - 1) * this._mapTileSize.height);
- },
-
- _positionForHexAt:function (pos) {
- var diffY = (pos.x % 2 == 1) ? (-this._mapTileSize.height / 2) : 0;
- return cc.p(pos.x * this._mapTileSize.width * 3 / 4,
- (this._layerSize.height - pos.y - 1) * this._mapTileSize.height + diffY);
- },
-
- _calculateLayerOffset:function (pos) {
- var ret = cc.PointZero();
- switch (this._layerOrientation) {
- case cc.TMX_ORIENTATION_ORTHO:
- ret = cc.p(pos.x * this._mapTileSize.width, -pos.y * this._mapTileSize.height);
- break;
- case cc.TMX_ORIENTATION_ISO:
- ret = cc.p((this._mapTileSize.width / 2) * (pos.x - pos.y),
- (this._mapTileSize.height / 2 ) * (-pos.x - pos.y));
- break;
- case cc.TMX_ORIENTATION_HEX:
- cc.Assert((pos.x == 0 && pos.y == 0), "offset for hexagonal map not implemented yet");
- break;
- }
- return ret;
- },
-
- _appendTileForGID:function (gid, pos) {
- var rect = this._tileSet.rectForGID(gid);
- rect = cc.RECT_PIXELS_TO_POINTS(rect);
-
- var z = 0 | (pos.x + pos.y * this._layerSize.width);
- var tile = this._reusedTileWithRect(rect);
- this._setupTileSprite(tile, pos, gid);
-
- // optimization:
- // The difference between appendTileForGID and insertTileforGID is that append is faster, since
- // it appends the tile at the end of the texture atlas
- var indexForZ = this._atlasIndexArray.length;
-
- // don't add it using the "standard" way.
- this.insertQuadFromSprite(tile, indexForZ);
-
- // append should be after addQuadFromSprite since it modifies the quantity values
- this._atlasIndexArray = cc.ArrayAppendObjectToIndex(this._atlasIndexArray, z, indexForZ);
- return tile;
- },
-
- _insertTileForGID:function (gid, pos) {
- var rect = this._tileSet.rectForGID(gid);
- rect = cc.RECT_PIXELS_TO_POINTS(rect);
-
- var z = 0 | (pos.x + pos.y * this._layerSize.width);
- var tile = this._reusedTileWithRect(rect);
- this._setupTileSprite(tile, pos, gid);
-
- // get atlas index
- var indexForZ = this._atlasIndexForNewZ(z);
-
- // Optimization: add the quad without adding a child
- this.insertQuadFromSprite(tile, indexForZ);
-
- // insert it into the local atlasindex array
- this._atlasIndexArray = cc.ArrayAppendObjectToIndex(this._atlasIndexArray, z, indexForZ);
- // update possible children
- if (this._children) {
- var locChildren = this._children;
- for (var i = 0, len = locChildren.length; i < len; i++) {
- var child = locChildren[i];
- if (child) {
- var ai = child.getAtlasIndex();
- if (ai >= indexForZ)
- child.setAtlasIndex(ai + 1);
- }
- }
- }
- this._tiles[z] = gid;
- return tile;
- },
-
- _updateTileForGID:function (gid, pos) {
- var rect = this._tileSet.rectForGID(gid);
- var locScaleFactor = this._contentScaleFactor;
- rect = cc.rect(rect.x / locScaleFactor, rect.y / locScaleFactor,
- rect.width / locScaleFactor, rect.height / locScaleFactor);
- var z = pos.x + pos.y * this._layerSize.width;
-
- var tile = this._reusedTileWithRect(rect);
- this._setupTileSprite(tile, pos, gid);
-
- // get atlas index
- var indexForZ = this._atlasIndexForExistantZ(z);
- tile.setAtlasIndex(indexForZ);
- tile.setDirty(true);
- tile.updateTransform();
- this._tiles[z] = gid;
-
- return tile;
- },
-
- //The layer recognizes some special properties, like cc_vertez
- _parseInternalProperties:function () {
- // if cc_vertex=automatic, then tiles will be rendered using vertexz
- var vertexz = this.getProperty("cc_vertexz");
- if (vertexz) {
- if (vertexz == "automatic") {
- this._useAutomaticVertexZ = true;
- var alphaFuncVal = this.getProperty("cc_alpha_func");
- var alphaFuncValue = 0;
- if (alphaFuncVal)
- alphaFuncValue = parseFloat(alphaFuncVal);
-
- if (cc.renderContextType === cc.WEBGL) {
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLORALPHATEST));
- var alphaValueLocation = cc.renderContext.getUniformLocation(this.getShaderProgram().getProgram(), cc.UNIFORM_ALPHA_TEST_VALUE_S);
- // NOTE: alpha test shader is hard-coded to use the equivalent of a glAlphaFunc(GL_GREATER) comparison
- this.getShaderProgram().use();
- this.getShaderProgram().setUniformLocationWith1f(alphaValueLocation, alphaFuncValue);
- }
- } else
- this._vertexZvalue = parseInt(vertexz, 10);
- }
- },
-
- _setupTileSprite:function (sprite, pos, gid) {
- var z = pos.x + pos.y * this._layerSize.width;
- sprite.setPosition(this.getPositionAt(pos));
- if (cc.renderContextType === cc.WEBGL)
- sprite.setVertexZ(this._vertexZForPos(pos));
- else
- sprite.setTag(z);
-
- sprite.setAnchorPoint(cc.PointZero());
- sprite.setOpacity(this._opacity);
- if (cc.renderContextType === cc.WEBGL) {
- sprite.setRotation(0.0);
- }
-
- sprite.setFlippedX(false);
- sprite.setFlippedY(false);
-
- // Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles.
- if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) {
- // put the anchor in the middle for ease of rotation.
- sprite.setAnchorPoint(cc.p(0.5, 0.5));
- sprite.setPosition(this.getPositionAt(pos).x + sprite.getContentSize().height / 2,
- this.getPositionAt(pos).y + sprite.getContentSize().width / 2);
-
- var flag = (gid & (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG) >>> 0) >>> 0;
- // handle the 4 diagonally flipped states.
- if (flag == cc.TMX_TILE_HORIZONTAL_FLAG)
- sprite.setRotation(90);
- else if (flag == cc.TMX_TILE_VERTICAL_FLAG)
- sprite.setRotation(270);
- else if (flag == (cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) {
- sprite.setRotation(90);
- sprite.setFlippedX(true);
- } else {
- sprite.setRotation(270);
- sprite.setFlippedX(true);
- }
- } else {
- if ((gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0)
- sprite.setFlippedX(true);
-
- if ((gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0)
- sprite.setFlippedY(true);
- }
- },
-
- _reusedTileWithRect:function (rect) {
- if(cc.renderContextType === cc.WEBGL){
- if (!this._reusedTile) {
- this._reusedTile = new cc.Sprite();
- this._reusedTile.initWithTexture(this.getTexture(), rect, false);
- this._reusedTile.setBatchNode(this);
- } else {
- // XXX HACK: Needed because if "batch node" is nil,
- // then the Sprite'squad will be reset
- this._reusedTile.setBatchNode(null);
-
- // Re-init the sprite
- this._reusedTile.setTextureRect(rect, false, rect.size);
-
- // restore the batch node
- this._reusedTile.setBatchNode(this);
- }
- } else {
- this._reusedTile = new cc.Sprite();
- this._reusedTile.initWithTexture(this._textureForCanvas, rect, false);
- this._reusedTile.setBatchNode(this);
- this._reusedTile.setParent(this);
- }
- return this._reusedTile;
- },
-
- _vertexZForPos:function (pos) {
- var ret = 0;
- var maxVal = 0;
- if (this._useAutomaticVertexZ) {
- switch (this._layerOrientation) {
- case cc.TMX_ORIENTATION_ISO:
- maxVal = this._layerSize.width + this._layerSize.height;
- ret = -(maxVal - (pos.x + pos.y));
- break;
- case cc.TMX_ORIENTATION_ORTHO:
- ret = -(this._layerSize.height - pos.y);
- break;
- case cc.TMX_ORIENTATION_HEX:
- cc.Assert(0, "TMX Hexa zOrder not supported");
- break;
- default:
- cc.Assert(0, "TMX invalid value");
- break;
- }
- } else
- ret = this._vertexZvalue;
- return ret;
- },
-
- _atlasIndexForExistantZ:function (z) {
- var item;
- if (this._atlasIndexArray) {
- var locAtlasIndexArray = this._atlasIndexArray;
- for (var i = 0, len = locAtlasIndexArray.length; i < len; i++) {
- item = locAtlasIndexArray[i];
- if (item == z)
- break;
- }
- }
- cc.Assert(item != null, "TMX atlas index not found. Shall not happen");
- return i;
- },
-
- _atlasIndexForNewZ:function (z) {
- var locAtlasIndexArray = this._atlasIndexArray;
- for (var i = 0, len = locAtlasIndexArray.length; i < len; i++) {
- var val = locAtlasIndexArray[i];
- if (z < val)
- break;
- }
- return i;
- }
-});
-
-if(cc.Browser.supportWebGL){
- cc.TMXLayer.prototype.draw = cc.SpriteBatchNode.prototype.draw;
-}else{
- cc.TMXLayer.prototype.draw = cc.TMXLayer.prototype._drawForCanvas;
-}
-
-/**
- * Creates a cc.TMXLayer with an tile set info, a layer info and a map info
- * @param {cc.TMXTilesetInfo} tilesetInfo
- * @param {cc.TMXLayerInfo} layerInfo
- * @param {cc.TMXMapInfo} mapInfo
- * @return {cc.TMXLayer|Null}
- */
-cc.TMXLayer.create = function (tilesetInfo, layerInfo, mapInfo) {
- var ret = new cc.TMXLayer();
- if (ret.initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo))
- return ret;
- return null;
-};
diff --git a/cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js b/cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js
deleted file mode 100644
index 969c85a693..0000000000
--- a/cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js
+++ /dev/null
@@ -1,286 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * cc.TileMapAtlas is a subclass of cc.AtlasNode.
- *
- * It knows how to render a map based of tiles.
- * The tiles must be in a .PNG format while the map must be a .TGA file.
- *
- * For more information regarding the format, please see this post:
- * http://www.cocos2d-iphone.org/archives/27
- *
- * All features from cc.AtlasNode are valid in cc.TileMapAtlas
- *
- * IMPORTANT:
- * This class is deprecated. It is maintained for compatibility reasons only.
- * You SHOULD not use this class.
- * Instead, use the newer TMX file format: cc.TMXTiledMap
- * @class
- * @extends cc.AtlasNode
- */
-cc.TileMapAtlas = cc.AtlasNode.extend(/** @lends cc.TileMapAtlas# */{
- _TGAInfo:null,
- indices:null,
- //numbers of tiles to render
- _itemsToRender:0,
- //x,y to altas dictionary
- _posToAtlasIndex:null,
-
- /**
- * @return {cc.ImageTGA}
- */
- getTGAInfo:function () {
- return this._TGAInfo;
- },
-
- /**
- * @param {cc.ImageTGA} Var
- */
- setTGAInfo:function (Var) {
- this._TGAInfo = Var;
- },
-
- /**
- * Initializes a cc.TileMap with a tile file (atlas) with a map file and the width and height of each tile in points.
- * The file will be loaded using the TextureMgr.
- * @param {String} tile
- * @param {String} mapFile
- * @param {Number} tileWidth
- * @param {Number} tileHeight
- * @return {Boolean}
- * @example
- * //example
- * var tmpAtlas = new cc.TileMapAtlas();
- * tmpAtlas.initWithTileFile("hello.png", "hello.tga", 16, 16);
- */
- initWithTileFile:function (tile, mapFile, tileWidth, tileHeight) {
- this._loadTGAfile(mapFile);
- this._calculateItemsToRender();
- if (cc.AtlasNode.prototype.initWithTileFile.call(this, tile, tileWidth, tileHeight, this._itemsToRender)) {
- this._color = cc.white();
- this._posToAtlasIndex = {};
- this._updateAtlasValues();
- this.setContentSize(cc.size((this._TGAInfo.width * this._itemWidth),
- (this._TGAInfo.height * this._itemHeight)));
- return true;
- }
- return false;
- },
-
- /**
- * Returns a tile from position x,y.
- * For the moment only channel R is used.
- * @param {cc.Point} position
- * @return {cc.Color3B}
- */
- getTileAt:function (position) {
- cc.Assert(this._TGAInfo != null, "tgaInfo must not be nil");
- cc.Assert(position.x < this._TGAInfo.width, "Invalid position.x");
- cc.Assert(position.y < this._TGAInfo.height, "Invalid position.y");
-
- var colorPos = 0|(position.x * 3 + position.y * this._TGAInfo.width * 3);
- var locTGAImageData = this._TGAInfo.imageData;
- return new cc.Color3B(locTGAImageData[colorPos], locTGAImageData[colorPos + 1], locTGAImageData[colorPos + 2]);
- },
-
- /**
- * Sets a tile at position x,y.
- * For the moment only channel R is used
- * @param {cc.Color3B} tile
- * @param {cc.Point} position
- */
- setTile:function (tile, position) {
- cc.Assert(this._TGAInfo != null, "tgaInfo must not be nil");
- cc.Assert(this._posToAtlasIndex != null, "posToAtlasIndex must not be nil");
- cc.Assert(position.x < this._TGAInfo.width, "Invalid position.x");
- cc.Assert(position.y < this._TGAInfo.height, "Invalid position.x");
- cc.Assert(tile.r != 0, "R component must be non 0");
-
- var colorPos = 0 | (position.x * 3 + position.y * this._TGAInfo.width * 3);
- if (this._TGAInfo.imageData[colorPos] == 0)
- cc.log("cocos2d: Value.r must be non 0.");
- else {
- this._TGAInfo.imageData[colorPos] = tile.r;
- this._TGAInfo.imageData[colorPos + 1] = tile.g;
- this._TGAInfo.imageData[colorPos + 2] = tile.b;
-
- var num = this._posToAtlasIndex[position.x + "_" + position.y];
- this._updateAtlasValueAt(position, tile, num);
- }
- },
-
- /**
- * Dealloc the map from memory
- */
- releaseMap:function () {
- if (this._TGAInfo) {
- cc.tgaDestroy(this._TGAInfo);
- }
- this._TGAInfo = null;
- },
-
- _loadTGAfile:function (file) {
- cc.Assert(file != null, "file must be non-nil");
-
- // //Find the path of the file
- // NSBundle *mainBndl = [cc.Director sharedDirector].loadingBundle;
- // cc.String *resourcePath = [mainBndl resourcePath];
- // cc.String * path = [resourcePath stringByAppendingPathComponent:file];
-
- this._TGAInfo = cc.tgaLoad(cc.FileUtils.getInstance().fullPathForFilename(file));
- if (this._TGAInfo.status != cc.TGA_OK) {
- cc.Assert(0, "TileMapAtlasLoadTGA : TileMapAtas cannot load TGA file");
- }
- },
-
- _calculateItemsToRender:function () {
- cc.Assert(this._TGAInfo != null, "tgaInfo must be non-nil");
-
- this._itemsToRender = 0;
- var locWidth = this._TGAInfo.width, locHeight = this._TGAInfo.height, locImageData = this._TGAInfo.imageData;
- for (var x = 0; x < locWidth; x++) {
- for (var y = 0; y < locHeight; y++) {
- if (locImageData[x * 3 + y * locWidth * 3])
- ++this._itemsToRender;
- }
- }
- },
-
- /**
- * @param {cc.Point|cc.GridSize} pos
- * @param {cc.Color3B} value
- * @param {Number} index
- * @private
- */
- _updateAtlasValueAt:function (pos, value, index) {
- var locTextureAtlas = this._textureAtlas;
- cc.Assert( index >= 0 && index < locTextureAtlas.getCapacity(), "updateAtlasValueAt: Invalid index");
- var quad = locTextureAtlas.getQuads()[index];
-
- var x = pos.x;
- var y = pos.y;
- var row = (value.r % this._itemsPerRow);
- var col = (value.r / this._itemsPerRow);
-
- var textureWide = locTextureAtlas.getTexture().getPixelsWide();
- var textureHigh = locTextureAtlas.getTexture().getPixelsHigh();
-
- var locItemWidth = this._itemWidth;
- var locItemHeight = this._itemHeight;
- var itemWidthInPixels = locItemWidth * cc.CONTENT_SCALE_FACTOR();
- var itemHeightInPixels = locItemHeight * cc.CONTENT_SCALE_FACTOR();
-
- var left, right, top, bottom;
- if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) {
- left = (2 * row * itemWidthInPixels + 1) / (2 * textureWide);
- right = left + (itemWidthInPixels * 2 - 2) / (2 * textureWide);
- top = (2 * col * itemHeightInPixels + 1) / (2 * textureHigh);
- bottom = top + (itemHeightInPixels * 2 - 2) / (2 * textureHigh);
- } else {
- left = (row * itemWidthInPixels) / textureWide;
- right = left + itemWidthInPixels / textureWide;
- top = (col * itemHeightInPixels) / textureHigh;
- bottom = top + itemHeightInPixels / textureHigh;
- }
-
- quad.tl.texCoords.u = left;
- quad.tl.texCoords.v = top;
- quad.tr.texCoords.u = right;
- quad.tr.texCoords.v = top;
- quad.bl.texCoords.u = left;
- quad.bl.texCoords.v = bottom;
- quad.br.texCoords.u = right;
- quad.br.texCoords.v = bottom;
-
- quad.bl.vertices.x = (x * locItemWidth);
- quad.bl.vertices.y = (y * locItemHeight);
- quad.bl.vertices.z = 0.0;
- quad.br.vertices.x = (x * locItemWidth + locItemWidth);
- quad.br.vertices.y = (y * locItemHeight);
- quad.br.vertices.z = 0.0;
- quad.tl.vertices.x = (x * locItemWidth);
- quad.tl.vertices.y = (y * locItemHeight + locItemHeight);
- quad.tl.vertices.z = 0.0;
- quad.tr.vertices.x = (x * locItemWidth + locItemWidth);
- quad.tr.vertices.y = (y * locItemHeight + locItemHeight);
- quad.tr.vertices.z = 0.0;
-
- var locColor = this._displayedColor;
- var color = {r: locColor.r, g: locColor.g, b: locColor.b, a: this._displayedOpacity};
- quad.tr.colors = color;
- quad.tl.colors = color;
- quad.br.colors = color;
- quad.bl.colors = color;
-
- locTextureAtlas.setDirty(true);
- var totalQuads = locTextureAtlas.getTotalQuads();
- if (index + 1 > totalQuads)
- locTextureAtlas.increaseTotalQuadsWith(index + 1 - totalQuads);
- },
-
- _updateAtlasValues:function () {
- cc.Assert(this._TGAInfo != null, "tgaInfo must be non-nil");
-
- var total = 0;
- var locTGAInfo = this._TGAInfo;
- var locTGAInfoWidth = locTGAInfo.width, locTGAInfoHeight = locTGAInfo.height, locItemsToRender = this._itemsToRender;
- for (var x = 0; x < locTGAInfoWidth; x++) {
- for (var y = 0; y < locTGAInfoHeight; y++) {
- if (total < locItemsToRender) {
- var colorPos = x * 3 + y * locTGAInfoWidth * 3;
- var value = new cc.Color3B(locTGAInfo.imageData[colorPos], locTGAInfo.imageData[colorPos + 1], locTGAInfo.imageData[colorPos + 2]);
- if (value.r != 0) {
- this._updateAtlasValueAt(cc.p(x, y), value, total);
- this._posToAtlasIndex[x + "_" + y] = total;
- total++;
- }
- }
- }
- }
- }
-});
-
-/**
- * Creates a cc.TileMap with a tile file (atlas) with a map file and the width and height of each tile in points.
- * The tile file will be loaded using the TextureMgr.
- * @param {String} tile
- * @param {String} mapFile
- * @param {Number} tileWidth
- * @param {Number} tileHeight
- * @return {Boolean|Null}
- * @example
- * //example
- * var tmpAtlas = new cc.TileMapAtlas();
- * tmpAtlas.initWithTileFile("hello.png", "hello.tga", 16, 16);
- */
-cc.TileMapAtlas.create = function (tile, mapFile, tileWidth, tileHeight) {
- var ret = new cc.TileMapAtlas();
- if (ret.initWithTileFile(tile, mapFile, tileWidth, tileHeight)) {
- return ret;
- }
- return null;
-};
diff --git a/cocos2d/support/CCTGAlib.js b/cocos2d/tilemap/CCTGAlib.js
similarity index 81%
rename from cocos2d/support/CCTGAlib.js
rename to cocos2d/tilemap/CCTGAlib.js
index 12bdd1e579..76bd69bcf7 100644
--- a/cocos2d/support/CCTGAlib.js
+++ b/cocos2d/tilemap/CCTGAlib.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2013 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -80,7 +82,7 @@ cc.ImageTGA = function (status, type, pixelDepth, width, height, imageData, flip
};
/**
- * load the image header field from stream. We only keep those that matter!
+ * load the image header field from stream. We only keep those that matter!
* @param {Array} buffer
* @param {Number} bufSize
* @param {cc.ImageTGA} psInfo
@@ -116,7 +118,7 @@ cc.tgaLoadHeader = function (buffer, bufSize, psInfo) {
};
/**
- * loads the image pixels. You shouldn't call this function directly
+ * loads the image pixels. You shouldn't call this function directly.
* @param {Array} buffer
* @param {Number} bufSize
* @param {cc.ImageTGA} psInfo
@@ -148,60 +150,6 @@ cc.tgaLoadImageData = function (buffer, bufSize, psInfo) {
return true;
};
-/**
- * this is the function to call when we want to load an image
- * @param filename
- * @return {cc.ImageTGA}
- */
-cc.tgaLoad = function (filename) {
- var buffer = cc.FileUtils.getInstance().getFileData(filename, "rb");
- var size = buffer.length;
-
- if (buffer == null)
- return null;
-
- var info = new cc.ImageTGA();
- // get the file header info
- if (!cc.tgaLoadHeader(buffer, size, info)) {
- info.status = cc.TGA_ERROR_MEMORY;
- return info;
- }
-
- // check if the image is color indexed
- if (info.type === 1) {
- info.status = cc.TGA_ERROR_INDEXED_COLOR;
- return info;
- }
-
- // check for other types (compressed images)
- if ((info.type != 2) && (info.type != 3) && (info.type != 10)) {
- info.status = cc.TGA_ERROR_COMPRESSED_FILE;
- return info;
- }
-
- var bLoadImage = false;
- // finally load the image pixels
- if (info.type == 10)
- bLoadImage = cc.tgaLoadRLEImageData(buffer, size, info);
- else
- bLoadImage = cc.tgaLoadImageData(buffer, size, info);
-
- // check for errors when reading the pixels
- if (!bLoadImage) {
- info.status = cc.TGA_ERROR_READING_FILE;
- return info;
- }
-
- info.status = cc.TGA_OK;
- if (info.flipped) {
- cc.tgaFlipImage(info);
- if (info.flipped)
- info.status = cc.TGA_ERROR_MEMORY;
- }
- buffer = null;
- return info;
-};
-
/**
* converts RGB to grayscale
* @param {cc.ImageTGA} psInfo
@@ -244,8 +192,15 @@ cc.tgaDestroy = function (psInfo) {
psInfo = null;
};
+/**
+ * Load RLE image data
+ * @param buffer
+ * @param bufSize
+ * @param psInfo
+ * @returns {boolean}
+ */
cc.tgaLoadRLEImageData = function (buffer, bufSize, psInfo) {
- var mode, total, i, index = 0 , skip = 0, flag = 0;
+ var mode, total, i, index = 0, skip = 0, flag = 0;
var aux = [], runlength = 0;
var step = 18; // . size_t step = (sizeof(unsigned char) + sizeof(signed short)) * 6;
@@ -257,10 +212,10 @@ cc.tgaLoadRLEImageData = function (buffer, bufSize, psInfo) {
for (i = 0; i < total; i++) {
// if we have a run length pending, run it
- if (runlength != 0) {
+ if (runlength !== 0) {
// we do, update the run length count
runlength--;
- skip = (flag != 0);
+ skip = (flag !== 0);
} else {
// otherwise, read in the run length token
if (step + 1 > bufSize)
@@ -302,6 +257,10 @@ cc.tgaLoadRLEImageData = function (buffer, bufSize, psInfo) {
return true;
};
+/**
+ * ImageTGA Flip
+ * @param {cc.ImageTGA} psInfo
+ */
cc.tgaFlipImage = function (psInfo) {
// mode equal the number of components for each pixel
var mode = psInfo.pixelDepth / 8;
@@ -327,30 +286,49 @@ cc.__setDataToArray = function (sourceData, destArray, startIndex) {
destArray[startIndex + i] = sourceData[i];
};
-
+/**
+ * Binary Stream Reader
+ *
+ * @class
+ * @param binaryData
+ */
cc.BinaryStreamReader = cc.Class.extend({
- _binaryData:null,
- _offset:0,
-
- ctor:function (binaryData) {
+ _binaryData: null,
+ _offset: 0,
+
+ /**
+ * The cc.BinaryStreamReader's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.BinaryStreamReader()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param binaryData
+ */
+ ctor: function (binaryData) {
this._binaryData = binaryData;
},
- setBinaryData:function (binaryData) {
+ /**
+ * Set the binaryData.
+ * @param binaryData
+ */
+ setBinaryData: function (binaryData) {
this._binaryData = binaryData;
this._offset = 0;
},
- getBinaryData:function () {
+ /**
+ * Gets the binaryData.
+ * @returns {Object}
+ */
+ getBinaryData: function () {
return this._binaryData;
},
- _checkSize:function (neededBits) {
+ _checkSize: function (neededBits) {
if (!(this._offset + Math.ceil(neededBits / 8) < this._data.length))
throw new Error("Index out of bound");
},
- _decodeFloat:function (precisionBits, exponentBits) {
+ _decodeFloat: function (precisionBits, exponentBits) {
var length = precisionBits + exponentBits + 1;
var size = length >> 3;
this._checkSize(length);
@@ -374,16 +352,16 @@ cc.BinaryStreamReader = cc.Class.extend({
this._offset += size;
- return exponent == (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity
+ return exponent === (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity
: (1 + signal * -2) * (exponent || significand ? !exponent ? Math.pow(2, -bias + 1) * significand
: Math.pow(2, exponent - bias) * (1 + significand) : 0);
},
- _readByte:function (i, size) {
+ _readByte: function (i, size) {
return this._data[this._offset + size - i - 1];
},
- _decodeInt:function (bits, signed) {
+ _decodeInt: function (bits, signed) {
var x = this._readBits(0, bits, bits / 8), max = Math.pow(2, bits);
var result = signed && x >= max / 2 ? x - max : x;
@@ -391,12 +369,13 @@ cc.BinaryStreamReader = cc.Class.extend({
return result;
},
- _shl:function (a, b) {
- for (++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1){};
+ _shl: function (a, b) {
+ for (++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) === 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1) {
+ }
return a;
},
- _readBits:function (start, length, size) {
+ _readBits: function (start, length, size) {
var offsetLeft = (start + length) % 8;
var offsetRight = start % 8;
var curByte = size - (start >> 3) - 1;
@@ -414,33 +393,33 @@ cc.BinaryStreamReader = cc.Class.extend({
return sum;
},
- readInteger:function () {
+ readInteger: function () {
return this._decodeInt(32, true);
},
- readUnsignedInteger:function () {
+ readUnsignedInteger: function () {
return this._decodeInt(32, false);
},
- readSingle:function () {
+ readSingle: function () {
return this._decodeFloat(23, 8);
},
- readShort:function () {
+ readShort: function () {
return this._decodeInt(16, true);
},
- readUnsignedShort:function () {
+ readUnsignedShort: function () {
return this._decodeInt(16, false);
},
- readByte:function () {
+ readByte: function () {
var readByte = this._data[this._offset];
this._offset += 1;
return readByte;
},
- readData:function (start, end) {
+ readData: function (start, end) {
if (this._binaryData instanceof Array) {
return this._binaryData.slice(start, end);
} else {
@@ -449,11 +428,11 @@ cc.BinaryStreamReader = cc.Class.extend({
}
},
- setOffset:function (offset) {
+ setOffset: function (offset) {
this._offset = offset;
},
- getOffset:function () {
+ getOffset: function () {
return this._offset;
}
});
diff --git a/cocos2d/tilemap/CCTMXLayer.js b/cocos2d/tilemap/CCTMXLayer.js
new file mode 100644
index 0000000000..e78c8d082f
--- /dev/null
+++ b/cocos2d/tilemap/CCTMXLayer.js
@@ -0,0 +1,803 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * cc.TMXLayer represents the TMX layer.
+ *
+ * It is a subclass of cc.SpriteBatchNode. By default the tiles are rendered using a cc.TextureAtlas.
+ * If you modify a tile on runtime, then, that tile will become a cc.Sprite, otherwise no cc.Sprite objects are created.
+ * The benefits of using cc.Sprite objects as tiles are:
+ * - tiles (cc.Sprite) can be rotated/scaled/moved with a nice API
+ *
+ * If the layer contains a property named "cc.vertexz" with an integer (in can be positive or negative),
+ * then all the tiles belonging to the layer will use that value as their OpenGL vertex Z for depth.
+ *
+ * On the other hand, if the "cc.vertexz" property has the "automatic" value, then the tiles will use an automatic vertex Z value.
+ * Also before drawing the tiles, GL_ALPHA_TEST will be enabled, and disabled after drawing them. The used alpha func will be:
+ *
+ * glAlphaFunc( GL_GREATER, value )
+ *
+ * "value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer.
+ * The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a different value, like 0.5.
+ * @class
+ * @extends cc.SpriteBatchNode
+ *
+ * @property {Array} tiles - Tiles for layer
+ * @property {cc.TMXTilesetInfo} tileset - Tileset for layer
+ * @property {Number} layerOrientation - Layer orientation
+ * @property {Array} properties - Properties from the layer. They can be added using tilemap editors
+ * @property {String} layerName - Name of the layer
+ * @property {Number} layerWidth - Width of the layer
+ * @property {Number} layerHeight - Height of the layer
+ * @property {Number} tileWidth - Width of a tile
+ * @property {Number} tileHeight - Height of a tile
+ */
+cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{
+ tiles: null,
+ tileset: null,
+ layerOrientation: null,
+ properties: null,
+ layerName: "",
+
+ _textures: null,
+ _texGrids: null,
+ _spriteTiles: null,
+
+ //size of the layer in tiles
+ _layerSize: null,
+ _mapTileSize: null,
+ //TMX Layer supports opacity
+ _opacity: 255,
+ _minGID: null,
+ _maxGID: null,
+ //Only used when vertexZ is used
+ _vertexZvalue: null,
+ _useAutomaticVertexZ: null,
+ //used for optimization
+ _reusedTile: null,
+ _atlasIndexArray: null,
+ //used for retina display
+ _contentScaleFactor: null,
+
+ _className:"TMXLayer",
+
+ /**
+ * Creates a cc.TMXLayer with an tile set info, a layer info and a map info
+ * Constructor of cc.TMXLayer
+ * @param {cc.TMXTilesetInfo} tilesetInfo
+ * @param {cc.TMXLayerInfo} layerInfo
+ * @param {cc.TMXMapInfo} mapInfo
+ */
+ ctor:function (tilesetInfo, layerInfo, mapInfo) {
+ cc.SpriteBatchNode.prototype.ctor.call(this);
+ this._descendants = [];
+
+ this._layerSize = cc.size(0, 0);
+ this._mapTileSize = cc.size(0, 0);
+ this._spriteTiles = {};
+
+ if(mapInfo !== undefined)
+ this.initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo);
+ },
+
+ _createRenderCmd: function(){
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.TMXLayer.CanvasRenderCmd(this);
+ else
+ return new cc.TMXLayer.WebGLRenderCmd(this);
+ },
+
+ _fillTextureGrids: function (tileset, texId) {
+ var tex = this._textures[texId];
+ if (!tex.isLoaded()) {
+ tex.addEventListener("load", function () {
+ this._fillTextureGrids(tileset, texId);
+ }, this);
+ return;
+ }
+ if (!tileset.imageSize.width || !tileset.imageSize.height) {
+ tileset.imageSize.width = tex.width;
+ tileset.imageSize.height = tex.height;
+ }
+ var tw = tileset._tileSize.width,
+ th = tileset._tileSize.height,
+ imageW = tex._contentSize.width,
+ imageH = tex._contentSize.height,
+ spacing = tileset.spacing,
+ margin = tileset.margin,
+
+ cols = Math.floor((imageW - margin*2 + spacing) / (tw + spacing)),
+ rows = Math.floor((imageH - margin*2 + spacing) / (th + spacing)),
+ count = rows * cols,
+
+ gid = tileset.firstGid,
+ maxGid = tileset.firstGid + count,
+ grids = this._texGrids,
+ grid = null,
+ override = grids[gid] ? true : false,
+
+ t, l, r, b;
+
+ for (; gid < maxGid; ++gid) {
+ // Avoid overlapping
+ if (override && !grids[gid]) {
+ override = false;
+ }
+ if (!override && grids[gid]) {
+ break;
+ }
+
+ grid = {
+ texId: texId,
+ x: 0, y: 0, width: tw, height: th,
+ t: 0, l: 0, r: 0, b: 0
+ };
+ tileset.rectForGID(gid, grid);
+ grid.t = grid.y / imageH;
+ grid.l = grid.x / imageW;
+ grid.r = (grid.x + grid.width) / imageW;
+ grid.b = (grid.y + grid.height) / imageH;
+ grids[gid] = grid;
+ }
+ },
+
+ /**
+ * Initializes a cc.TMXLayer with a tileset info, a layer info and a map info
+ * @param {cc.TMXTilesetInfo} tilesetInfo
+ * @param {cc.TMXLayerInfo} layerInfo
+ * @param {cc.TMXMapInfo} mapInfo
+ * @return {Boolean}
+ */
+ initWithTilesetInfo:function (tilesetInfo, layerInfo, mapInfo) {
+ var size = layerInfo._layerSize;
+ var totalNumberOfTiles = parseInt(size.width * size.height);
+
+ // layerInfo
+ this.layerName = layerInfo.name;
+ this.tiles = layerInfo._tiles;
+ this.properties = layerInfo.properties;
+ this._layerSize = size;
+ this._minGID = layerInfo._minGID;
+ this._maxGID = layerInfo._maxGID;
+ this._opacity = layerInfo._opacity;
+
+ // tilesetInfo
+ this.tileset = tilesetInfo;
+
+ // mapInfo
+ this.layerOrientation = mapInfo.orientation;
+ this._mapTileSize = mapInfo.getTileSize();
+
+ var tilesets = mapInfo._tilesets;
+ if (tilesets) {
+ this._textures = [];
+ this._texGrids = [];
+ var i, len = tilesets.length, tileset, tex;
+ for (i = 0; i < len; ++i) {
+ tileset = tilesets[i];
+ tex = cc.textureCache.addImage(tileset.sourceImage);
+ this._textures.push(tex);
+ this._fillTextureGrids(tileset, i);
+ if (tileset === tilesetInfo) {
+ this._texture = tex;
+ }
+ }
+ }
+
+ // offset (after layer orientation is set);
+ var offset = this._calculateLayerOffset(layerInfo.offset);
+ this.setPosition(cc.pointPixelsToPoints(offset));
+
+ // Parse cocos2d properties
+ this._parseInternalProperties();
+
+ this.setContentSize(cc.sizePixelsToPoints(cc.size(this._layerSize.width * this._mapTileSize.width,
+ this._layerSize.height * this._mapTileSize.height)));
+ this._useAutomaticVertexZ = false;
+ this._vertexZvalue = 0;
+ return true;
+ },
+
+ /**
+ * Gets layer size.
+ * @return {cc.Size}
+ */
+ getLayerSize:function () {
+ return cc.size(this._layerSize.width, this._layerSize.height);
+ },
+
+ /**
+ * Set layer size
+ * @param {cc.Size} Var
+ */
+ setLayerSize:function (Var) {
+ this._layerSize.width = Var.width;
+ this._layerSize.height = Var.height;
+ },
+
+ _getLayerWidth: function () {
+ return this._layerSize.width;
+ },
+ _setLayerWidth: function (width) {
+ this._layerSize.width = width;
+ },
+ _getLayerHeight: function () {
+ return this._layerSize.height;
+ },
+ _setLayerHeight: function (height) {
+ this._layerSize.height = height;
+ },
+
+ /**
+ * Size of the map's tile (could be different from the tile's size)
+ * @return {cc.Size}
+ */
+ getMapTileSize:function () {
+ return cc.size(this._mapTileSize.width,this._mapTileSize.height);
+ },
+
+ /**
+ * Set the map tile size.
+ * @param {cc.Size} Var
+ */
+ setMapTileSize:function (Var) {
+ this._mapTileSize.width = Var.width;
+ this._mapTileSize.height = Var.height;
+ },
+
+ _getTileWidth: function () {
+ return this._mapTileSize.width;
+ },
+ _setTileWidth: function (width) {
+ this._mapTileSize.width = width;
+ },
+ _getTileHeight: function () {
+ return this._mapTileSize.height;
+ },
+ _setTileHeight: function (height) {
+ this._mapTileSize.height = height;
+ },
+
+ /**
+ * Pointer to the map of tiles
+ * @return {Array}
+ */
+ getTiles:function () {
+ return this.tiles;
+ },
+
+ /**
+ * Pointer to the map of tiles
+ * @param {Array} Var
+ */
+ setTiles:function (Var) {
+ this.tiles = Var;
+ },
+
+ /**
+ * Tile set information for the layer
+ * @return {cc.TMXTilesetInfo}
+ */
+ getTileset:function () {
+ return this.tileset;
+ },
+
+ /**
+ * Tile set information for the layer
+ * @param {cc.TMXTilesetInfo} Var
+ */
+ setTileset:function (Var) {
+ this.tileset = Var;
+ },
+
+ /**
+ * Layer orientation, which is the same as the map orientation
+ * @return {Number}
+ */
+ getLayerOrientation:function () {
+ return this.layerOrientation;
+ },
+
+ /**
+ * Layer orientation, which is the same as the map orientation
+ * @param {Number} Var
+ */
+ setLayerOrientation:function (Var) {
+ this.layerOrientation = Var;
+ },
+
+ /**
+ * properties from the layer. They can be added using Tiled
+ * @return {Array}
+ */
+ getProperties:function () {
+ return this.properties;
+ },
+
+ /**
+ * properties from the layer. They can be added using Tiled
+ * @param {Array} Var
+ */
+ setProperties:function (Var) {
+ this.properties = Var;
+ },
+
+ /**
+ * Return the value for the specific property name
+ * @param {String} propertyName
+ * @return {*}
+ */
+ getProperty:function (propertyName) {
+ return this.properties[propertyName];
+ },
+
+ /**
+ * Gets the layer name
+ * @return {String}
+ */
+ getLayerName:function () {
+ return this.layerName;
+ },
+
+ /**
+ * Set the layer name
+ * @param {String} layerName
+ */
+ setLayerName:function (layerName) {
+ this.layerName = layerName;
+ },
+
+ /**
+ * Dealloc the map that contains the tile position from memory.
+ * Unless you want to know at runtime the tiles positions, you can safely call this method.
+ * If you are going to call layer.getTileGIDAt() then, don't release the map
+ */
+ releaseMap:function () {
+ this._spriteTiles = {};
+ },
+
+ /**
+ * Returns the tile (cc.Sprite) at a given a tile coordinate.
+ * The returned cc.Sprite will be already added to the cc.TMXLayer. Don't add it again.
+ * The cc.Sprite can be treated like any other cc.Sprite: rotated, scaled, translated, opacity, color, etc.
+ * You can remove either by calling:
+ * - layer.removeChild(sprite, cleanup);
+ * - or layer.removeTileAt(ccp(x,y));
+ * @param {cc.Point|Number} pos or x
+ * @param {Number} [y]
+ * @return {cc.Sprite}
+ */
+ getTileAt: function (pos, y) {
+ if (pos === undefined) {
+ throw new Error("cc.TMXLayer.getTileAt(): pos should be non-null");
+ }
+ var x = pos;
+ if (y === undefined) {
+ x = pos.x;
+ y = pos.y;
+ }
+ if (x >= this._layerSize.width || y >= this._layerSize.height || x < 0 || y < 0) {
+ throw new Error("cc.TMXLayer.getTileAt(): invalid position");
+ }
+ if (!this.tiles) {
+ cc.log("cc.TMXLayer.getTileAt(): TMXLayer: the tiles map has been released");
+ return null;
+ }
+
+ var tile = null, gid = this.getTileGIDAt(x, y);
+
+ // if GID == 0, then no tile is present
+ if (gid === 0) {
+ return tile;
+ }
+
+ var z = 0 | (x + y * this._layerSize.width);
+ tile = this._spriteTiles[z];
+ // tile not created yet. create it
+ if (!tile) {
+ var rect = this._texGrids[gid];
+ var tex = this._textures[rect.texId];
+ rect = cc.rectPixelsToPoints(rect);
+
+ tile = new cc.Sprite(tex, rect);
+ tile.setPosition(this.getPositionAt(x, y));
+ var vertexZ = this._vertexZForPos(x, y);
+ tile.setVertexZ(vertexZ);
+ tile.setAnchorPoint(0, 0);
+ tile.setOpacity(this._opacity);
+
+ this.addChild(tile, vertexZ, z);
+ }
+ return tile;
+ },
+
+ /**
+ * Returns the tile gid at a given tile coordinate.
+ * if it returns 0, it means that the tile is empty.
+ * This method requires the the tile map has not been previously released (eg. don't call layer.releaseMap())
+ * @param {cc.Point|Number} pos or x
+ * @param {Number} [y]
+ * @return {Number}
+ */
+ getTileGIDAt:function (pos, y) {
+ if (pos === undefined) {
+ throw new Error("cc.TMXLayer.getTileGIDAt(): pos should be non-null");
+ }
+ var x = pos;
+ if (y === undefined) {
+ x = pos.x;
+ y = pos.y;
+ }
+ if (x >= this._layerSize.width || y >= this._layerSize.height || x < 0 || y < 0) {
+ throw new Error("cc.TMXLayer.getTileGIDAt(): invalid position");
+ }
+ if (!this.tiles) {
+ cc.log("cc.TMXLayer.getTileGIDAt(): TMXLayer: the tiles map has been released");
+ return null;
+ }
+
+ var idx = 0 | (x + y * this._layerSize.width);
+ // Bits on the far end of the 32-bit global tile ID are used for tile flags
+ var tile = this.tiles[idx];
+
+ return (tile & cc.TMX_TILE_FLIPPED_MASK) >>> 0;
+ },
+ // XXX: deprecated
+ // tileGIDAt:getTileGIDAt,
+
+ /**
+ * Sets the tile gid (gid = tile global id) at a given tile coordinate.
+ * The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor . Tileset Mgr +1.
+ * If a tile is already placed at that position, then it will be removed.
+ * @param {Number} gid
+ * @param {cc.Point|Number} posOrX position or x
+ * @param {Number} flagsOrY flags or y
+ * @param {Number} [flags]
+ */
+ setTileGID: function(gid, posOrX, flagsOrY, flags) {
+ if (posOrX === undefined) {
+ throw new Error("cc.TMXLayer.setTileGID(): pos should be non-null");
+ }
+ var pos;
+ if (flags !== undefined) {
+ pos = cc.p(posOrX, flagsOrY);
+ } else {
+ pos = posOrX;
+ flags = flagsOrY;
+ }
+ if (pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0) {
+ throw new Error("cc.TMXLayer.setTileGID(): invalid position");
+ }
+ if (!this.tiles) {
+ cc.log("cc.TMXLayer.setTileGID(): TMXLayer: the tiles map has been released");
+ return;
+ }
+ if (gid !== 0 && gid < this.tileset.firstGid) {
+ cc.log( "cc.TMXLayer.setTileGID(): invalid gid:" + gid);
+ return;
+ }
+
+ flags = flags || 0;
+ var currentFlags = this.getTileFlagsAt(pos);
+ var currentGID = this.getTileGIDAt(pos);
+
+ if (currentGID !== gid || currentFlags !== flags) {
+ var gidAndFlags = (gid | flags) >>> 0;
+ // setting gid=0 is equal to remove the tile
+ if (gid === 0)
+ this.removeTileAt(pos);
+ else if (currentGID === 0) // empty tile. create a new one
+ this._updateTileForGID(gidAndFlags, pos);
+ else { // modifying an existing tile with a non-empty tile
+ var z = pos.x + pos.y * this._layerSize.width;
+ var sprite = this.getChildByTag(z);
+ if (sprite) {
+ var rect = this._texGrids[gid];
+ var tex = this._textures[rect.texId];
+ rect = cc.rectPixelsToPoints(rect);
+ sprite.setTexture(tex);
+ sprite.setTextureRect(rect, false);
+ if (flags != null)
+ this._setupTileSprite(sprite, pos, gidAndFlags);
+
+ this.tiles[z] = gidAndFlags;
+ } else {
+ this._updateTileForGID(gidAndFlags, pos);
+ }
+ }
+ }
+ },
+
+ addChild: function (child, localZOrder, tag) {
+ cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
+ if (tag !== undefined) {
+ this._spriteTiles[tag] = child;
+ child._vertexZ = this._vertexZ + cc.renderer.assignedZStep * tag / this.tiles.length;
+ // child._renderCmd._needDraw = false;
+ }
+ },
+
+ removeChild: function (child, cleanup) {
+ if (this._spriteTiles[child.tag]) {
+ this._spriteTiles[child.tag] = null;
+ // child._renderCmd._needDraw = true;
+ }
+ cc.Node.prototype.removeChild.call(this, child, cleanup);
+ },
+
+ /**
+ * lipped tiles can be changed dynamically
+ * @param {cc.Point|Number} pos or x
+ * @param {Number} [y]
+ * @return {Number}
+ */
+ getTileFlagsAt:function (pos, y) {
+ if(!pos)
+ throw new Error("cc.TMXLayer.getTileFlagsAt(): pos should be non-null");
+ if(y !== undefined)
+ pos = cc.p(pos, y);
+ if(pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0)
+ throw new Error("cc.TMXLayer.getTileFlagsAt(): invalid position");
+ if(!this.tiles){
+ cc.log("cc.TMXLayer.getTileFlagsAt(): TMXLayer: the tiles map has been released");
+ return null;
+ }
+
+ var idx = 0 | (pos.x + pos.y * this._layerSize.width);
+ // Bits on the far end of the 32-bit global tile ID are used for tile flags
+ var tile = this.tiles[idx];
+
+ return (tile & cc.TMX_TILE_FLIPPED_ALL) >>> 0;
+ },
+ // XXX: deprecated
+ // tileFlagAt:getTileFlagsAt,
+
+ /**
+ * Removes a tile at given tile coordinate
+ * @param {cc.Point|Number} pos position or x
+ * @param {Number} [y]
+ */
+ removeTileAt:function (pos, y) {
+ if (!pos) {
+ throw new Error("cc.TMXLayer.removeTileAt(): pos should be non-null");
+ }
+ if (y !== undefined) {
+ pos = cc.p(pos, y);
+ }
+ if (pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0) {
+ throw new Error("cc.TMXLayer.removeTileAt(): invalid position");
+ }
+ if (!this.tiles) {
+ cc.log("cc.TMXLayer.removeTileAt(): TMXLayer: the tiles map has been released");
+ return;
+ }
+
+ var gid = this.getTileGIDAt(pos);
+ if (gid !== 0) {
+ var z = 0 | (pos.x + pos.y * this._layerSize.width);
+ // remove tile from GID map
+ this.tiles[z] = 0;
+
+ // remove it from sprites and/or texture atlas
+ var sprite = this._spriteTiles[z];
+ if (sprite) {
+ this.removeChild(sprite, true);
+ }
+ }
+ },
+
+ /**
+ * Returns the position in pixels of a given tile coordinate
+ * @param {cc.Point|Number} pos position or x
+ * @param {Number} [y]
+ * @return {cc.Point}
+ */
+ getPositionAt:function (pos, y) {
+ if (y !== undefined)
+ pos = cc.p(pos, y);
+ var ret = cc.p(0,0);
+ switch (this.layerOrientation) {
+ case cc.TMX_ORIENTATION_ORTHO:
+ ret = this._positionForOrthoAt(pos);
+ break;
+ case cc.TMX_ORIENTATION_ISO:
+ ret = this._positionForIsoAt(pos);
+ break;
+ case cc.TMX_ORIENTATION_HEX:
+ ret = this._positionForHexAt(pos);
+ break;
+ }
+ return cc.pointPixelsToPoints(ret);
+ },
+ // XXX: Deprecated. For backward compatibility only
+ // positionAt:getPositionAt,
+
+ _positionForIsoAt:function (pos) {
+ return cc.p(this._mapTileSize.width / 2 * ( this._layerSize.width + pos.x - pos.y - 1),
+ this._mapTileSize.height / 2 * (( this._layerSize.height * 2 - pos.x - pos.y) - 2));
+ },
+
+ _positionForOrthoAt:function (pos) {
+ return cc.p(pos.x * this._mapTileSize.width,
+ (this._layerSize.height - pos.y - 1) * this._mapTileSize.height);
+ },
+
+ _positionForHexAt:function (pos) {
+ var diffY = (pos.x % 2 === 1) ? (-this._mapTileSize.height / 2) : 0;
+ return cc.p(pos.x * this._mapTileSize.width * 3 / 4,
+ (this._layerSize.height - pos.y - 1) * this._mapTileSize.height + diffY);
+ },
+
+ _calculateLayerOffset:function (pos) {
+ var ret = cc.p(0,0);
+ switch (this.layerOrientation) {
+ case cc.TMX_ORIENTATION_ORTHO:
+ ret = cc.p(pos.x * this._mapTileSize.width, -pos.y * this._mapTileSize.height);
+ break;
+ case cc.TMX_ORIENTATION_ISO:
+ ret = cc.p((this._mapTileSize.width / 2) * (pos.x - pos.y),
+ (this._mapTileSize.height / 2 ) * (-pos.x - pos.y));
+ break;
+ case cc.TMX_ORIENTATION_HEX:
+ if(pos.x !== 0 || pos.y !== 0)
+ cc.log("offset for hexagonal map not implemented yet");
+ break;
+ }
+ return ret;
+ },
+
+ _updateTileForGID:function (gid, pos) {
+ if (!this._texGrids[gid]) {
+ return;
+ }
+
+ var idx = 0 | (pos.x + pos.y * this._layerSize.width);
+ if (idx < this.tiles.length) {
+ this.tiles[idx] = gid;
+ }
+ },
+
+ //The layer recognizes some special properties, like cc_vertez
+ _parseInternalProperties:function () {
+ // if cc_vertex=automatic, then tiles will be rendered using vertexz
+ var vertexz = this.getProperty("cc_vertexz");
+ if (vertexz) {
+ if (vertexz === "automatic") {
+ this._useAutomaticVertexZ = true;
+ var alphaFuncVal = this.getProperty("cc_alpha_func");
+ var alphaFuncValue = 0;
+ if (alphaFuncVal)
+ alphaFuncValue = parseFloat(alphaFuncVal);
+
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) { //todo: need move to WebGL render cmd
+ this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
+ // NOTE: alpha test shader is hard-coded to use the equivalent of a glAlphaFunc(GL_GREATER) comparison
+ this.shaderProgram.use();
+ this.shaderProgram.setUniformLocationWith1f(cc.UNIFORM_ALPHA_TEST_VALUE_S, alphaFuncValue);
+ }
+ } else
+ this._vertexZvalue = parseInt(vertexz, 10);
+ }
+ },
+
+ _setupTileSprite:function (sprite, pos, gid) {
+ var z = pos.x + pos.y * this._layerSize.width;
+ var posInPixel = this.getPositionAt(pos);
+ sprite.setPosition(posInPixel);
+ sprite.setVertexZ(this._vertexZForPos(pos));
+ sprite.setAnchorPoint(0, 0);
+ sprite.setOpacity(this._opacity);
+ sprite.setFlippedX(false);
+ sprite.setFlippedY(false);
+ sprite.setRotation(0.0);
+
+ // Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles.
+ if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) {
+ // put the anchor in the middle for ease of rotation.
+ sprite.setAnchorPoint(0.5, 0.5);
+ sprite.setPosition(posInPixel.x + sprite.width/2, posInPixel.y + sprite.height/2);
+
+ var flag = (gid & (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG) >>> 0) >>> 0;
+ // handle the 4 diagonally flipped states.
+ if (flag === cc.TMX_TILE_HORIZONTAL_FLAG)
+ sprite.setRotation(90);
+ else if (flag === cc.TMX_TILE_VERTICAL_FLAG)
+ sprite.setRotation(270);
+ else if (flag === (cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) {
+ sprite.setRotation(90);
+ sprite.setFlippedX(true);
+ } else {
+ sprite.setRotation(270);
+ sprite.setFlippedX(true);
+ }
+ } else {
+ if ((gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) {
+ sprite.setFlippedX(true);
+ }
+ if ((gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0) {
+ sprite.setFlippedY(true);
+ }
+ }
+ },
+
+ _vertexZForPos:function (x, y) {
+ if (y === undefined) {
+ y = x.y;
+ x = x.x;
+ }
+ var ret = 0;
+ var maxVal = 0;
+ if (this._useAutomaticVertexZ) {
+ switch (this.layerOrientation) {
+ case cc.TMX_ORIENTATION_ISO:
+ maxVal = this._layerSize.width + this._layerSize.height;
+ ret = -(maxVal - (x + y));
+ break;
+ case cc.TMX_ORIENTATION_ORTHO:
+ ret = -(this._layerSize.height - y);
+ break;
+ case cc.TMX_ORIENTATION_HEX:
+ cc.log("TMX Hexa zOrder not supported");
+ break;
+ default:
+ cc.log("TMX invalid value");
+ break;
+ }
+ } else {
+ ret = this._vertexZvalue;
+ }
+ return ret;
+ }
+});
+
+var _p = cc.TMXLayer.prototype;
+
+// Extended properties
+/** @expose */
+_p.layerWidth;
+cc.defineGetterSetter(_p, "layerWidth", _p._getLayerWidth, _p._setLayerWidth);
+/** @expose */
+_p.layerHeight;
+cc.defineGetterSetter(_p, "layerHeight", _p._getLayerHeight, _p._setLayerHeight);
+/** @expose */
+_p.tileWidth;
+cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth);
+/** @expose */
+_p.tileHeight;
+cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight);
+
+
+/**
+ * Creates a cc.TMXLayer with an tile set info, a layer info and a map info
+ * @deprecated since v3.0 please use new cc.TMXLayer(tilesetInfo, layerInfo, mapInfo) instead.
+ * @param {cc.TMXTilesetInfo} tilesetInfo
+ * @param {cc.TMXLayerInfo} layerInfo
+ * @param {cc.TMXMapInfo} mapInfo
+ * @return {cc.TMXLayer|Null}
+ */
+cc.TMXLayer.create = function (tilesetInfo, layerInfo, mapInfo) {
+ return new cc.TMXLayer(tilesetInfo, layerInfo, mapInfo);
+};
diff --git a/cocos2d/tilemap/CCTMXLayerCanvasRenderCmd.js b/cocos2d/tilemap/CCTMXLayerCanvasRenderCmd.js
new file mode 100644
index 0000000000..f354284de2
--- /dev/null
+++ b/cocos2d/tilemap/CCTMXLayerCanvasRenderCmd.js
@@ -0,0 +1,259 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.TMXLayer.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = true;
+ };
+
+ var proto = cc.TMXLayer.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = cc.TMXLayer.CanvasRenderCmd;
+
+ proto.visit = function (parentCmd) {
+ var node = this._node, renderer = cc.renderer;
+
+ parentCmd = parentCmd || this.getParentRenderCmd();
+ if (parentCmd) {
+ this._curLevel = parentCmd._curLevel + 1;
+ }
+
+ // quick return if not visible
+ if (!node._visible)
+ return;
+
+ if (isNaN(node._customZ)) {
+ node._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+
+ this._syncStatus(parentCmd);
+
+ // Visit children
+ var children = node._children, child,
+ spTiles = node._spriteTiles,
+ i, len = children.length;
+ if (len > 0) {
+ node.sortAllChildren();
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0) {
+ child._renderCmd.visit(this);
+ }
+ else {
+ break;
+ }
+ }
+
+ renderer.pushRenderCommand(this);
+ for (; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder === 0 && spTiles[child.tag]) {
+ if (isNaN(child._customZ)) {
+ child._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+ child._renderCmd.updateStatus();
+ continue;
+ }
+ child._renderCmd.visit(this);
+ }
+ } else {
+ renderer.pushRenderCommand(this);
+ }
+ this._dirtyFlag = 0;
+ };
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var node = this._node, hasRotation = (node._rotationX || node._rotationY),
+ layerOrientation = node.layerOrientation,
+ tiles = node.tiles,
+ alpha = node._opacity / 255;
+
+ if (!tiles || alpha <= 0) {
+ return;
+ }
+
+ var maptw = node._mapTileSize.width,
+ mapth = node._mapTileSize.height,
+ tilew = node.tileset._tileSize.width / cc.director._contentScaleFactor,
+ tileh = node.tileset._tileSize.height / cc.director._contentScaleFactor,
+ extw = tilew - maptw,
+ exth = tileh - mapth,
+ winw = cc.winSize.width,
+ winh = cc.winSize.height,
+ rows = node._layerSize.height,
+ cols = node._layerSize.width,
+ grids = node._texGrids,
+ spTiles = node._spriteTiles,
+ wt = this._worldTransform,
+ ox = -node._contentSize.width * node._anchorPoint.x,
+ oy = -node._contentSize.height * node._anchorPoint.y,
+ a = wt.a, b = wt.b, c = wt.c, d = wt.d,
+ mapx = ox * a + oy * c + wt.tx,
+ mapy = ox * b + oy * d + wt.ty;
+
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+
+ // Culling
+ var startCol = 0, startRow = 0,
+ maxCol = cols, maxRow = rows;
+ if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ORTHO) {
+ startCol = Math.floor(-(mapx - extw * a) / (maptw * a));
+ startRow = Math.floor((mapy - exth * d + mapth * rows * d - winh) / (mapth * d));
+ maxCol = Math.ceil((winw - mapx + extw * a) / (maptw * a));
+ maxRow = rows - Math.floor(-(mapy + exth * d) / (mapth * d));
+ // Adjustment
+ if (startCol < 0) startCol = 0;
+ if (startRow < 0) startRow = 0;
+ if (maxCol > cols) maxCol = cols;
+ if (maxRow > rows) maxRow = rows;
+ }
+
+ var i, row, col, colOffset = startRow * cols, z,
+ gid, grid, tex, cmd,
+ mask = cc.TMX_TILE_FLIPPED_MASK,
+ top, left, bottom, right, dw = tilew, dh = tileh,
+ w = tilew * a, h = tileh * d, gt, gl, gb, gr,
+ flippedX = false, flippedY = false;
+
+ // Draw culled sprite tiles
+ z = colOffset + startCol;
+ for (i in spTiles) {
+ if (i < z && spTiles[i]) {
+ cmd = spTiles[i]._renderCmd;
+ if (spTiles[i]._localZOrder === 0 && !!cmd.rendering) {
+ cmd.rendering(ctx, scaleX, scaleY);
+ }
+ }
+ else if (i >= z) {
+ break;
+ }
+ }
+
+ wrapper.setTransform(wt, scaleX, scaleY);
+ wrapper.setGlobalAlpha(alpha);
+
+ for (row = startRow; row < maxRow; ++row) {
+ for (col = startCol; col < maxCol; ++col) {
+ z = colOffset + col;
+ // Skip sprite tiles
+ if (spTiles[z]) {
+ cmd = spTiles[z]._renderCmd;
+ if (spTiles[z]._localZOrder === 0 && !!cmd.rendering) {
+ cmd.rendering(ctx, scaleX, scaleY);
+ wrapper.setTransform(wt, scaleX, scaleY);
+ wrapper.setGlobalAlpha(alpha);
+ }
+ continue;
+ }
+
+ gid = node.tiles[z];
+ grid = grids[(gid & mask) >>> 0];
+ if (!grid) {
+ continue;
+ }
+ tex = node._textures[grid.texId];
+ if (!tex || !tex._htmlElementObj) {
+ continue;
+ }
+
+ switch (layerOrientation) {
+ case cc.TMX_ORIENTATION_ORTHO:
+ left = col * maptw;
+ bottom = -(rows - row - 1) * mapth;
+ break;
+ case cc.TMX_ORIENTATION_ISO:
+ left = maptw / 2 * ( cols + col - row - 1);
+ bottom = -mapth / 2 * ( rows * 2 - col - row - 2);
+ break;
+ case cc.TMX_ORIENTATION_HEX:
+ left = col * maptw * 3 / 4;
+ bottom = -(rows - row - 1) * mapth + ((col % 2 === 1) ? (-mapth / 2) : 0);
+ break;
+ }
+ right = left + tilew;
+ top = bottom - tileh;
+ // TMX_ORIENTATION_ISO trim
+ if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ISO) {
+ gb = -mapy + bottom * d;
+ if (gb < -winh - h) {
+ col += Math.floor((-winh - gb) * 2 / h) - 1;
+ continue;
+ }
+ gr = mapx + right * a;
+ if (gr < -w) {
+ col += Math.floor((-gr) * 2 / w) - 1;
+ continue;
+ }
+ gl = mapx + left * a;
+ gt = -mapy + top * d;
+ if (gl > winw || gt > 0) {
+ col = maxCol;
+ continue;
+ }
+ }
+
+ // Rotation and Flip
+ if (gid > cc.TMX_TILE_DIAGONAL_FLAG) {
+ flippedX = (gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0;
+ flippedY = (gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0;
+ }
+
+ if (flippedX) {
+ left = -right;
+ context.scale(-1, 1);
+ }
+ if (flippedY) {
+ top = -bottom;
+ context.scale(1, -1);
+ }
+
+ context.drawImage(tex._htmlElementObj,
+ grid.x, grid.y, grid.width, grid.height,
+ left, top, dw, dh);
+ // Revert flip
+ if (flippedX) {
+ context.scale(-1, 1);
+ }
+ if (flippedY) {
+ context.scale(1, -1);
+ }
+ cc.g_NumberOfDraws++;
+ }
+ colOffset += cols;
+ }
+
+ // Draw culled sprite tiles
+ for (i in spTiles) {
+ if (i > z && spTiles[i]) {
+ cmd = spTiles[i]._renderCmd;
+ if (spTiles[i]._localZOrder === 0 && !!cmd.rendering) {
+ cmd.rendering(ctx, scaleX, scaleY);
+ }
+ }
+ }
+ };
+})();
diff --git a/cocos2d/tilemap/CCTMXLayerWebGLRenderCmd.js b/cocos2d/tilemap/CCTMXLayerWebGLRenderCmd.js
new file mode 100644
index 0000000000..d0e90bebc9
--- /dev/null
+++ b/cocos2d/tilemap/CCTMXLayerWebGLRenderCmd.js
@@ -0,0 +1,259 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.TMXLayer.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._vertices = [
+ {x: 0, y: 0},
+ {x: 0, y: 0},
+ {x: 0, y: 0},
+ {x: 0, y: 0}
+ ];
+ this._color = new Uint32Array(1);
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST);
+
+ var radian = Math.PI * 90 / 180;
+ this._sin90 = Math.sin(radian);
+ this._cos90 = Math.cos(radian);
+ radian = radian * 3;
+ this._sin270 = Math.sin(radian);
+ this._cos270 = Math.cos(radian);
+ };
+
+ var proto = cc.TMXLayer.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = cc.TMXLayer.WebGLRenderCmd;
+
+ proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
+ var node = this._node, hasRotation = (node._rotationX || node._rotationY),
+ layerOrientation = node.layerOrientation,
+ tiles = node.tiles;
+
+ if (!tiles) {
+ return 0;
+ }
+
+ var scalex = cc.view._scaleX,
+ scaley = cc.view._scaleY,
+ maptw = node._mapTileSize.width,
+ mapth = node._mapTileSize.height,
+ tilew = node.tileset._tileSize.width / cc.director._contentScaleFactor,
+ tileh = node.tileset._tileSize.height / cc.director._contentScaleFactor,
+ extw = tilew - maptw,
+ exth = tileh - mapth,
+ winw = cc.winSize.width,
+ winh = cc.winSize.height,
+ rows = node._layerSize.height,
+ cols = node._layerSize.width,
+ grids = node._texGrids,
+ spTiles = node._spriteTiles,
+ wt = this._worldTransform,
+ a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty,
+ ox = -node._contentSize.width * node._anchorPoint.x,
+ oy = -node._contentSize.height * node._anchorPoint.y,
+ mapx = ox * a + oy * c + tx,
+ mapy = ox * b + oy * d + ty;
+
+ var opacity = node._opacity,
+ cr = this._displayedColor.r,
+ cg = this._displayedColor.g,
+ cb = this._displayedColor.b;
+ if (node._opacityModifyRGB) {
+ var ca = opacity / 255;
+ cr *= ca;
+ cg *= ca;
+ cb *= ca;
+ }
+ this._color[0] = ((opacity << 24) | (cb << 16) | (cg << 8) | cr);
+
+ // Culling
+ var startCol = 0, startRow = 0,
+ maxCol = cols, maxRow = rows;
+ if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ORTHO) {
+ startCol = Math.floor(-(mapx - extw * a) / (maptw * a));
+ startRow = Math.floor((mapy - exth * d + mapth * rows * d - winh) / (mapth * d));
+ maxCol = Math.ceil((winw - mapx + extw * a) / (maptw * a));
+ maxRow = rows - Math.floor(-(mapy + exth * d) / (mapth * d));
+ // Adjustment
+ if (startCol < 0) startCol = 0;
+ if (startRow < 0) startRow = 0;
+ if (maxCol > cols) maxCol = cols;
+ if (maxRow > rows) maxRow = rows;
+ }
+
+ var row, col,
+ offset = vertexDataOffset,
+ colOffset = startRow * cols, z, gid, grid,
+ mask = cc.TMX_TILE_FLIPPED_MASK,
+ i, top, left, bottom, right,
+ w = tilew * a, h = tileh * d, gt, gl, gb, gr,
+ wa = a, wb = b, wc = c, wd = d, wtx = tx, wty = ty, // world
+ flagged = false, flippedX = false, flippedY = false,
+ vertices = this._vertices;
+ for (row = startRow; row < maxRow; ++row) {
+ for (col = startCol; col < maxCol; ++col) {
+ // No more buffer
+ if (offset + 24 > f32buffer.length) {
+ cc.renderer._increaseBatchingSize((offset - vertexDataOffset) / 6);
+ cc.renderer._batchRendering();
+ vertexDataOffset = 0;
+ offset = 0;
+ }
+
+ z = colOffset + col;
+ // Skip sprite tiles
+ if (spTiles[z]) {
+ continue;
+ }
+
+ gid = node.tiles[z];
+ grid = grids[(gid & mask) >>> 0];
+ if (!grid) {
+ continue;
+ }
+
+ // Vertices
+ switch (layerOrientation) {
+ case cc.TMX_ORIENTATION_ORTHO:
+ left = col * maptw;
+ bottom = (rows - row - 1) * mapth;
+ z = node._vertexZ + cc.renderer.assignedZStep * z / tiles.length;
+ break;
+ case cc.TMX_ORIENTATION_ISO:
+ left = maptw / 2 * ( cols + col - row - 1);
+ bottom = mapth / 2 * ( rows * 2 - col - row - 2);
+ z = node._vertexZ + cc.renderer.assignedZStep * (node.height - bottom) / node.height;
+ break;
+ case cc.TMX_ORIENTATION_HEX:
+ left = col * maptw * 3 / 4;
+ bottom = (rows - row - 1) * mapth + ((col % 2 === 1) ? (-mapth / 2) : 0);
+ z = node._vertexZ + cc.renderer.assignedZStep * (node.height - bottom) / node.height;
+ break;
+ }
+ right = left + tilew;
+ top = bottom + tileh;
+ // TMX_ORIENTATION_ISO trim
+ if (!hasRotation && layerOrientation === cc.TMX_ORIENTATION_ISO) {
+ gb = mapy + bottom * d;
+ if (gb > winh + h) {
+ col += Math.floor((gb - winh) * 2 / h) - 1;
+ continue;
+ }
+ gr = mapx + right * a;
+ if (gr < -w) {
+ col += Math.floor((-gr) * 2 / w) - 1;
+ continue;
+ }
+ gl = mapx + left * a;
+ gt = mapy + top * d;
+ if (gl > winw || gt < 0) {
+ col = maxCol;
+ continue;
+ }
+ }
+ // Rotation and Flip
+ if (gid > cc.TMX_TILE_DIAGONAL_FLAG) {
+ flagged = true;
+ flippedX = (gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0;
+ flippedY = (gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0;
+ // if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) {
+ // var flag = (gid & (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG) >>> 0) >>> 0;
+ // // handle the 4 diagonally flipped states.
+ // var la, lb, lc, ld;
+ // if (flag === cc.TMX_TILE_HORIZONTAL_FLAG || flag === (cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) {
+ // lb = -(lc = this._sin90);
+ // la = ld = this._cos90;
+ // }
+ // else {
+ // lb = -(lc = this._sin270);
+ // la = ld = this._cos270;
+ // }
+ // left += grid.width * scalex / 2;
+ // bottom += grid.height * scaley / 2;
+ // wa = la * a + lb * c;
+ // wb = la * b + lb * d;
+ // wc = lc * a + ld * c;
+ // wd = lc * b + ld * d;
+ // wtx = a * left + c * bottom + tx;
+ // wty = d * bottom + ty + b * left;
+ // right = right - left;
+ // top = top - bottom;
+ // left = -right;
+ // bottom = -top;
+ // }
+ }
+
+ vertices[0].x = left * wa + top * wc + wtx; // tl
+ vertices[0].y = left * wb + top * wd + wty;
+ vertices[1].x = left * wa + bottom * wc + wtx; // bl
+ vertices[1].y = left * wb + bottom * wd + wty;
+ vertices[2].x = right * wa + top * wc + wtx; // tr
+ vertices[2].y = right * wb + top * wd + wty;
+ vertices[3].x = right * wa + bottom * wc + wtx; // br
+ vertices[3].y = right * wb + bottom * wd + wty;
+
+ for (i = 0; i < 4; ++i) {
+ f32buffer[offset] = vertices[i].x;
+ f32buffer[offset + 1] = vertices[i].y;
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = this._color[0];
+ switch (i) {
+ case 0: // tl
+ f32buffer[offset + 4] = flippedX ? grid.r : grid.l;
+ f32buffer[offset + 5] = flippedY ? grid.b : grid.t;
+ break;
+ case 1: // bl
+ f32buffer[offset + 4] = flippedX ? grid.r : grid.l;
+ f32buffer[offset + 5] = flippedY ? grid.t : grid.b;
+ break;
+ case 2: // tr
+ f32buffer[offset + 4] = flippedX ? grid.l : grid.r;
+ f32buffer[offset + 5] = flippedY ? grid.b : grid.t;
+ break;
+ case 3: // br
+ f32buffer[offset + 4] = flippedX ? grid.l : grid.r;
+ f32buffer[offset + 5] = flippedY ? grid.t : grid.b;
+ break;
+ }
+
+ offset += 6;
+ }
+ if (flagged) {
+ wa = a;
+ wb = b;
+ wc = c;
+ wd = d;
+ wtx = tx;
+ wty = ty;
+ flippedX = false;
+ flippedY = false;
+ flagged = false;
+ }
+ }
+ colOffset += cols;
+ }
+ return (offset - vertexDataOffset) / 6;
+ };
+})();
diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXObjectGroup.js b/cocos2d/tilemap/CCTMXObjectGroup.js
similarity index 63%
rename from cocos2d/tileMap_parallax_nodes/CCTMXObjectGroup.js
rename to cocos2d/tilemap/CCTMXObjectGroup.js
index 0dab429efc..b5d41dbc9a 100644
--- a/cocos2d/tileMap_parallax_nodes/CCTMXObjectGroup.js
+++ b/cocos2d/tilemap/CCTMXObjectGroup.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -28,21 +28,26 @@
* cc.TMXObjectGroup represents the TMX object group.
* @class
* @extends cc.Class
+ *
+ * @property {Array} properties - Properties from the group. They can be added using tilemap editors
+ * @property {String} groupName - Name of the group
*/
cc.TMXObjectGroup = cc.Class.extend(/** @lends cc.TMXObjectGroup# */{
- //name of the group
- _groupName:null,
- _positionOffset:null,
- _properties:null,
- _objects:null,
+ properties: null,
+ groupName: "",
+
+ _positionOffset: null,
+ _objects: null,
/**
- * Constructor
+ * The cc.TMXObjectGroup's constructor.
+ * This function will automatically be invoked when you create a node using new construction: "var node = new cc.TMXObjectGroup()".
+ * Override it to extend its behavior, remember to call "this._super()" in the extended "ctor" function.
*/
ctor:function () {
- this._groupName = "";
- this._positionOffset = cc.PointZero();
- this._properties = [];
+ this.groupName = "";
+ this._positionOffset = cc.p(0,0);
+ this.properties = [];
this._objects = [];
},
@@ -51,15 +56,16 @@ cc.TMXObjectGroup = cc.Class.extend(/** @lends cc.TMXObjectGroup# */{
* @return {cc.Point}
*/
getPositionOffset:function () {
- return cc.p(this._positionOffset.x,this._positionOffset.y);
+ return cc.p(this._positionOffset);
},
/**
- * @param {cc.Point} Var
+ * Offset position of child objects
+ * @param {cc.Point} offset
*/
- setPositionOffset:function (Var) {
- this._positionOffset.x = Var.x;
- this._positionOffset.y = Var.y;
+ setPositionOffset:function (offset) {
+ this._positionOffset.x = offset.x;
+ this._positionOffset.y = offset.y;
},
/**
@@ -67,28 +73,31 @@ cc.TMXObjectGroup = cc.Class.extend(/** @lends cc.TMXObjectGroup# */{
* @return {Array}
*/
getProperties:function () {
- return this._properties;
+ return this.properties;
},
/**
+ * List of properties stored in a dictionary
* @param {object} Var
*/
setProperties:function (Var) {
- this._properties.push(Var);
+ this.properties.push(Var);
},
/**
+ * Gets the Group name.
* @return {String}
*/
getGroupName:function () {
- return this._groupName.toString();
+ return this.groupName.toString();
},
/**
+ * Set the Group name
* @param {String} groupName
*/
setGroupName:function (groupName) {
- this._groupName = groupName;
+ this.groupName = groupName;
},
/**
@@ -97,21 +106,32 @@ cc.TMXObjectGroup = cc.Class.extend(/** @lends cc.TMXObjectGroup# */{
* @return {object}
*/
propertyNamed:function (propertyName) {
- return this._properties[propertyName];
+ return this.properties[propertyName];
},
/**
* Return the dictionary for the specific object name.
* It will return the 1st object found on the array for the given name.
+ * @deprecated since v3.4 please use .getObject
* @param {String} objectName
* @return {object|Null}
*/
objectNamed:function (objectName) {
+ return this.getObject(objectName);
+ },
+
+ /**
+ * Return the dictionary for the specific object name.
+ * It will return the 1st object found on the array for the given name.
+ * @param {String} objectName
+ * @return {object|Null}
+ */
+ getObject: function(objectName){
if (this._objects && this._objects.length > 0) {
var locObjects = this._objects;
for (var i = 0, len = locObjects.length; i < len; i++) {
var name = locObjects[i]["name"];
- if (name && name == objectName)
+ if (name && name === objectName)
return locObjects[i];
}
}
@@ -120,6 +140,7 @@ cc.TMXObjectGroup = cc.Class.extend(/** @lends cc.TMXObjectGroup# */{
},
/**
+ * Gets the objects.
* @return {Array}
*/
getObjects:function () {
@@ -127,6 +148,7 @@ cc.TMXObjectGroup = cc.Class.extend(/** @lends cc.TMXObjectGroup# */{
},
/**
+ * Set the objects.
* @param {object} objects
*/
setObjects:function (objects) {
diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js b/cocos2d/tilemap/CCTMXTiledMap.js
similarity index 55%
rename from cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js
rename to cocos2d/tilemap/CCTMXTiledMap.js
index c52c060d10..5ca4107ed2 100644
--- a/cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js
+++ b/cocos2d/tilemap/CCTMXTiledMap.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -72,7 +72,7 @@ cc.TMX_ORIENTATION_ISO = 2;
*
* Limitations:
* - It only supports one tileset per layer.
- * - Embeded images are not supported
+ * - Embedded images are not supported
* - It only supports the XML format (the JSON format is not supported)
*
* Technical description:
@@ -97,32 +97,62 @@ cc.TMX_ORIENTATION_ISO = 2;
* object.getProperty(name_of_the_property);
* @class
* @extends cc.Node
+ * @param {String} tmxFile tmxFile fileName or content string
+ * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required.
+
+ *
+ * @property {Array} properties - Properties from the map. They can be added using tilemap editors
+ * @property {Number} mapOrientation - Map orientation
+ * @property {Array} objectGroups - Object groups of the map
+ * @property {Number} mapWidth - Width of the map
+ * @property {Number} mapHeight - Height of the map
+ * @property {Number} tileWidth - Width of a tile
+ * @property {Number} tileHeight - Height of a tile
+ *
+ * @example
+ * //example
+ * 1.
+ * //create a TMXTiledMap with file name
+ * var tmxTiledMap = new cc.TMXTiledMap("res/orthogonal-test1.tmx");
+ * 2.
+ * //create a TMXTiledMap with content string and resource path
+ * var resources = "res/TileMaps";
+ * var filePath = "res/TileMaps/orthogonal-test1.tmx";
+ * var xmlStr = cc.loader.getRes(filePath);
+ * var tmxTiledMap = new cc.TMXTiledMap(xmlStr, resources);
*/
cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
+ properties: null,
+ mapOrientation: null,
+ objectGroups: null,
+
//the map's size property measured in tiles
- _mapSize:null,
- _tileSize:null,
- _properties:null,
- _objectGroups:null,
- _mapOrientation:null,
+ _mapSize: null,
+ _tileSize: null,
//tile properties
- //todo delete
- _TMXLayers:null,
- _tileProperties:null,
+ _tileProperties: null,
+ _className: "TMXTiledMap",
- ctor:function(){
+ /**
+ * Creates a TMX Tiled Map with a TMX file or content string.
+ * Constructor of cc.TMXTiledMap
+ * @param {String} tmxFile tmxFile fileName or content string
+ * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required.
+ */
+ ctor:function(tmxFile,resourcePath){
cc.Node.prototype.ctor.call(this);
- this._mapSize = cc.SizeZero();
- this._tileSize = cc.SizeZero();
- this._properties = null;
- this._objectGroups = null;
- this._mapOrientation = null;
- this._TMXLayers = null;
-
- this._tileProperties = [];
+ this._mapSize = cc.size(0, 0);
+ this._tileSize = cc.size(0, 0);
+
+ if(resourcePath !== undefined){
+ this.initWithXML(tmxFile,resourcePath);
+ }else if(tmxFile !== undefined){
+ this.initWithTMXFile(tmxFile);
+ }
},
/**
+ * Gets the map size.
* @return {cc.Size}
*/
getMapSize:function () {
@@ -130,6 +160,7 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
},
/**
+ * Set the map size.
* @param {cc.Size} Var
*/
setMapSize:function (Var) {
@@ -137,7 +168,21 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
this._mapSize.height = Var.height;
},
+ _getMapWidth: function () {
+ return this._mapSize.width;
+ },
+ _setMapWidth: function (width) {
+ this._mapSize.width = width;
+ },
+ _getMapHeight: function () {
+ return this._mapSize.height;
+ },
+ _setMapHeight: function (height) {
+ this._mapSize.height = height;
+ },
+
/**
+ * Gets the tile size.
* @return {cc.Size}
*/
getTileSize:function () {
@@ -145,6 +190,7 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
},
/**
+ * Set the tile size
* @param {cc.Size} Var
*/
setTileSize:function (Var) {
@@ -152,19 +198,33 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
this._tileSize.height = Var.height;
},
+ _getTileWidth: function () {
+ return this._tileSize.width;
+ },
+ _setTileWidth: function (width) {
+ this._tileSize.width = width;
+ },
+ _getTileHeight: function () {
+ return this._tileSize.height;
+ },
+ _setTileHeight: function (height) {
+ this._tileSize.height = height;
+ },
+
/**
* map orientation
* @return {Number}
*/
getMapOrientation:function () {
- return this._mapOrientation;
+ return this.mapOrientation;
},
/**
+ * map orientation
* @param {Number} Var
*/
setMapOrientation:function (Var) {
- this._mapOrientation = Var;
+ this.mapOrientation = Var;
},
/**
@@ -172,57 +232,72 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
* @return {Array}
*/
getObjectGroups:function () {
- return this._objectGroups;
+ return this.objectGroups;
},
/**
+ * object groups
* @param {Array} Var
*/
setObjectGroups:function (Var) {
- this._objectGroups = Var;
+ this.objectGroups = Var;
},
/**
- * properties
+ * Gets the properties
* @return {object}
*/
getProperties:function () {
- return this._properties;
+ return this.properties;
},
/**
+ * Set the properties
* @param {object} Var
*/
setProperties:function (Var) {
- this._properties = Var;
+ this.properties = Var;
},
/**
+ * Initializes the instance of cc.TMXTiledMap with tmxFile
* @param {String} tmxFile
- * @return {Boolean}
+ * @return {Boolean} Whether the initialization was successful.
* @example
* //example
* var map = new cc.TMXTiledMap()
* map.initWithTMXFile("hello.tmx");
*/
- initWithTMXFile:function (tmxFile,resourcePath) {
- cc.Assert(tmxFile != null && tmxFile.length > 0, "TMXTiledMap: tmx file should not be nil");
- this.setContentSize(cc.SizeZero());
- var mapInfo = cc.TMXMapInfo.create(tmxFile,resourcePath);
+ initWithTMXFile:function (tmxFile) {
+ if(!tmxFile || tmxFile.length === 0)
+ throw new Error("cc.TMXTiledMap.initWithTMXFile(): tmxFile should be non-null or non-empty string.");
+ this.width = 0;
+ this.height = 0;
+ var mapInfo = new cc.TMXMapInfo(tmxFile);
if (!mapInfo)
return false;
- cc.Assert(mapInfo.getTilesets().length != 0, "TMXTiledMap: Map not found. Please check the filename.");
+ var locTilesets = mapInfo.getTilesets();
+ if(!locTilesets || locTilesets.length === 0)
+ cc.log("cc.TMXTiledMap.initWithTMXFile(): Map not found. Please check the filename.");
this._buildWithMapInfo(mapInfo);
return true;
},
+ /**
+ * Initializes the instance of cc.TMXTiledMap with tmxString
+ * @param {String} tmxString
+ * @param {String} resourcePath
+ * @return {Boolean} Whether the initialization was successful.
+ */
initWithXML:function(tmxString, resourcePath){
- this.setContentSize(cc.SizeZero());
-
- var mapInfo = cc.TMXMapInfo.createWithXML(tmxString, resourcePath);
+ this.width = 0;
+ this.height = 0;
- cc.Assert( mapInfo.getTilesets().length != 0, "TMXTiledMap: Map not found. Please check the filename.");
+ var mapInfo = new cc.TMXMapInfo(tmxString, resourcePath);
+ var locTilesets = mapInfo.getTilesets();
+ if(!locTilesets || locTilesets.length === 0)
+ cc.log("cc.TMXTiledMap.initWithXML(): Map not found. Please check the filename.");
this._buildWithMapInfo(mapInfo);
return true;
},
@@ -230,9 +305,9 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
_buildWithMapInfo:function (mapInfo) {
this._mapSize = mapInfo.getMapSize();
this._tileSize = mapInfo.getTileSize();
- this._mapOrientation = mapInfo.getOrientation();
- this._objectGroups = mapInfo.getObjectGroups();
- this._properties = mapInfo.getProperties();
+ this.mapOrientation = mapInfo.orientation;
+ this.objectGroups = mapInfo.getObjectGroups();
+ this.properties = mapInfo.properties;
this._tileProperties = mapInfo.getTileProperties();
var idx = 0;
@@ -244,49 +319,59 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
if (layerInfo && layerInfo.visible) {
var child = this._parseLayer(layerInfo, mapInfo);
this.addChild(child, idx, idx);
-
// update content size with the max size
- var childSize = child.getContentSize();
- var currentSize = this.getContentSize();
- currentSize.width = Math.max(currentSize.width, childSize.width);
- currentSize.height = Math.max(currentSize.height, childSize.height);
- this.setContentSize(currentSize);
+ this.width = Math.max(this.width, child.width);
+ this.height = Math.max(this.height, child.height);
idx++;
}
}
}
},
- /** return the TMXLayer for the specific layer
+
+ /**
+ * Return All layers array.
+ * @returns {Array}
+ */
+ allLayers: function () {
+ var retArr = [], locChildren = this._children;
+ for(var i = 0, len = locChildren.length;i< len;i++){
+ var layer = locChildren[i];
+ if(layer && layer instanceof cc.TMXLayer)
+ retArr.push(layer);
+ }
+ return retArr;
+ },
+
+ /**
+ * return the TMXLayer for the specific layer
* @param {String} layerName
* @return {cc.TMXLayer}
*/
getLayer:function (layerName) {
- cc.Assert(layerName != null && layerName.length > 0, "Invalid layer name!");
-
- for (var i = 0; i < this._children.length; i++) {
- var layer = this._children[i];
- if (layer) {
- if (layer.getLayerName() == layerName) {
- return layer;
- }
- }
+ if(!layerName || layerName.length === 0)
+ throw new Error("cc.TMXTiledMap.getLayer(): layerName should be non-null or non-empty string.");
+ var locChildren = this._children;
+ for (var i = 0; i < locChildren.length; i++) {
+ var layer = locChildren[i];
+ if (layer && layer.layerName === layerName)
+ return layer;
}
-
// layer not found
return null;
},
/**
- * Return the TMXObjectGroup for the secific group
+ * Return the TMXObjectGroup for the specific group
* @param {String} groupName
* @return {cc.TMXObjectGroup}
*/
getObjectGroup:function (groupName) {
- cc.Assert(groupName != null && groupName.length > 0, "Invalid group name!");
- if (this._objectGroups) {
- for (var i = 0; i < this._objectGroups.length; i++) {
- var objectGroup = this._objectGroups[i];
- if (objectGroup && objectGroup.getGroupName() == groupName) {
+ if(!groupName || groupName.length === 0)
+ throw new Error("cc.TMXTiledMap.getObjectGroup(): groupName should be non-null or non-empty string.");
+ if (this.objectGroups) {
+ for (var i = 0; i < this.objectGroups.length; i++) {
+ var objectGroup = this.objectGroups[i];
+ if (objectGroup && objectGroup.groupName === groupName) {
return objectGroup;
}
}
@@ -301,24 +386,34 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
* @return {String}
*/
getProperty:function (propertyName) {
- return this._properties[propertyName.toString()];
+ return this.properties[propertyName.toString()];
},
/**
* Return properties dictionary for tile GID
* @param {Number} GID
* @return {object}
+ * @deprecated
*/
propertiesForGID:function (GID) {
+ cc.log("propertiesForGID is deprecated. Please use getPropertiesForGID instead.");
+ return this.getPropertiesForGID[GID];
+ },
+
+ /**
+ * Return properties dictionary for tile GID
+ * @param {Number} GID
+ * @return {object}
+ */
+ getPropertiesForGID: function(GID) {
return this._tileProperties[GID];
},
_parseLayer:function (layerInfo, mapInfo) {
var tileset = this._tilesetForLayer(layerInfo, mapInfo);
- var layer = cc.TMXLayer.create(tileset, layerInfo, mapInfo);
+ var layer = new cc.TMXLayer(tileset, layerInfo, mapInfo);
// tell the layerinfo to release the ownership of the tiles map.
layerInfo.ownTiles = false;
- layer.setupTiles();
return layer;
},
@@ -333,9 +428,9 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
for (var x = 0; x < size.width; x++) {
var pos = x + size.width * y;
var gid = layerInfo._tiles[pos];
- if (gid != 0) {
+ if (gid !== 0) {
// Optimization: quick return
- // if the layer is invalid (more than 1 tileset per layer) an cc.Assert will be thrown later
+ // if the layer is invalid (more than 1 tileset per layer) an cc.assert will be thrown later
if (((gid & cc.TMX_TILE_FLIPPED_MASK)>>>0) >= tileset.firstGid) {
return tileset;
}
@@ -353,33 +448,31 @@ cc.TMXTiledMap = cc.Node.extend(/** @lends cc.TMXTiledMap# */{
}
});
-/**
- * Creates a TMX Tiled Map with a TMX file.
- * Implementation cc.TMXTiledMap
- * @param {String} tmxFile
- * @param {String} resourcePath
- * @return {cc.TMXTiledMap|undefined}
- * @example
- * //example
- * var map = cc.TMXTiledMap.create("hello.tmx");
- */
-cc.TMXTiledMap.create = function (tmxFile, resourcePath) {
- var ret = new cc.TMXTiledMap();
- if (ret.initWithTMXFile(tmxFile,resourcePath)) {
- return ret;
- }
- return null;
-};
+var _p = cc.TMXTiledMap.prototype;
+
+// Extended properties
+/** @expose */
+_p.mapWidth;
+cc.defineGetterSetter(_p, "mapWidth", _p._getMapWidth, _p._setMapWidth);
+/** @expose */
+_p.mapHeight;
+cc.defineGetterSetter(_p, "mapHeight", _p._getMapHeight, _p._setMapHeight);
+/** @expose */
+_p.tileWidth;
+cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth);
+/** @expose */
+_p.tileHeight;
+cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight);
+
/**
- * initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources
- * @param {String} tmxString
- * @param {String} resourcePath
+ * Creates a TMX Tiled Map with a TMX file or content string.
+ * Implementation cc.TMXTiledMap
+ * @deprecated since v3.0 please use new cc.TMXTiledMap(tmxFile,resourcePath) instead.
+ * @param {String} tmxFile tmxFile fileName or content string
+ * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required.
* @return {cc.TMXTiledMap|undefined}
*/
-cc.TMXTiledMap.createWithXML = function(tmxString, resourcePath){
- var tileMap = new cc.TMXTiledMap();
- if(tileMap.initWithXML(tmxString,resourcePath))
- return tileMap;
- return null;
+cc.TMXTiledMap.create = function (tmxFile,resourcePath) {
+ return new cc.TMXTiledMap(tmxFile,resourcePath);
};
diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXXMLParser.js b/cocos2d/tilemap/CCTMXXMLParser.js
similarity index 59%
rename from cocos2d/tileMap_parallax_nodes/CCTMXXMLParser.js
rename to cocos2d/tilemap/CCTMXXMLParser.js
index 2fa40d7dc0..70509e6802 100644
--- a/cocos2d/tileMap_parallax_nodes/CCTMXXMLParser.js
+++ b/cocos2d/tilemap/CCTMXXMLParser.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -24,27 +24,6 @@
THE SOFTWARE.
****************************************************************************/
-/**
- * @constant
- * @type Number
- */
-cc.TMX_LAYER_ATTRIB_NONE = 1 << 0;
-/**
- * @constant
- * @type Number
- */
-cc.TMX_LAYER_ATTRIB_BASE64 = 1 << 1;
-/**
- * @constant
- * @type Number
- */
-cc.TMX_LAYER_ATTRIB_GZIP = 1 << 2;
-/**
- * @constant
- * @type Number
- */
-cc.TMX_LAYER_ATTRIB_ZLIB = 1 << 3;
-
/**
* @constant
* @type Number
@@ -124,10 +103,13 @@ cc.TMX_TILE_FLIPPED_MASK = (~(cc.TMX_TILE_FLIPPED_ALL)) >>> 0;
* This information is obtained from the TMX file.
* @class
* @extends cc.Class
+ *
+ * @property {Array} properties - Properties of the layer info.
*/
cc.TMXLayerInfo = cc.Class.extend(/** @lends cc.TMXLayerInfo# */{
- _properties:null,
- name:"",
+ properties:null,
+
+ name:"",
_layerSize:null,
_tiles:null,
visible:null,
@@ -138,30 +120,32 @@ cc.TMXLayerInfo = cc.Class.extend(/** @lends cc.TMXLayerInfo# */{
offset:null,
ctor:function () {
- this._properties = [];
+ this.properties = [];
this.name = "";
this._layerSize = null;
- this._tiles = [];
+ this._tiles = null;
this.visible = true;
this._opacity = 0;
this.ownTiles = true;
this._minGID = 100000;
this._maxGID = 0;
- this.offset = cc.PointZero();
+ this.offset = cc.p(0,0);
},
/**
+ * Gets the Properties.
* @return {Array}
*/
getProperties:function () {
- return this._properties;
+ return this.properties;
},
/**
- * @param {object} Var
+ * Set the Properties.
+ * @param {object} value
*/
- setProperties:function (Var) {
- this._properties = Var;
+ setProperties:function (value) {
+ this.properties = value;
}
});
@@ -177,57 +161,54 @@ cc.TMXLayerInfo = cc.Class.extend(/** @lends cc.TMXLayerInfo# */{
* This information is obtained from the TMX file.
* @class
* @extends cc.Class
+ *
+ * @property {string} name - Tileset name
+ * @property {number} firstGid - First grid
+ * @property {number} spacing - Spacing
+ * @property {number} margin - Margin
+ * @property {string} sourceImage - Filename containing the tiles (should be sprite sheet / texture atlas)
+ * @property {cc.Size|null} imageSize - Size in pixels of the image
*/
cc.TMXTilesetInfo = cc.Class.extend(/** @lends cc.TMXTilesetInfo# */{
- /**
- * Tileset name
- */
+ //Tileset name
name:"",
- /**
- * First grid
- */
+ //First grid
firstGid:0,
_tileSize:null,
- /**
- * Spacing
- */
+ //Spacing
spacing:0,
- /**
- * Margin
- */
+ //Margin
margin:0,
- /**
- * Filename containing the tiles (should be sprite sheet / texture atlas)
- */
+ //Filename containing the tiles (should be sprite sheet / texture atlas)
sourceImage:"",
- /**
- * Size in pixels of the image
- */
+ //Size in pixels of the image
imageSize:null,
ctor:function () {
- this._tileSize = cc.SizeZero();
- this.imageSize = cc.SizeZero();
+ this._tileSize = cc.size(0, 0);
+ this.imageSize = cc.size(0, 0);
},
/**
+ * Return rect
* @param {Number} gid
* @return {cc.Rect}
*/
- rectForGID:function (gid) {
- var rect = cc.RectZero();
- rect.size = this._tileSize;
+ rectForGID:function (gid, result) {
+ var rect = result || cc.rect(0, 0, 0, 0);
+ rect.width = this._tileSize.width;
+ rect.height = this._tileSize.height;
gid &= cc.TMX_TILE_FLIPPED_MASK;
gid = gid - parseInt(this.firstGid, 10);
var max_x = parseInt((this.imageSize.width - this.margin * 2 + this.spacing) / (this._tileSize.width + this.spacing), 10);
- rect.origin.x = parseInt((gid % max_x) * (this._tileSize.width + this.spacing) + this.margin, 10);
- rect.origin.y = parseInt(parseInt(gid / max_x, 10) * (this._tileSize.height + this.spacing) + this.margin, 10);
+ rect.x = parseInt((gid % max_x) * (this._tileSize.width + this.spacing) + this.margin, 10);
+ rect.y = parseInt(parseInt(gid / max_x, 10) * (this._tileSize.height + this.spacing) + this.margin, 10);
return rect;
}
});
@@ -245,50 +226,92 @@ cc.TMXTilesetInfo = cc.Class.extend(/** @lends cc.TMXTilesetInfo# */{
*
* This information is obtained from the TMX file.
* @class
- * @extends cc.SAXParser
+ * @extends cc.saxParser
+ *
+ * @property {Array} properties - Properties of the map info.
+ * @property {Number} orientation - Map orientation.
+ * @property {Object} parentElement - Parent element.
+ * @property {Number} parentGID - Parent GID.
+ * @property {Object} layerAttrs - Layer attributes.
+ * @property {Boolean} storingCharacters - Is reading storing characters stream.
+ * @property {String} tmxFileName - TMX file name.
+ * @property {String} currentString - Current string stored from characters stream.
+ * @property {Number} mapWidth - Width of the map
+ * @property {Number} mapHeight - Height of the map
+ * @property {Number} tileWidth - Width of a tile
+ * @property {Number} tileHeight - Height of a tile
+ *
+ * @param {String} tmxFile fileName or content string
+ * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required.
+ * @example
+ * 1.
+ * //create a TMXMapInfo with file name
+ * var tmxMapInfo = new cc.TMXMapInfo("res/orthogonal-test1.tmx");
+ * 2.
+ * //create a TMXMapInfo with content string and resource path
+ * var resources = "res/TileMaps";
+ * var filePath = "res/TileMaps/orthogonal-test1.tmx";
+ * var xmlStr = cc.loader.getRes(filePath);
+ * var tmxMapInfo = new cc.TMXMapInfo(xmlStr, resources);
*/
cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
- // map orientation
- _orientation:null,
+ properties:null,
+ orientation:null,
+ parentElement:null,
+ parentGID:null,
+ layerAttrs:0,
+ storingCharacters:false,
+ tmxFileName:null,
+ currentString:null,
+
+ _objectGroups:null,
_mapSize:null,
_tileSize:null,
_layers:null,
- _tileSets:null,
- _objectGroups:null,
- _parentElement:null,
- _parentGID:null,
- _layerAttribs:0,
- _storingCharacters:false,
- _properties:null,
- // tmx filename
- _TMXFileName:null,
- //current string
- _currentString:null,
+ _tilesets:null,
// tile properties
_tileProperties:null,
_resources:"",
_currentFirstGID:0,
- ctor:function () {
- this._tileSets = [];
- this._tileProperties = [];
- this._properties = [];
- this._mapSize = cc.SizeZero();
- this._tileSize = cc.SizeZero();
+ /**
+ * Creates a TMX Format with a tmx file or content string
+ * Constructor of cc.TMXMapInfo
+ * @param {String} tmxFile fileName or content string
+ * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required.
+ */
+ ctor:function (tmxFile, resourcePath) {
+ cc.SAXParser.prototype.ctor.apply(this);
+ this._mapSize = cc.size(0, 0);
+ this._tileSize = cc.size(0, 0);
+ this._layers = [];
+ this._tilesets = [];
+ this._objectGroups = [];
+ this.properties = [];
+ this._tileProperties = {};
+
this._currentFirstGID = 0;
+
+ if (resourcePath !== undefined) {
+ this.initWithXML(tmxFile,resourcePath);
+ } else if(tmxFile !== undefined){
+ this.initWithTMXFile(tmxFile);
+ }
},
/**
+ * Gets Map orientation.
* @return {Number}
*/
getOrientation:function () {
- return this._orientation;
+ return this.orientation;
},
/**
- * @param {Number} Var
+ * Set the Map orientation.
+ * @param {Number} value
*/
- setOrientation:function (Var) {
- this._orientation = Var;
+ setOrientation:function (value) {
+ this.orientation = value;
},
/**
@@ -300,13 +323,27 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
},
/**
- * @param {cc.Size} Var
+ * Map width & height
+ * @param {cc.Size} value
*/
- setMapSize:function (Var) {
- this._mapSize.width = Var.width;
- this._mapSize.height = Var.height;
+ setMapSize:function (value) {
+ this._mapSize.width = value.width;
+ this._mapSize.height = value.height;
},
+ _getMapWidth: function () {
+ return this._mapSize.width;
+ },
+ _setMapWidth: function (width) {
+ this._mapSize.width = width;
+ },
+ _getMapHeight: function () {
+ return this._mapSize.height;
+ },
+ _setMapHeight: function (height) {
+ this._mapSize.height = height;
+ },
+
/**
* Tiles width & height
* @return {cc.Size}
@@ -316,13 +353,27 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
},
/**
- * @param {cc.Size} Var
+ * Tiles width & height
+ * @param {cc.Size} value
*/
- setTileSize:function (Var) {
- this._tileSize.width = Var.width;
- this._tileSize.height = Var.height;
+ setTileSize:function (value) {
+ this._tileSize.width = value.width;
+ this._tileSize.height = value.height;
},
+ _getTileWidth: function () {
+ return this._tileSize.width;
+ },
+ _setTileWidth: function (width) {
+ this._tileSize.width = width;
+ },
+ _getTileHeight: function () {
+ return this._tileSize.height;
+ },
+ _setTileHeight: function (height) {
+ this._tileSize.height = height;
+ },
+
/**
* Layers
* @return {Array}
@@ -332,10 +383,11 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
},
/**
- * @param {cc.TMXLayerInfo} Var
+ * Layers
+ * @param {cc.TMXLayerInfo} value
*/
- setLayers:function (Var) {
- this._layers.push(Var);
+ setLayers:function (value) {
+ this._layers.push(value);
},
/**
@@ -343,14 +395,15 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
* @return {Array}
*/
getTilesets:function () {
- return this._tileSets;
+ return this._tilesets;
},
/**
- * @param {cc.TMXTilesetInfo} Var
+ * tilesets
+ * @param {cc.TMXTilesetInfo} value
*/
- setTilesets:function (Var) {
- this._tileSets.push(Var);
+ setTilesets:function (value) {
+ this._tilesets.push(value);
},
/**
@@ -362,25 +415,27 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
},
/**
- * @param {cc.TMXObjectGroup} Var
+ * ObjectGroups
+ * @param {cc.TMXObjectGroup} value
*/
- setObjectGroups:function (Var) {
- this._objectGroups.push(Var);
+ setObjectGroups:function (value) {
+ this._objectGroups.push(value);
},
/**
* parent element
- * @return {Number}
+ * @return {Object}
*/
getParentElement:function () {
- return this._parentElement;
+ return this.parentElement;
},
/**
- * @param {Number} Var
+ * parent element
+ * @param {Object} value
*/
- setParentElement:function (Var) {
- this._parentElement = Var;
+ setParentElement:function (value) {
+ this.parentElement = value;
},
/**
@@ -388,44 +443,47 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
* @return {Number}
*/
getParentGID:function () {
- return this._parentGID;
+ return this.parentGID;
},
/**
- * @param {Number} Var
+ * parent GID
+ * @param {Number} value
*/
- setParentGID:function (Var) {
- this._parentGID = Var;
+ setParentGID:function (value) {
+ this.parentGID = value;
},
/**
- * layer attribute
- * @return {Number}
+ * Layer attribute
+ * @return {Object}
*/
getLayerAttribs:function () {
- return this._layerAttribs;
+ return this.layerAttrs;
},
/**
- * @param {Number} Var
+ * Layer attribute
+ * @param {Object} value
*/
- setLayerAttribs:function (Var) {
- this._layerAttribs = Var;
+ setLayerAttribs:function (value) {
+ this.layerAttrs = value;
},
/**
- * is string characters?
+ * Is reading storing characters stream
* @return {Boolean}
*/
getStoringCharacters:function () {
- return this._storingCharacters;
+ return this.storingCharacters;
},
/**
- * @param {Boolean} Var
+ * Is reading storing characters stream
+ * @param {Boolean} value
*/
- setStoringCharacters:function (Var) {
- this._storingCharacters = Var;
+ setStoringCharacters:function (value) {
+ this.storingCharacters = value;
},
/**
@@ -433,26 +491,25 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
* @return {Array}
*/
getProperties:function () {
- return this._properties;
+ return this.properties;
},
/**
- * @param {object} Var
+ * Properties
+ * @param {object} value
*/
- setProperties:function (Var) {
- this._properties.push(Var);
+ setProperties:function (value) {
+ this.properties = value;
},
/**
* Initializes a TMX format with a tmx file
* @param {String} tmxFile
- * @param {String} resourcePath
* @return {Element}
*/
- initWithTMXFile:function (tmxFile, resourcePath) {
- this._internalInit(tmxFile, resourcePath);
- return this.parseXMLFile(this._TMXFileName);
- //return this.parseXMLFile(cc.FileUtils.getInstance().fullPathForFilename(this._TMXFileName));
+ initWithTMXFile:function (tmxFile) {
+ this._internalInit(tmxFile, null);
+ return this.parseXMLFile(tmxFile);
},
/**
@@ -473,8 +530,10 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
*/
parseXMLFile:function (tmxFile, isXmlString) {
isXmlString = isXmlString || false;
- tmxFile = cc.FileUtils.getInstance().fullPathForFilename(tmxFile);
- var mapXML = cc.SAXParser.getInstance().tmxParse(tmxFile, isXmlString);
+ var xmlStr = isXmlString ? tmxFile : cc.loader.getRes(tmxFile);
+ if(!xmlStr) throw new Error("Please load the resource first : " + tmxFile);
+
+ var mapXML = this._parseXML(xmlStr);
var i, j;
// PARSE
@@ -483,18 +542,18 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
var version = map.getAttribute('version');
var orientationStr = map.getAttribute('orientation');
- if (map.nodeName == "map") {
- if (version != "1.0" && version !== null)
+ if (map.nodeName === "map") {
+ if (version !== "1.0" && version !== null)
cc.log("cocos2d: TMXFormat: Unsupported TMX version:" + version);
- if (orientationStr == "orthogonal")
- this.setOrientation(cc.TMX_ORIENTATION_ORTHO);
- else if (orientationStr == "isometric")
- this.setOrientation(cc.TMX_ORIENTATION_ISO);
- else if (orientationStr == "hexagonal")
- this.setOrientation(cc.TMX_ORIENTATION_HEX);
+ if (orientationStr === "orthogonal")
+ this.orientation = cc.TMX_ORIENTATION_ORTHO;
+ else if (orientationStr === "isometric")
+ this.orientation = cc.TMX_ORIENTATION_ISO;
+ else if (orientationStr === "hexagonal")
+ this.orientation = cc.TMX_ORIENTATION_HEX;
else if (orientationStr !== null)
- cc.log("cocos2d: TMXFomat: Unsupported orientation:" + this.getOrientation());
+ cc.log("cocos2d: TMXFomat: Unsupported orientation:" + orientationStr);
var mapSize = cc.size(0, 0);
mapSize.width = parseFloat(map.getAttribute('width'));
@@ -509,11 +568,11 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
// The parent element is the map
var propertyArr = map.querySelectorAll("map > properties > property");
if (propertyArr) {
+ var aPropertyDict = {};
for (i = 0; i < propertyArr.length; i++) {
- var aProperty = {};
- aProperty[propertyArr[i].getAttribute('name')] = propertyArr[i].getAttribute('value');
- this.setProperties(aProperty);
+ aPropertyDict[propertyArr[i].getAttribute('name')] = propertyArr[i].getAttribute('value');
}
+ this.properties = aPropertyDict;
}
}
@@ -527,10 +586,11 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
for (i = 0; i < tilesets.length; i++) {
var selTileset = tilesets[i];
// If this is an external tileset then start parsing that
- var externalTilesetFilename = selTileset.getAttribute('source');
- if (externalTilesetFilename) {
+ var tsxName = selTileset.getAttribute('source');
+ if (tsxName) {
//this._currentFirstGID = parseInt(selTileset.getAttribute('firstgid'));
- this.parseXMLFile(cc.FileUtils.getInstance().fullPathFromRelativeFile(externalTilesetFilename, isXmlString ? this._resources + "/" : tmxFile));
+ var tsxPath = isXmlString ? cc.path.join(this._resources, tsxName) : cc.path.changeBasename(tmxFile, tsxName);
+ this.parseXMLFile(tsxPath);
} else {
var tileset = new cc.TMXTilesetInfo();
tileset.name = selTileset.getAttribute('name') || "";
@@ -553,34 +613,32 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
var image = selTileset.getElementsByTagName('image')[0];
var imagename = image.getAttribute('source');
var num = -1;
- if(this._TMXFileName)
- num = this._TMXFileName.lastIndexOf("/");
+ if(this.tmxFileName)
+ num = this.tmxFileName.lastIndexOf("/");
if (num !== -1) {
- var dir = this._TMXFileName.substr(0, num + 1);
+ var dir = this.tmxFileName.substr(0, num + 1);
tileset.sourceImage = dir + imagename;
} else {
tileset.sourceImage = this._resources + (this._resources ? "/" : "") + imagename;
}
this.setTilesets(tileset);
- }
- }
- // PARSE
- var tiles = map.querySelectorAll('tile');
- if (tiles) {
- for (i = 0; i < tiles.length; i++) {
- var info = this._tileSets[0];
- var t = tiles[i];
- this.setParentGID(parseInt(info.firstGid) + parseInt(t.getAttribute('id') || 0));
- var tp = t.querySelectorAll("properties > property");
- if (tp) {
- var dict = {};
- for (j = 0; j < tp.length; j++) {
- var name = tp[j].getAttribute('name');
- var value = tp[j].getAttribute('value');
- dict[name] = value;
+ // PARSE
+ var tiles = selTileset.getElementsByTagName('tile');
+ if (tiles) {
+ for (var tIdx = 0; tIdx < tiles.length; tIdx++) {
+ var t = tiles[tIdx];
+ this.parentGID = parseInt(tileset.firstGid) + parseInt(t.getAttribute('id') || 0);
+ var tp = t.querySelectorAll("properties > property");
+ if (tp) {
+ var dict = {};
+ for (j = 0; j < tp.length; j++) {
+ var name = tp[j].getAttribute('name');
+ dict[name] = tp[j].getAttribute('value');
+ }
+ this._tileProperties[this.parentGID] = dict;
+ }
}
- this._tileProperties[this.getParentGID()] = dict;
}
}
}
@@ -620,35 +678,44 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
// Unpack the tilemap data
var compression = data.getAttribute('compression');
var encoding = data.getAttribute('encoding');
- cc.Assert(compression == null || compression === "gzip" || compression === "zlib", "TMX: unsupported compression method");
+ if(compression && compression !== "gzip" && compression !== "zlib"){
+ cc.log("cc.TMXMapInfo.parseXMLFile(): unsupported compression method");
+ return null;
+ }
+ var tiles;
switch (compression) {
case 'gzip':
- layer._tiles = cc.unzipBase64AsArray(nodeValue, 4);
+ tiles = cc.unzipBase64AsArray(nodeValue, 4);
break;
case 'zlib':
var inflator = new Zlib.Inflate(cc.Codec.Base64.decodeAsArray(nodeValue, 1));
- layer._tiles = cc.uint8ArrayToUint32Array(inflator.decompress());
+ tiles = cc.uint8ArrayToUint32Array(inflator.decompress());
break;
case null:
case '':
// Uncompressed
- if (encoding == "base64")
- layer._tiles = cc.Codec.Base64.decodeAsArray(nodeValue, 4);
+ if (encoding === "base64")
+ tiles = cc.Codec.Base64.decodeAsArray(nodeValue, 4);
else if (encoding === "csv") {
- layer._tiles = [];
+ tiles = [];
var csvTiles = nodeValue.split(',');
for (var csvIdx = 0; csvIdx < csvTiles.length; csvIdx++)
- layer._tiles.push(parseInt(csvTiles[csvIdx]));
+ tiles.push(parseInt(csvTiles[csvIdx]));
} else {
//XML format
var selDataTiles = data.getElementsByTagName("tile");
- layer._tiles = [];
+ tiles = [];
for (var xmlIdx = 0; xmlIdx < selDataTiles.length; xmlIdx++)
- layer._tiles.push(parseInt(selDataTiles[xmlIdx].getAttribute("gid")));
+ tiles.push(parseInt(selDataTiles[xmlIdx].getAttribute("gid")));
}
break;
default:
- cc.Assert(this.getLayerAttribs() != cc.TMX_LAYER_ATTRIB_NONE, "TMX tile map: Only base64 and/or gzip/zlib maps are supported");
+ if(this.layerAttrs === cc.TMXLayerInfo.ATTRIB_NONE)
+ cc.log("cc.TMXMapInfo.parseXMLFile(): Only base64 and/or gzip/zlib maps are supported");
+ break;
+ }
+ if (tiles) {
+ layer._tiles = new Uint32Array(tiles);
}
// The parent element is the last layer
@@ -658,7 +725,7 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
for (j = 0; j < layerProps.length; j++) {
layerProp[layerProps[j].getAttribute('name')] = layerProps[j].getAttribute('value');
}
- layer.setProperties(layerProp);
+ layer.properties = layerProp;
}
this.setLayers(layer);
}
@@ -670,7 +737,7 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
for (i = 0; i < objectGroups.length; i++) {
var selGroup = objectGroups[i];
var objectGroup = new cc.TMXObjectGroup();
- objectGroup.setGroupName(selGroup.getAttribute('name'));
+ objectGroup.groupName = selGroup.getAttribute('name');
objectGroup.setPositionOffset(cc.p(parseFloat(selGroup.getAttribute('x')) * this.getTileSize().width || 0,
parseFloat(selGroup.getAttribute('y')) * this.getTileSize().height || 0));
@@ -680,11 +747,12 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
var groupProp = {};
groupProp[groupProps[j].getAttribute('name')] = groupProps[j].getAttribute('value');
// Add the property to the layer
- objectGroup.setProperties(groupProp);
+ objectGroup.properties = groupProp;
}
}
var objects = selGroup.querySelectorAll('object');
+ var getContentScaleFactor = cc.director.getContentScaleFactor();
if (objects) {
for (j = 0; j < objects.length; j++) {
var selObj = objects[j];
@@ -698,14 +766,15 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
// Assign all the attributes as key/name pairs in the properties dictionary
objectProp["type"] = selObj.getAttribute('type') || "";
- objectProp["x"] = parseInt(selObj.getAttribute('x') || 0) + objectGroup.getPositionOffset().x;
- var y = parseInt(selObj.getAttribute('y') || 0) + objectGroup.getPositionOffset().y;
-
objectProp["width"] = parseInt(selObj.getAttribute('width')) || 0;
objectProp["height"] = parseInt(selObj.getAttribute('height')) || 0;
+ objectProp["x"] = (((selObj.getAttribute('x') || 0) | 0) + objectGroup.getPositionOffset().x) / getContentScaleFactor;
+ var y = ((selObj.getAttribute('y') || 0) | 0) + objectGroup.getPositionOffset().y / getContentScaleFactor;
// Correct y position. (Tiled uses Flipped, cocos2d uses Standard)
- objectProp["y"] = parseInt(this.getMapSize().height * this.getTileSize().height) - y - objectProp["height"];
+ objectProp["y"] = (parseInt(this.getMapSize().height * this.getTileSize().height) - y - objectProp["height"]) / cc.director.getContentScaleFactor();
+
+ objectProp["rotation"] = parseInt(selObj.getAttribute('rotation')) || 0;
var docObjProps = selObj.querySelectorAll("properties > property");
if (docObjProps) {
@@ -718,7 +787,7 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
if(polygonProps && polygonProps.length > 0) {
var selPgPointStr = polygonProps[0].getAttribute('points');
if(selPgPointStr)
- objectProp["polygonPoints"] = this._parsePointsString(selPgPointStr);
+ objectProp["points"] = this._parsePointsString(selPgPointStr);
}
//polyline
@@ -763,6 +832,7 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
},
/**
+ * Gets the tile properties.
* @return {object}
*/
getTileProperties:function () {
@@ -770,6 +840,7 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
},
/**
+ * Set the tile properties.
* @param {object} tileProperties
*/
setTileProperties:function (tileProperties) {
@@ -777,80 +848,107 @@ cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{
},
/**
+ * Gets the currentString
* @return {String}
*/
getCurrentString:function () {
- return this._currentString;
+ return this.currentString;
},
/**
+ * Set the currentString
* @param {String} currentString
*/
setCurrentString:function (currentString) {
- this._currentString = currentString;
+ this.currentString = currentString;
},
/**
+ * Gets the tmxFileName
* @return {String}
*/
getTMXFileName:function () {
- return this._TMXFileName;
+ return this.tmxFileName;
},
/**
+ * Set the tmxFileName
* @param {String} fileName
*/
setTMXFileName:function (fileName) {
- this._TMXFileName = fileName;
+ this.tmxFileName = fileName;
},
_internalInit:function (tmxFileName, resourcePath) {
- this._tileSets = [];
- this._layers = [];
-
- //this._TMXFileName = cc.FileUtils.getInstance().fullPathForFilename(tmxFileName);
- this._TMXFileName = tmxFileName;
+ this._tilesets.length = 0;
+ this._layers.length = 0;
- if (resourcePath) {
+ this.tmxFileName = tmxFileName;
+ if (resourcePath)
this._resources = resourcePath;
- }
-
- this._objectGroups = [];
- this._properties = [];
- this._tileProperties = [];
+ this._objectGroups.length = 0;
+ this.properties.length = 0;
+ this._tileProperties.length = 0;
// tmp vars
- this._currentString = "";
- this._storingCharacters = false;
- this._layerAttribs = cc.TMX_LAYER_ATTRIB_NONE;
- this._parentElement = cc.TMX_PROPERTY_NONE;
+ this.currentString = "";
+ this.storingCharacters = false;
+ this.layerAttrs = cc.TMXLayerInfo.ATTRIB_NONE;
+ this.parentElement = cc.TMX_PROPERTY_NONE;
this._currentFirstGID = 0;
}
});
+var _p = cc.TMXMapInfo.prototype;
+
+// Extended properties
+/** @expose */
+_p.mapWidth;
+cc.defineGetterSetter(_p, "mapWidth", _p._getMapWidth, _p._setMapWidth);
+/** @expose */
+_p.mapHeight;
+cc.defineGetterSetter(_p, "mapHeight", _p._getMapHeight, _p._setMapHeight);
+/** @expose */
+_p.tileWidth;
+cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth);
+/** @expose */
+_p.tileHeight;
+cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight);
+
+
/**
- * Creates a TMX Format with a tmx file
- * @param {String} tmxFile
- * @param {String} resourcePath
+ * Creates a TMX Format with a tmx file or content string
+ * @deprecated since v3.0 please use new cc.TMXMapInfo(tmxFile, resourcePath) instead.
+ * @param {String} tmxFile fileName or content string
+ * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required.
* @return {cc.TMXMapInfo}
*/
cc.TMXMapInfo.create = function (tmxFile, resourcePath) {
- var ret = new cc.TMXMapInfo();
- if (ret.initWithTMXFile(tmxFile, resourcePath))
- return ret;
- return null;
+ return new cc.TMXMapInfo(tmxFile, resourcePath);
};
+
+cc.loader.register(["tmx", "tsx"], cc._txtLoader);
+
+
/**
- * creates a TMX Format with an XML string and a TMX resource path
- * @param {String} tmxString
- * @param {String} resourcePath
- * @return {cc.TMXMapInfo}
+ * @constant
+ * @type Number
*/
-cc.TMXMapInfo.createWithXML = function (tmxString, resourcePath) {
- var ret = new cc.TMXMapInfo();
- if (ret.initWithXML(tmxString, resourcePath))
- return ret;
- return null;
-};
+cc.TMXLayerInfo.ATTRIB_NONE = 1 << 0;
+/**
+ * @constant
+ * @type Number
+ */
+cc.TMXLayerInfo.ATTRIB_BASE64 = 1 << 1;
+/**
+ * @constant
+ * @type Number
+ */
+cc.TMXLayerInfo.ATTRIB_GZIP = 1 << 2;
+/**
+ * @constant
+ * @type Number
+ */
+cc.TMXLayerInfo.ATTRIB_ZLIB = 1 << 3;
diff --git a/cocos2d/touch_dispatcher/CCMouseDispatcher.js b/cocos2d/touch_dispatcher/CCMouseDispatcher.js
deleted file mode 100644
index 32749b950c..0000000000
--- a/cocos2d/touch_dispatcher/CCMouseDispatcher.js
+++ /dev/null
@@ -1,593 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_DOWN = 1 << 0;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_MOVED = 1 << 1;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_DRAGGED = 1 << 2;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_UP = 1 << 3;
-
-/**
- * @constant
- * @type Number
- */
-cc.RIGHT_MOUSE_DOWN = 1 << 4;
-
-/**
- * @constant
- * @type Number
- */
-cc.RIGHT_MOUSE_DRAGGED = 1 << 5;
-
-/**
- * @constant
- * @type Number
- */
-cc.RIGHT_MOUSE_UP = 1 << 6;
-
-/**
- * @constant
- * @type Number
- */
-cc.OTHER_MOUSE_DOWN = 1 << 7;
-
-/**
- * @constant
- * @type Number
- */
-cc.OTHER_MOUSE_DRAGGED = 1 << 8;
-
-/**
- * @constant
- * @type Number
- */
-cc.OTHER_MOUSE_UP = 1 << 9;
-
-/**
- * @constant
- * @type Number
- */
-cc.SCROLL_WHEEL = 1 << 10;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_ENTERED = 1 << 11;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_EXITED = 1 << 12;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_LEFTBUTTON = 0;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_MIDDLEBUTTON = 1;
-
-/**
- * @constant
- * @type Number
- */
-cc.MOUSE_RIGHTBUTTON = 2;
-
-/**
- * CCMouseEventDelegate protocol.
- * Implement it in your node to receive any of mouse events
- */
-cc.MouseEventDelegate = cc.Class.extend({
- /**
- * called when the "mouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseMoved" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onMouseMoved:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onMouseUp:function (event) {
- return false;
- },
-
- //right
- /**
- * called when the "rightMouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onRightMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "rightMouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onRightMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "rightMouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onRightMouseUp:function (event) {
- return false;
- },
-
- //other
- /**
- * called when the "otherMouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onOtherMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "otherMouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onOtherMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "otherMouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onOtherMouseUp:function (event) {
- return false;
- },
-
- //scroll wheel
- /**
- * called when the "scrollWheel" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} event
- * @return {Boolean}
- */
- onScrollWheel:function (event) {
- return false;
- },
-
- // enter / exit
- /**
- * called when the "mouseEntered" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} theEvent
- * @return {Boolean}
- */
- onMouseEntered:function (theEvent) {
- return false;
- },
-
- /**
- * called when the "mouseExited" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param {cc.Mouse} theEvent
- * @return {Boolean}
- */
- onMouseExited:function (theEvent) {
- return false;
- }
-});
-
-cc.Mouse = cc.Touch.extend({
- _wheelDelta:0,
- _button:cc.MOUSE_LEFTBUTTON,
-
- getWheelDelta:function () {
- return this._wheelDelta;
- },
-
- setWheelDelta:function (delta) {
- this._wheelDelta = delta;
- },
-
- getButton:function () {
- return this._button;
- },
-
- setButton:function (button) {
- this._button = button;
- }
-});
-
-/**
- * cc.MouseHandler
- * Object than contains the delegate and priority of the event handler.
- * @class
- * @extends cc.Class
- */
-cc.MouseHandler = cc.Class.extend(/** @lends cc.MouseHandler# */{
- _delegate:null,
- _priority:0,
- _enabledSelectors:0,
-
- /**
- * @return {cc.MouseEventDelegate}
- */
- getDelegate:function () {
- return this._delegate;
- },
-
- /**
- * @param {cc.TouchDelegate} delegate
- */
- setDelegate:function (delegate) {
- this._delegate = delegate;
- },
-
- /**
- * @return {Number}
- */
- getPriority:function () {
- return this._priority;
- },
-
- /**
- * @param {Number} priority
- */
- setPriority:function (priority) {
- this._priority = priority;
- },
-
- /**
- * Enabled selectors
- * @return {Number}
- */
- getEnabledSelectors:function () {
- return this._enabledSelectors;
- },
-
- /**
- * @param {Number} value
- */
- setEnalbedSelectors:function (value) {
- this._enabledSelectors = value;
- },
-
- initWithDelegate:function (delegate, priority) {
- this._delegate = delegate;
- this._priority = priority;
- }
-});
-
-cc.MouseHandler.create = function (delegate, priority) {
- var handler = new cc.MouseHandler();
- handler.initWithDelegate(delegate, priority);
- return handler;
-};
-
-cc.MouseDispatcher = cc.Class.extend({
- _mousePressed:false,
- _rightMousePressed:false,
- _mouseDelegateHandlers:null,
- _dispatchEvents:false,
-
- init:function () {
- this._dispatchEvents = true;
- this._mouseDelegateHandlers = [];
- this._mousePressed = false;
- this._rightMousePressed = false;
-
- cc.MouseDispatcher._registerHtmlElementEvent(cc.canvas);
- return true;
- },
-
- _setMousePressed:function (pressed) {
- this._mousePressed = pressed;
- },
-
- _getMousePressed:function () {
- return this._mousePressed;
- },
-
- _setRightMousePressed:function (pressed) {
- this._rightMousePressed = pressed;
- },
-
- _getRightMousePressed:function () {
- return this._rightMousePressed;
- },
-
- /**
- * Adds a mouse delegate to the dispatcher's list.
- * Delegates with a lower priority value will be called before higher priority values.
- * All the events will be propagated to all the delegates, unless the one delegate returns YES.
- * @param delegate
- * @param priority
- */
- addMouseDelegate:function (delegate, priority) {
- var handler = cc.MouseHandler.create(delegate, priority);
-
- this._mouseDelegateHandlers = this.forceAddHandler(handler, this._mouseDelegateHandlers);
- },
-
- /**
- * Force add handler
- * @param {cc.TouchHandler} handler
- * @param {Array} array
- * @return {Array}
- */
- forceAddHandler:function (handler, array) {
- var u = 0;
-
- for (var i = 0; i < array.length; i++) {
- var h = array[i];
- if (h) {
- if (h.getPriority() < handler.getPriority()) {
- ++u;
- }
- if (h.getDelegate() == handler.getDelegate()) {
- cc.Assert(0, "TouchDispatcher.forceAddHandler()");
- return array;
- }
- }
- }
- return cc.ArrayAppendObjectToIndex(array, handler, u);
- },
-
- /**
- * removes a mouse delegate
- * @param delegate
- */
- removeMouseDelegate:function (delegate) {
- if (delegate == null)
- return;
-
- for (var i = 0; i < this._mouseDelegateHandlers.length; i++) {
- var handler = this._mouseDelegateHandlers[i];
- if (handler && handler.getDelegate() == delegate) {
- cc.ArrayRemoveObject(this._mouseDelegateHandlers, handler);
- break;
- }
- }
- },
-
- _findHandler:function (delegate) {
- for (var i = 0; i < this._mouseDelegateHandlers.length; i++) {
- if (this._mouseDelegateHandlers[i] && this._mouseDelegateHandlers[i].getDelegate() == delegate) {
- return this._mouseDelegateHandlers[i];
- }
- }
- return null;
- },
-
- setPriority:function (priority, delegate) {
- cc.Assert(delegate != null, "MouseDispatcher.setPriority():Arguments is null");
- var handler = this._findHandler(delegate);
- cc.Assert(handler != null, "MouseDispatcher.setPriority():Cant find MouseHandler");
-
- if (handler.getPriority() != priority) {
- handler.setPriority(priority);
- this._mouseDelegateHandlers.sort(cc.less);
- }
- },
-
- /**
- * Removes all mouse delegates, releasing all the delegates
- */
- removeAllMouseDelegates:function () {
- this._mouseDelegateHandlers.length = 0;
- },
-
- mouseHandle:function (mouseObj, event, index) {
- for (var i = 0; i < this._mouseDelegateHandlers.length; i++) {
- var handler = this._mouseDelegateHandlers[i];
-
- switch (index) {
- case cc.MOUSE_DOWN:
- if (mouseObj.getButton() == cc.MOUSE_RIGHTBUTTON) {
- if (handler.getDelegate().onRightMouseDown)
- handler.getDelegate().onRightMouseDown(mouseObj);
- } else {
- if (handler.getDelegate().onMouseDown)
- handler.getDelegate().onMouseDown(mouseObj);
- }
- break;
- case cc.MOUSE_UP:
- if (mouseObj.getButton() == cc.MOUSE_RIGHTBUTTON) {
- if (handler.getDelegate().onRightMouseUp)
- handler.getDelegate().onRightMouseUp(mouseObj);
- } else {
- if (handler.getDelegate().onMouseUp)
- handler.getDelegate().onMouseUp(mouseObj);
- }
- break;
- case cc.MOUSE_MOVED:
- if (this._mousePressed) {
- if (handler.getDelegate().onMouseDragged)
- handler.getDelegate().onMouseDragged(mouseObj);
- } else if (this._rightMousePressed) {
- if (handler.getDelegate().onRightMouseDragged)
- handler.getDelegate().onRightMouseDragged(mouseObj);
- } else {
- if (handler.getDelegate().onMouseMoved)
- handler.getDelegate().onMouseMoved(mouseObj);
- }
- break;
- case cc.MOUSE_ENTERED:
- if (handler.getDelegate().onMouseEntered)
- handler.getDelegate().onMouseEntered(mouseObj);
- break;
- case cc.MOUSE_EXITED:
- if (handler.getDelegate().onMouseExited)
- handler.getDelegate().onMouseExited(mouseObj);
- break;
- case cc.SCROLL_WHEEL:
- if (handler.getDelegate().onScrollWheel)
- handler.getDelegate().onScrollWheel(mouseObj);
- break;
- }
- }
- }
-});
-
-cc.MouseDispatcher._preMousePoint = cc.p(0, 0);
-
-cc.MouseDispatcher._isRegisterEvent = false;
-
-cc.MouseDispatcher._registerHtmlElementEvent = function (element) {
- if (cc.MouseDispatcher._isRegisterEvent)
- return;
-
- window.addEventListener('mousedown', function (event) {
- if (event.button == cc.MOUSE_RIGHTBUTTON) {
- cc.Director.getInstance().getMouseDispatcher()._setRightMousePressed(true);
- } else {
- cc.Director.getInstance().getMouseDispatcher()._setMousePressed(true);
- }
- });
-
- window.addEventListener('mouseup', function (event) {
- if (event.button == cc.MOUSE_RIGHTBUTTON) {
- cc.Director.getInstance().getMouseDispatcher()._setRightMousePressed(false);
- } else {
- cc.Director.getInstance().getMouseDispatcher()._setMousePressed(false);
- }
- });
-
- function getMouseByEvent(event) {
- var pos = cc.getHTMLElementPosition(element);
-
- var tx = event.pageX;
- var ty = event.pageY;
- var eglViewer = cc.EGLView.getInstance();
-
- var mouseX = (tx - pos.left) / eglViewer.getScaleX();
- var mouseY = (pos.height - (ty - pos.top)) / eglViewer.getScaleY();
-
- var mouse = new cc.Mouse(mouseX, mouseY);
- mouse._setPrevPoint(cc.MouseDispatcher._preMousePoint.x, cc.MouseDispatcher._preMousePoint.y);
- mouse.setButton(event.button);
- cc.MouseDispatcher._preMousePoint.x = mouseX;
- cc.MouseDispatcher._preMousePoint.y = mouseY;
-
- return mouse;
- }
-
- //register canvas mouse event
- element.addEventListener("mousedown", function (event) {
- cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_DOWN);
- });
-
- element.addEventListener("mouseup", function (event) {
- cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_UP);
- });
-
- element.addEventListener("mousemove", function (event) {
- cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_MOVED);
- });
-
- element.addEventListener("mousewheel", function (event) {
- var mouse = getMouseByEvent(event);
- mouse.setWheelDelta(event.wheelDelta);
- cc.Director.getInstance().getMouseDispatcher().mouseHandle(mouse, event, cc.SCROLL_WHEEL);
- }, false);
-
- /* firefox fix */
- element.addEventListener("DOMMouseScroll", function(event) {
- var mouse = getMouseByEvent(event);
- mouse.setWheelDelta(event.detail * -120);
- cc.Director.getInstance().getMouseDispatcher().mouseHandle(mouse, event, cc.SCROLL_WHEEL);
- });
-
- element.addEventListener("mouseout", function (event) {
- cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_EXITED);
- }, false);
-
- element.addEventListener("mouseover", function (event) {
- cc.Director.getInstance().getMouseDispatcher().mouseHandle(getMouseByEvent(event), event, cc.MOUSE_ENTERED);
- }, false);
-};
-
-
diff --git a/cocos2d/touch_dispatcher/CCTouchDelegateProtocol.js b/cocos2d/touch_dispatcher/CCTouchDelegateProtocol.js
deleted file mode 100644
index fc2a42af7a..0000000000
--- a/cocos2d/touch_dispatcher/CCTouchDelegateProtocol.js
+++ /dev/null
@@ -1,277 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * @class
- * @extends cc.Class
- */
-cc.Touch = cc.Class.extend(/** @lends cc.Touch# */{
- _point:null,
- _prevPoint:cc.PointZero(),
- _id:0,
-
- /**
- * Constructor
- */
- ctor:function (x, y, id) {
- this._point = cc.p(x || 0, y || 0);
- this._id = id || 0;
- },
-
- /**
- * get point of touch
- * @return {cc.Point}
- */
- getLocation:function () {
- return this._point;
- },
-
- /**
- * @return {cc.Point}
- */
- getPreviousLocation:function () {
- return this._prevPoint;
- },
-
- /**
- * @return {cc.Point}
- */
- getDelta:function () {
- return cc.pSub(this._point, this._prevPoint);
- },
-
- /**
- * @return {Number}
- */
- getID:function () {
- return this._id;
- },
-
- /**
- * @return {Number}
- */
- getId:function () {
- return this._id;
- },
-
- /**
- * set information to touch
- * @param {Number} id
- * @param {Number} x
- * @param {Number} y
- */
- setTouchInfo:function (id, x, y) {
- this._prevPoint = this._point;
- this._point = cc.p(x || 0, y || 0);
- this._id = id;
- },
-
- _setPrevPoint:function (x, y) {
- this._prevPoint = cc.p(x || 0, y || 0);
- }
-});
-
-/**
- * @class
- * @extends cc.Class
- */
-cc.TouchDelegate = cc.Class.extend(/** @lends cc.TouchDelegate# */{
- _eventTypeFuncMap:null,
-
- /**
- * Virtual function
- * @param {cc.Touch} touch
- * @param {event} event
- * @return {Boolean}
- */
- onTouchBegan:function (touch, event) {
- return false;
- },
-
- /**
- * Virtual function
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchMoved:function (touch, event) {
- },
-
- /**
- * Virtual function
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchEnded:function (touch, event) {
- },
-
- /**
- * Virtual function
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchCancelled:function (touch, event) {
- },
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesBegan:function (touches, event) {
- },
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesMoved:function (touches, event) {
- },
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesEnded:function (touches, event) {
- },
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesCancelled:function (touches, event) {
- },
-
- /*
- * In TouchesTest, class Padle inherits from cc.Sprite and cc.TargetedTouchDelegate.
- * When it invoke cc.registerTargetedDelegate(0, true, this),
- * it will crash in cc.TouchHandler.initWithDelegate() because of dynamic_cast() on android.
- * I don't know why, so add these functions for the subclass to invoke it's own retain() and release
- *Virtual function
- */
- touchDelegateRetain:function () {
- },
-
- /**
- * Virtual function
- */
- touchDelegateRelease:function () {
- }
-});
-
-/**
- * Using this type of delegate results in two benefits:
- * - 1. You don't need to deal with cc.Sets, the dispatcher does the job of splitting
- * them. You get exactly one UITouch per call.
- * - 2. You can *claim* a UITouch by returning YES in onTouchBegan. Updates of claimed
- * touches are sent only to the delegate(s) that claimed them. So if you get a move/
- * ended/cancelled update you're sure it's your touch. This frees you from doing a
- * lot of checks when doing multi-touch.
- *
- * (The name TargetedTouchDelegate relates to updates "targeting" their specific
- * handler, without bothering the other handlers.)
- * @class
- * @extends cc.Class
- */
-cc.TargetedTouchDelegate = cc.TouchDelegate.extend(/** @lends cc.TargetedTouchDelegate# */{
-
- /**
- * Return YES to claim the touch.
- * @param {cc.Touch} touch
- * @param {event} event
- * @return {Boolean}
- */
- onTouchBegan:function (touch, event) {
- return false;
- },
-
- /**
- * Virtual function
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchMoved:function (touch, event) {
- },
-
- /**
- * Virtual function
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchEnded:function (touch, event) {
- },
-
- /**
- * Virtual function
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchCancelled:function (touch, event) {
- }
-});
-
-/**
- * This type of delegate is the same one used by CocoaTouch. You will receive all the events (Began,Moved,Ended,Cancelled).
- * @class
- * @extends cc.Class
- */
-cc.StandardTouchDelegate = cc.TouchDelegate.extend(/** @lends cc.StandardTouchDelegate# */{
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesBegan:function (touches, event) {
- },
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesMoved:function (touches, event) {
- },
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesEnded:function (touches, event) {
- },
-
- /**
- * Virtual function
- * @param {Array} touches
- * @param {event} event
- */
- onTouchesCancelled:function (touches, event) {
- }
-});
-
diff --git a/cocos2d/touch_dispatcher/CCTouchDispatcher.js b/cocos2d/touch_dispatcher/CCTouchDispatcher.js
deleted file mode 100644
index 08d208b5f3..0000000000
--- a/cocos2d/touch_dispatcher/CCTouchDispatcher.js
+++ /dev/null
@@ -1,1062 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * @constant
- * @type Number
- */
-cc.TouchSelectorBeganBit = 1 << 0;
-
-/**
- * @constant
- * @type Number
- */
-cc.TouchSelectorMovedBit = 1 << 1;
-
-/**
- * @constant
- * @type Number
- */
-cc.TouchSelectorEndedBit = 1 << 2;
-
-/**
- * @constant
- * @type Number
- */
-cc.TouchSelectorCancelledBit = 1 << 3;
-
-/**
- * @constant
- * @type Number
- */
-cc.TouchSelectorAllBits = (cc.TouchSelectorBeganBit | cc.TouchSelectorMovedBit | cc.TouchSelectorEndedBit | cc.TouchSelectorCancelledBit);
-
-/**
- * @constant
- * @type Number
- */
-cc.TOUCH_BEGAN = 0;
-
-/**
- * @constant
- * @type Number
- */
-cc.TOUCH_MOVED = 1;
-
-/**
- * @constant
- * @type Number
- */
-cc.TOUCH_ENDED = 2;
-
-/**
- * @constant
- * @type Number
- */
-cc.TOUCH_CANCELLED = 3;
-
-/**
- * @constant
- * @type Number
- */
-cc.TouchMax = 4;
-
-/**
- * @function
- * @param {cc.TouchHandler} p1
- * @param {cc.TouchHandler} p2
- * @return {Boolean}
- */
-cc.less = function (p1, p2) {
- return p1.getPriority() > p2.getPriority();
-};
-
-/**
- * @param {Number} type
- * Constructor
- */
-cc.TouchHandlerHelperData = function (type) {
- // we only use the type
- this.type = type;
-};
-
-/**
- * cc.TouchDispatcher.
- * Singleton that handles all the touch events.
- * The dispatcher dispatches events to the registered TouchHandlers.
- * There are 2 different type of touch handlers:
- * - Standard Touch Handlers
- * - Targeted Touch Handlers
- *
- * The Standard Touch Handlers work like the CocoaTouch touch handler: a set of touches is passed to the delegate.
- * On the other hand, the Targeted Touch Handlers only receive 1 touch at the time, and they can "swallow" touches (avoid the propagation of the event).
- *
- * Firstly, the dispatcher sends the received touches to the targeted touches.
- * These touches can be swallowed by the Targeted Touch Handlers. If there are still remaining touches, then the remaining touches will be sent
- * to the Standard Touch Handlers.
- * @class
- * @extends cc.Class
- */
-cc.TouchDispatcher = cc.Class.extend(/** @lends cc.TouchDispatcher# */ {
- _mousePressed:false,
- _targetedHandlers:null,
- _standardHandlers:null,
- _locked:false,
- _toAdd:false,
- _toRemove:false,
- _handlersToAdd:null,
- _handlersToRemove:null,
- _toQuit:false,
- _dispatchEvents:false,
- _handlerHelperData:[new cc.TouchHandlerHelperData(cc.TOUCH_BEGAN), new cc.TouchHandlerHelperData(cc.TOUCH_MOVED), new cc.TouchHandlerHelperData(cc.TOUCH_ENDED), new cc.TouchHandlerHelperData(cc.TOUCH_CANCELLED)],
-
- /**
- * @return {Boolean}
- */
- init:function () {
- this._dispatchEvents = true;
- this._targetedHandlers = [];
- this._standardHandlers = [];
- this._handlersToAdd = [];
- this._handlersToRemove = [];
- this._toRemove = false;
- this._toAdd = false;
- this._toQuit = false;
- this._locked = false;
- this._mousePressed = false;
- cc.TouchDispatcher.registerHtmlElementEvent(cc.canvas);
- return true;
- },
-
- _setMousePressed:function (pressed) {
- this._mousePressed = pressed;
- },
-
- _getMousePressed:function () {
- return this._mousePressed;
- },
-
- /**
- * Whether or not the events are going to be dispatched. Default: true
- * @return {Boolean}
- */
- isDispatchEvents:function () {
- return this._dispatchEvents;
- },
-
- /**
- * @param {Boolean} dispatchEvents
- */
- setDispatchEvents:function (dispatchEvents) {
- this._dispatchEvents = dispatchEvents;
- },
-
- /**
- * Adds a standard touch delegate to the dispatcher's list.
- * See StandardTouchDelegate description.
- * IMPORTANT: The delegate will be retained.
- * @param {Object} delegate
- * @param {Number} [priority=0]
- */
- _addStandardDelegate:function (delegate, priority) {
- priority = priority || 0;
- var handler = cc.StandardTouchHandler.create(delegate, priority);
-
- if (!this._locked) {
- this._standardHandlers = this.forceAddHandler(handler, this._standardHandlers);
- } else {
- /* If handler is contained in m_pHandlersToRemove, if so remove it from m_pHandlersToRemove and retrun.
- * Refer issue #752(cocos2d-x)
- */
- if (this._handlersToRemove.indexOf(delegate) != -1) {
- cc.ArrayRemoveObject(this._handlersToRemove, delegate);
- return;
- }
-
- this._handlersToAdd.push(handler);
- this._toAdd = true;
- }
- },
-
- /**
- * @param {Object} delegate
- * @param {Number} priority
- * @param {Boolean} swallowsTouches
- */
- _addTargetedDelegate:function (delegate, priority, swallowsTouches) {
- var handler = cc.TargetedTouchHandler.create(delegate, priority, swallowsTouches);
- if (!this._locked) {
- this._targetedHandlers = this.forceAddHandler(handler, this._targetedHandlers);
- } else {
- /* If handler is contained in m_pHandlersToRemove, if so remove it from m_pHandlersToRemove and retrun.
- * Refer issue #752(cocos2d-x)
- */
- if (this._handlersToRemove.indexOf(delegate) != -1) {
- cc.ArrayRemoveObject(this._handlersToRemove, delegate);
- return;
- }
-
- this._handlersToAdd.push(handler);
- this._toAdd = true;
- }
- },
-
- /**
- * Force add handler
- * @param {cc.TouchHandler} handler
- * @param {Array} array
- * @return {Array}
- */
- forceAddHandler:function (handler, array) {
- var u = 0, h;
-
- for (var i = 0; i < array.length; i++) {
- h = array[i];
- if (h) {
- if (h.getPriority() < handler.getPriority())
- ++u;
- if (h.getDelegate() == handler.getDelegate()) {
- cc.Assert(0, "The handler has been added.");
- return array;
- }
- }
- }
- return cc.ArrayAppendObjectToIndex(array, handler, u);
- },
-
- /**
- * Force remove all delegates
- */
- forceRemoveAllDelegates:function () {
- this._standardHandlers.length = 0;
- this._targetedHandlers.length = 0;
- },
-
- /**
- * Removes a touch delegate.
- * The delegate will be released
- * @param {cc.TouchDelegate} delegate
- */
- _removeDelegate:function (delegate) {
- if (delegate == null) {
- return;
- }
-
- if (!this._locked) {
- this.forceRemoveDelegate(delegate);
- } else {
- /*
- * If handler is contained in m_pHandlersToAdd, if so remove it from m_pHandlersToAdd and return.
- */
- var handler = this.findHandler(this._handlersToAdd, delegate);
- if (handler) {
- cc.ArrayRemoveObject(this._handlersToAdd, handler);
- return;
- }
-
- this._handlersToRemove.push(delegate);
- this._toRemove = true;
- }
- },
-
- /**
- * Removes all touch delegates, releasing all the delegates
- */
- removeAllDelegates:function () {
- if (!this._locked) {
- this.forceRemoveAllDelegates();
- } else {
- this._toQuit = true;
- }
- },
-
- /**
- * Changes the priority of a previously added delegate. The lower the number, the higher the priority
- * @param {Number} priority
- * @param {cc.TouchDelegate} delegate
- */
- setPriority:function (priority, delegate) {
- cc.Assert(delegate != null, "TouchDispatcher.setPriority():Arguments is null");
-
- var handler = this.findHandler(delegate);
-
- cc.Assert(handler != null, "TouchDispatcher.setPriority():Cant find TouchHandler");
-
- if (handler.getPriority() != priority) {
- handler.setPriority(priority);
-
- this.rearrangeHandlers(this._targetedHandlers);
- this.rearrangeHandlers(this._standardHandlers);
- }
- },
-
- /**
- * @param {Array} touches
- * @param {event} event
- * @param {Number} index
- */
- touches:function (touches, event, index) {
- cc.Assert(index >= 0 && index < 4, "TouchDispatcher.touches()");
-
- this._locked = true;
-
- // optimization to prevent a mutable copy when it is not necessary
- var targetedHandlersCount = this._targetedHandlers.length;
- var standardHandlersCount = this._standardHandlers.length;
- var needsMutableSet = (targetedHandlersCount && standardHandlersCount);
-
- var mutableTouches = (needsMutableSet ? touches.slice() : touches);
- var helper = this._handlerHelperData[index];
- //
- // process the target handlers 1st
- //
- if (targetedHandlersCount > 0) {
- var touch, handler, claimed;
- for (var i = 0; i < touches.length; i++) {
- touch = touches[i];
-
- for (var j = 0; j < this._targetedHandlers.length; j++) {
- handler = this._targetedHandlers[j];
-
- if (!handler) {
- break;
- }
-
- claimed = false;
- if (index == cc.TOUCH_BEGAN) {
- if (handler.getDelegate().onTouchBegan) {
- claimed = handler.getDelegate().onTouchBegan(touch, event);
-
- if (claimed) {
- handler.getClaimedTouches().push(touch);
- }
- }
- //} else if (handler.getClaimedTouches().indexOf(touch)> -1){
- } else if (handler.getClaimedTouches().length > 0) {
- // moved ended cancelled
- claimed = true;
- switch (helper.type) {
- case cc.TOUCH_MOVED:
- if (cc.Browser.isMobile) {
- if (handler.getDelegate().onTouchMoved) handler.getDelegate().onTouchMoved(touch, event);
- } else {
- if (this._mousePressed && handler.getDelegate().onTouchMoved) handler.getDelegate().onTouchMoved(touch, event);
- }
- break;
- case cc.TOUCH_ENDED:
- if (handler.getDelegate().onTouchEnded) handler.getDelegate().onTouchEnded(touch, event);
- handler.getClaimedTouches().length = 0;
- //cc.ArrayRemoveObject(handler.getClaimedTouches(),touch);
- break;
- case cc.TOUCH_CANCELLED:
- if (handler.getDelegate().onTouchCancelled) handler.getDelegate().onTouchCancelled(touch, event);
- handler.getClaimedTouches().length = 0;
- //cc.ArrayRemoveObject(handler.getClaimedTouches(),touch);
- break;
- }
- }
-
- if (claimed && handler.isSwallowsTouches()) {
- if (needsMutableSet) {
- cc.ArrayRemoveObject(mutableTouches, touch);
- }
- break;
- }
- }
- }
- }
-
- //
- // process standard handlers 2nd
- //
- if (standardHandlersCount > 0) {
- for (i = 0; i < this._standardHandlers.length; i++) {
- handler = this._standardHandlers[i];
-
- if (!handler) {
- break;
- }
-
- switch (helper.type) {
- case cc.TOUCH_BEGAN:
- if (mutableTouches.length > 0) {
- if (handler.getDelegate().onTouchesBegan) handler.getDelegate().onTouchesBegan(mutableTouches, event);
- }
- break;
- case cc.TOUCH_MOVED:
- if (mutableTouches.length > 0) {
- if (cc.Browser.isMobile) {
- if (handler.getDelegate().onTouchesMoved) handler.getDelegate().onTouchesMoved(mutableTouches, event);
- } else {
- if (this._mousePressed && handler.getDelegate().onTouchesMoved) handler.getDelegate().onTouchesMoved(mutableTouches, event);
- }
- }
- break;
- case cc.TOUCH_ENDED:
- if (handler.getDelegate().onTouchesEnded) handler.getDelegate().onTouchesEnded(mutableTouches, event);
- break;
- case cc.TOUCH_CANCELLED:
- if (handler.getDelegate().onTouchesCancelled) handler.getDelegate().onTouchesCancelled(mutableTouches, event);
- break;
- }
- }
- }
-
- if (needsMutableSet) {
- mutableTouches = null;
- }
-
- //
- // Optimization. To prevent a [handlers copy] which is expensive
- // the add/removes/quit is done after the iterations
- //
- this._locked = false;
- if (this._toRemove) {
- this._toRemove = false;
- for (i = 0; i < this._handlersToRemove.length; i++) {
- this.forceRemoveDelegate(this._handlersToRemove[i]);
- }
- this._handlersToRemove.length = 0;
- }
-
- if (this._toAdd) {
- this._toAdd = false;
-
- for (i = 0; i < this._handlersToAdd.length; i++) {
- handler = this._handlersToAdd[i];
- if (!handler) {
- break;
- }
-
- if (handler instanceof cc.TargetedTouchHandler) {
- this._targetedHandlers = this.forceAddHandler(handler, this._targetedHandlers);
- } else {
- this._standardHandlers = this.forceAddHandler(handler, this._standardHandlers);
- }
- }
- this._handlersToAdd.length = 0;
- }
-
- if (this._toQuit) {
- this._toQuit = false;
- this.forceRemoveAllDelegates();
- }
- },
-
- /**
- * @param {Array} touches
- * @param {event} event
- */
- touchesBegan:function (touches, event) {
- if (this._dispatchEvents) {
- this.touches(touches, event, cc.TOUCH_BEGAN);
- }
- },
-
- /**
- * @param {Array} touches
- * @param {event} event
- */
- touchesMoved:function (touches, event) {
- if (this._dispatchEvents) {
- this.touches(touches, event, cc.TOUCH_MOVED);
- }
- },
-
- /**
- * @param {Array} touches
- * @param {event} event
- */
- touchesEnded:function (touches, event) {
- if (this._dispatchEvents) {
- this.touches(touches, event, cc.TOUCH_ENDED);
- }
- },
-
- /**
- * @param {Array} touches
- * @param {event} event
- */
- touchesCancelled:function (touches, event) {
- if (this._dispatchEvents) {
- this.touches(touches, event, cc.TOUCH_CANCELLED);
- }
- },
-
- /**
- * @param {Array||cc.TouchDelegate} array array or delegate
- * @param {cc.TouchDelegate} delegate
- * @return {cc.TargetedTouchHandler|cc.StandardTouchHandler|Null}
- */
- findHandler:function (array, delegate) {
- switch (arguments.length) {
- case 1:
- delegate = arguments[0];
- for (var i = 0; i < this._targetedHandlers.length; i++) {
- if (this._targetedHandlers[i].getDelegate() == delegate) {
- return this._targetedHandlers[i];
- }
- }
- for (i = 0; i < this._standardHandlers.length; i++) {
- if (this._standardHandlers[i].getDelegate() == delegate) {
- return this._standardHandlers[i];
- }
- }
- return null;
- break;
- case 2:
- cc.Assert(array != null && delegate != null, "TouchDispatcher.findHandler():Arguments is null");
-
- for (i = 0; i < array.length; i++) {
- if (array[i].getDelegate() == delegate) {
- return array[i];
- }
- }
-
- return null;
- break;
- default:
- throw "Argument must be non-nil ";
- break;
- }
- },
-
- /**
- * @param {cc.TouchDelegate} delegate
- */
- forceRemoveDelegate:function (delegate) {
- var handler;
- // XXX: remove it from both handlers ???
- // remove handler from m_pStandardHandlers
- for (var i = 0; i < this._standardHandlers.length; i++) {
- handler = this._standardHandlers[i];
- if (handler && handler.getDelegate() == delegate) {
- cc.ArrayRemoveObject(this._standardHandlers, handler);
- break;
- }
- }
-
- for (i = 0; i < this._targetedHandlers.length; i++) {
- handler = this._targetedHandlers[i];
- if (handler && handler.getDelegate() == delegate) {
- cc.ArrayRemoveObject(this._targetedHandlers, handler);
- break;
- }
- }
- },
-
- /**
- * @param {Array} array
- */
- rearrangeHandlers:function (array) {
- array.sort(cc.less);
- }
-});
-
-/**
- * @type {cc.Point}
- */
-cc.TouchDispatcher.preTouchPoint = cc.p(0, 0);
-
-cc.TouchDispatcher.isRegisterEvent = false;
-
-cc.getHTMLElementPosition = function (element) {
- var docElem = document.documentElement;
- var win = window;
- var box = null;
- if (typeof element.getBoundingClientRect === 'function') {
- box = element.getBoundingClientRect();
- } else {
- if (element instanceof HTMLCanvasElement) {
- box = {
- left:0,
- top:0,
- width:element.width,
- height:element.height
- };
- } else {
- box = {
- left:0,
- top:0,
- width:parseInt(element.style.width),
- height:parseInt(element.style.height)
- };
- }
- }
- return {
- left:box.left + win.pageXOffset - docElem.clientLeft,
- top:box.top + win.pageYOffset - docElem.clientTop,
- width:box.width,
- height:box.height
- };
-};
-
-cc.ProcessMouseupEvent = function (element, event) {
- var pos = cc.getHTMLElementPosition(element);
-
- var tx, ty;
- if (event.pageX != null) { //not avalable in <= IE8
- tx = event.pageX;
- ty = event.pageY;
- } else {
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
- tx = event.clientX;
- ty = event.clientY;
- }
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
-
- var touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- var posArr = [];
- posArr.push(touch);
- //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null);
- cc.EGLView.getInstance().touchesEnded(posArr, null);
-};
-
-/**
- * @param {HTMLCanvasElement|HTMLDivElement} element
- */
-cc.TouchDispatcher.registerHtmlElementEvent = function (element) {
- if (cc.TouchDispatcher.isRegisterEvent) return;
-
- if (!cc.Browser.isMobile) {
- window.addEventListener('mousedown', function (event) {
- cc.Director.getInstance().getTouchDispatcher()._setMousePressed(true);
- });
-
- window.addEventListener('mouseup', function (event) {
- cc.Director.getInstance().getTouchDispatcher()._setMousePressed(false);
-
- var pos = cc.getHTMLElementPosition(element);
-
- var tx, ty;
- if (event.pageX != null) { //not avalable in <= IE8
- tx = event.pageX;
- ty = event.pageY;
- } else {
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
- tx = event.clientX;
- ty = event.clientY;
- }
-
- if (!cc.rectContainsPoint(new cc.Rect(pos.left, pos.top, pos.width, pos.height), cc.p(tx, ty))) {
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
- var touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- var posArr = [];
- posArr.push(touch);
- //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null);
- cc.EGLView.getInstance().touchesEnded(posArr, null);
- }
- });
-
- //register canvas mouse event
- element.addEventListener("mousedown", function (event) {
- var pos = cc.getHTMLElementPosition(element);
-
- var tx, ty;
- if (event.pageX != null) { //not avalable in <= IE8
- tx = event.pageX;
- ty = event.pageY;
- } else {
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
- tx = event.clientX;
- ty = event.clientY;
- }
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
- var touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- var posArr = [];
- posArr.push(touch);
- //csx cc.Director.getInstance().getTouchDispatcher().touchesBegan(posArr, null);
- cc.EGLView.getInstance().touchesBegan(posArr, null);
- });
-
- element.addEventListener("mouseup", function (event) {
- cc.ProcessMouseupEvent(element, event);
- });
-
- element.addEventListener("mousemove", function (event) {
- var pos = cc.getHTMLElementPosition(element);
-
- var tx, ty;
- if (event.pageX != null) { //not avalable in <= IE8
- tx = event.pageX;
- ty = event.pageY;
- } else {
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
- tx = event.clientX;
- ty = event.clientY;
- }
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
- var touch = new cc.Touch(location.x, location.y);
- //TODO this feature only chrome support
- //if((event.button == 0) && (event.which == 1))
- // touch._setPressed(true);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- var posArr = [];
- posArr.push(touch);
-
- //csx cc.Director.getInstance().getTouchDispatcher().touchesMoved(posArr, null);
- cc.EGLView.getInstance().touchesMoved(posArr, null);
- });
- }
- else if(window.navigator.msPointerEnabled){
- var _pointerEventsMap = {
- "MSPointerDown" : "touchesBegan",
- "MSPointerMove" : "touchesMoved",
- "MSPointerUp" : "touchesEnded",
- "MSPointerCancel" : "touchesCancelled"
- };
-
- for(var i in _pointerEventsMap){
- (function(_pointerEvent, _touchEvent){
- element.addEventListener(_pointerEvent, function (event){
- var pos = cc.getHTMLElementPosition(element);
-
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
-
- var tx, ty, touch, preLocation;
- tx = event.clientX;
- ty = event.clientY;
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
- var touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- cc.Director.getInstance().getTouchDispatcher()[_touchEvent]([touch], null);
- event.stopPropagation();
- event.preventDefault();
- }, false);
- })(i, _pointerEventsMap[i]);
- }
- }
- else {
-
- //register canvas touch event
- element.addEventListener("touchstart", function (event) {
- if (!event.changedTouches) return;
-
- var posArr = [];
- var pos = cc.getHTMLElementPosition(element);
-
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
-
- var touch_event, tx, ty, touch, preLocation;
- var length = event.changedTouches.length;
- for (var i = 0; i < length; i++) {
- touch_event = event.changedTouches[i];
- //tx = touch_event.pageX;
- //ty = touch_event.pageY;
- if (touch_event) {
- tx = touch_event.clientX;
- ty = touch_event.clientY;
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
- touch = null;
- if (touch_event.hasOwnProperty("identifier")) {
- touch = new cc.Touch(location.x, location.y, touch_event.identifier);
- //use Touch Pool
- preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation();
- touch._setPrevPoint(preLocation.x, preLocation.y);
- cc.TouchDispatcher._setPreTouch(touch);
- } else {
- touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- }
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- posArr.push(touch);
- }
- }
- //csx cc.Director.getInstance().getTouchDispatcher().touchesBegan(posArr, null);
- cc.EGLView.getInstance().touchesBegan(posArr, null);
- event.stopPropagation();
- event.preventDefault();
- }, false);
-
- element.addEventListener("touchmove", function (event) {
- if (!event.changedTouches) return;
-
- var posArr = [];
- var pos = cc.getHTMLElementPosition(element);
-
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
-
- var touch_event, tx, ty, touch, preLocation;
- var length = event.changedTouches.length;
- for (var i = 0; i < length; i++) {
- touch_event = event.changedTouches[i];
- //tx = touch_event.pageX;
- //ty = touch_event.pageY;
- if (touch_event) {
- tx = touch_event.clientX;
- ty = touch_event.clientY;
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
-
- touch = null;
- if (touch_event.hasOwnProperty("identifier")) {
- touch = new cc.Touch(location.x, location.y, touch_event.identifier);
- //use Touch Pool
- preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation();
- touch._setPrevPoint(preLocation.x, preLocation.y);
- cc.TouchDispatcher._setPreTouch(touch);
- } else {
- touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- }
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- posArr.push(touch);
- }
- }
- //csx cc.Director.getInstance().getTouchDispatcher().touchesMoved(posArr, null);
- cc.EGLView.getInstance().touchesMoved(posArr, null);
- event.stopPropagation();
- event.preventDefault();
- }, false);
-
- element.addEventListener("touchend", function (event) {
- if (!event.changedTouches) return;
-
- var posArr = [];
- var pos = cc.getHTMLElementPosition(element);
-
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
-
- var touch_event, tx, ty, touch, preLocation;
- var length = event.changedTouches.length;
- for (var i = 0; i < length; i++) {
- touch_event = event.changedTouches[i];
- //tx = touch_event.pageX;
- //ty = touch_event.pageY;
- if (touch_event) {
- tx = touch_event.clientX;
- ty = touch_event.clientY;
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
-
- touch = null;
- if (touch_event.hasOwnProperty("identifier")) {
- touch = new cc.Touch(location.x, location.y, touch_event.identifier);
- //use Touch Pool
- preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation();
- touch._setPrevPoint(preLocation.x, preLocation.y);
- cc.TouchDispatcher._deletePreTouchWithSameId(touch);
- } else {
- touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- }
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- posArr.push(touch);
- }
- }
- //csx cc.Director.getInstance().getTouchDispatcher().touchesEnded(posArr, null);
- cc.EGLView.getInstance().touchesEnded(posArr, null);
- event.stopPropagation();
- event.preventDefault();
- }, false);
-
- element.addEventListener("touchcancel", function (event) {
- if (!event.changedTouches) return;
-
- var posArr = [];
- var pos = cc.getHTMLElementPosition(element);
-
- pos.left -= document.body.scrollLeft;
- pos.top -= document.body.scrollTop;
-
- var touch_event, tx, ty, touch, preLocation;
- var length = event.changedTouches.length;
- for (var i = 0; i < length; i++) {
- touch_event = event.changedTouches[i];
- //tx = touch_event.pageX;
- //ty = touch_event.pageY;
- if (touch_event) {
- tx = touch_event.clientX;
- ty = touch_event.clientY;
-
- var location = cc.EGLView.getInstance().convertToLocationInView(tx, ty, pos);
-
- touch = null;
- if (touch_event.hasOwnProperty("identifier")) {
- touch = new cc.Touch(location.x, location.y, touch_event.identifier);
- //use Touch Pool
- preLocation = cc.TouchDispatcher._getPreTouch(touch).getLocation();
- touch._setPrevPoint(preLocation.x, preLocation.y);
- cc.TouchDispatcher._deletePreTouchWithSameId(touch);
- } else {
- touch = new cc.Touch(location.x, location.y);
- touch._setPrevPoint(cc.TouchDispatcher.preTouchPoint.x, cc.TouchDispatcher.preTouchPoint.y);
- }
- cc.TouchDispatcher.preTouchPoint.x = location.x;
- cc.TouchDispatcher.preTouchPoint.y = location.y;
-
- posArr.push(touch);
- }
- }
- //csx cc.Director.getInstance().getTouchDispatcher().touchesCancelled(posArr, null);
- cc.EGLView.getInstance().touchesCancelled(posArr, null);
- event.stopPropagation();
- event.preventDefault();
- }, false);
- }
-
- cc.TouchDispatcher.isRegisterEvent = true;
-};
-
-/**
- * @param {cc.Touch} touch
- * @return {cc.Touch} preTouch
- */
-cc.TouchDispatcher._getPreTouch = function (touch) {
- var preTouch = null;
- var preTouchPool = cc.TouchDispatcher._preTouchPool;
- var id = touch.getId();
- for (var i = preTouchPool.length - 1; i >= 0; i--) {
- if (preTouchPool[i].getId() == id) {
- preTouch = preTouchPool[i];
- break;
- }
- }
- if (!preTouch) {
- preTouch = touch;
- }
- return preTouch;
-};
-
-/**
- * @param {cc.Touch} touch
- */
-cc.TouchDispatcher._setPreTouch = function (touch) {
- var find = false;
- var preTouchPool = cc.TouchDispatcher._preTouchPool;
- var id = touch.getId();
- for (var i = preTouchPool.length - 1; i >= 0; i--) {
- if (preTouchPool[i].getId() == id) {
- preTouchPool[i] = touch;
- find = true;
- break;
- }
- }
- if (!find) {
- //debug touches{
- //cc.log("Pool.length: " + preTouchPool.length);
- //}
- if (preTouchPool.length <= 50) {
- preTouchPool.push(touch);
- } else {
- preTouchPool[cc.TouchDispatcher._preTouchPoolPointer] = touch;
- cc.TouchDispatcher._preTouchPoolPointer = (cc.TouchDispatcher._preTouchPoolPointer + 1) % 50;
- }
- }
-};
-
-/**
- * @param {cc.Touch} touch
- */
-cc.TouchDispatcher._deletePreTouchWithSameId = function (touch) {
- var changeTouch;
- var preTouchPool = cc.TouchDispatcher._preTouchPool;
- var id = touch.getId();
- for (var i = preTouchPool.length - 1; i >= 0; i--) {
- if (preTouchPool[i].getId() == id) {
- changeTouch = preTouchPool.pop();
- if (i != preTouchPool.length) {
- preTouchPool[i] = changeTouch;
- }
- break;
- }
- }
-};
-
-/**
- * @type {Array}
- */
-cc.TouchDispatcher._preTouchPool = [];
-
-/**
- * @type {Number}
- */
-cc.TouchDispatcher._preTouchPoolPointer = 0;
-
-/**
- * register a targeted touch delegate to the dispatcher's list.
- * @param {Number} priority
- * @param {Boolean} swallowsTouches
- * @param {Object} delegate
- */
-cc.registerTargetedDelegate = function(priority, swallowsTouches, delegate){
- cc.Director.getInstance().getTouchDispatcher()._addTargetedDelegate(delegate, priority, swallowsTouches);
-};
-
-/**
- * Adds a standard touch delegate to the dispatcher's list.
- * See StandardTouchDelegate description.
- * @param {Object} delegate
- * @param {Number} [priority=]
- */
-cc.registerStandardDelegate = function(delegate, priority){
- cc.Director.getInstance().getTouchDispatcher()._addStandardDelegate(delegate, priority);
-};
-
-/**
- * Removes a touch delegate. from TouchDispatcher
- * @param delegate
- */
-cc.unregisterTouchDelegate = function(delegate){
- cc.Director.getInstance().getTouchDispatcher()._removeDelegate(delegate);
-};
\ No newline at end of file
diff --git a/cocos2d/touch_dispatcher/CCTouchHandler.js b/cocos2d/touch_dispatcher/CCTouchHandler.js
deleted file mode 100644
index cd3bb2c647..0000000000
--- a/cocos2d/touch_dispatcher/CCTouchHandler.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * cc.TouchHandler
- * Object than contains the delegate and priority of the event handler.
- * @class
- * @extends cc.Class
- */
-cc.TouchHandler = cc.Class.extend(/** @lends cc.TouchHandler# */{
- _delegate:null,
- _priority:0,
- _enabledSelectors:0,
-
- /**
- * @return {cc.TouchDelegate}
- */
- getDelegate:function () {
- return this._delegate;
- },
-
- /**
- * @param {cc.TouchDelegate} delegate
- */
- setDelegate:function (delegate) {
- this._delegate = delegate;
- },
-
- /**
- * @return {Number}
- */
- getPriority:function () {
- return this._priority;
- },
-
- /**
- * @param {Number} priority
- */
- setPriority:function (priority) {
- this._priority = priority;
- },
-
- /**
- * Enabled selectors
- * @return {Number}
- */
- getEnabledSelectors:function () {
- return this._enabledSelectors;
- },
-
- /**
- * @param {Number} value
- */
- setEnalbedSelectors:function (value) {
- this._enabledSelectors = value;
- },
-
- /**
- * initializes a TouchHandler with a delegate and a priority
- * @param {cc.TouchDelegate} delegate
- * @param {Number} priority
- * @return {Boolean}
- */
- initWithDelegate:function (delegate, priority) {
- cc.Assert(delegate != null, "TouchHandler.initWithDelegate():touch delegate should not be null");
- this._delegate = delegate;
- this._priority = priority;
- this._enabledSelectors = 0;
- return true;
- }
-});
-
-/**
- * Create a TouchHandler with a delegate and a priority
- * @param {cc.TouchDelegate} delegate
- * @param {Number} priority
- * @return {cc.TouchHandler}
- */
-cc.TouchHandler.create = function (delegate, priority) {
- var handler = new cc.TouchHandler();
- if (handler) {
- handler.initWithDelegate(delegate, priority);
- }
- return handler;
-};
-
-/**
- * cc.StandardTouchHandler
- * It forwardes each event to the delegate.
- * @class
- * @extends cc.TouchHandler
- */
-cc.StandardTouchHandler = cc.TouchHandler.extend(/** @lends cc.StandardTouchHandler# */{
- /**
- * Initializes a TouchHandler with a delegate and a priority
- * @param {cc.TouchDelegate} delegate
- * @param {Number} priority
- * @return {Boolean}
- */
- initWithDelegate:function (delegate, priority) {
- return cc.TouchHandler.prototype.initWithDelegate.call(this, delegate, priority);
- }
-});
-
-/**
- * Create a TouchHandler with a delegate and a priority
- * @param {Object} delegate
- * @param {Number} priority
- * @return {cc.StandardTouchHandler}
- */
-cc.StandardTouchHandler.create = function (delegate, priority) {
- var handler = new cc.StandardTouchHandler();
- if (handler) {
- handler.initWithDelegate(delegate, priority);
- }
- return handler;
-};
-
-/**
- * @class
- * @extends cc.TouchHandler
- */
-cc.TargetedTouchHandler = cc.TouchHandler.extend(/** @lends cc.TargetedTouchHandler# */{
- _swallowsTouches:false,
- _claimedTouches:null,
-
- /**
- * Whether or not the touches are swallowed
- * @return {Boolean}
- */
- isSwallowsTouches:function () {
- return this._swallowsTouches;
- },
-
- /**
- * @param {Boolean} swallowsTouches
- */
- setSwallowsTouches:function (swallowsTouches) {
- this._swallowsTouches = swallowsTouches;
- },
-
- /**
- * MutableSet that contains the claimed touches
- * @return {Array}
- */
- getClaimedTouches:function () {
- return this._claimedTouches;
- },
-
- /**
- * Initializes a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not
- * @param {cc.TouchDelegate} delegate
- * @param {Number} priority
- * @param {Boolean} swallow
- * @return {Boolean}
- */
- initWithDelegate:function (delegate, priority, swallow) {
- if (cc.TouchHandler.prototype.initWithDelegate.call(this, delegate, priority)) {
- this._claimedTouches = [];
- this._swallowsTouches = swallow;
- return true;
- }
- return false;
- }
-});
-
-/**
- * Create a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not
- * @param {Object} delegate
- * @param {Number} priority
- * @param {Boolean} swallow
- * @return {cc.TargetedTouchHandler}
- */
-cc.TargetedTouchHandler.create = function (delegate, priority, swallow) {
- var handler = new cc.TargetedTouchHandler();
- if (handler) {
- handler.initWithDelegate(delegate, priority, swallow);
- }
- return handler;
-};
diff --git a/cocos2d/transitions/CCTransition.js b/cocos2d/transitions/CCTransition.js
new file mode 100644
index 0000000000..09b18228e6
--- /dev/null
+++ b/cocos2d/transitions/CCTransition.js
@@ -0,0 +1,1478 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+/**
+ * A tag constant for identifying fade scenes
+ * @constant
+ * @type Number
+ */
+cc.SCENE_FADE = 4208917214;
+
+/**
+ * horizontal orientation Type where the Left is nearer
+ * @constant
+ * @type Number
+ */
+cc.TRANSITION_ORIENTATION_LEFT_OVER = 0;
+/**
+ * horizontal orientation type where the Right is nearer
+ * @constant
+ * @type Number
+ */
+cc.TRANSITION_ORIENTATION_RIGHT_OVER = 1;
+/**
+ * vertical orientation type where the Up is nearer
+ * @constant
+ * @type Number
+ */
+cc.TRANSITION_ORIENTATION_UP_OVER = 0;
+/**
+ * vertical orientation type where the Bottom is nearer
+ * @constant
+ * @type Number
+ */
+cc.TRANSITION_ORIENTATION_DOWN_OVER = 1;
+
+/**
+ * @class
+ * @extends cc.Scene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene the scene to transit with
+ * @example
+ * var trans = new TransitionScene(time,scene);
+ */
+cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{
+ _inScene: null,
+ _outScene: null,
+ _duration: null,
+ _isInSceneOnTop: false,
+ _isSendCleanupToScene: false,
+ _className: "TransitionScene",
+
+ /**
+ * creates a base transition with duration and incoming scene
+ * Constructor of cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene the scene to transit with
+ */
+ ctor: function (t, scene) {
+ cc.Scene.prototype.ctor.call(this);
+ if (t !== undefined && scene !== undefined)
+ this.initWithDuration(t, scene);
+ },
+
+ //private
+ _setNewScene: function (dt) {
+ this.unschedule(this._setNewScene);
+ // Before replacing, save the "send cleanup to scene"
+ var director = cc.director;
+ this._isSendCleanupToScene = director.isSendCleanupToScene();
+ director.runScene(this._inScene);
+
+ // enable events while transitions
+ cc.eventManager.setEnabled(true);
+
+ // issue #267
+ this._outScene.visible = true;
+ },
+
+ //protected
+ _sceneOrder: function () {
+ this._isInSceneOnTop = true;
+ },
+
+ /**
+ * stuff gets drawn here
+ */
+ visit: function () {
+ if (this._isInSceneOnTop) {
+ this._outScene.visit();
+ this._inScene.visit();
+ } else {
+ this._inScene.visit();
+ this._outScene.visit();
+ }
+ cc.Node.prototype.visit.call(this);
+ },
+
+ /**
+ *
+ * Event callback that is invoked every time when cc.TransitionScene enters the 'stage'.
+ * If the TransitionScene enters the 'stage' with a transition, this event is called when the transition starts.
+ * During onEnter you can't access a "sister/brother" node.
+ * If you override onEnter, you must call its parent's onEnter function with this._super().
+ *
+ */
+ onEnter: function () {
+ cc.Node.prototype.onEnter.call(this);
+
+ // disable events while transitions
+ cc.eventManager.setEnabled(false);
+
+ // outScene should not receive the onEnter callback
+ // only the onExitTransitionDidStart
+ this._outScene._performRecursive(cc.Node._stateCallbackType.onExitTransitionDidStart);
+
+ this._inScene._performRecursive(cc.Node._stateCallbackType.onEnter);
+ },
+
+ /**
+ *
+ * callback that is called every time the cc.TransitionScene leaves the 'stage'.
+ * If the cc.TransitionScene leaves the 'stage' with a transition, this callback is called when the transition finishes.
+ * During onExit you can't access a sibling node.
+ * If you override onExit, you shall call its parent's onExit with this._super().
+ *
+ */
+ onExit: function () {
+ cc.Node.prototype.onExit.call(this);
+
+ // enable events while transitions
+ cc.eventManager.setEnabled(true);
+
+ this._outScene._performRecursive(cc.Node._stateCallbackType.onExit);
+
+ // _inScene should not receive the onEnter callback
+ // only the onEnterTransitionDidFinish
+ this._inScene._performRecursive(cc.Node._stateCallbackType.onEnterTransitionDidFinish);
+ },
+
+ /**
+ * custom cleanup
+ */
+ cleanup: function () {
+ cc.Node.prototype.cleanup.call(this);
+
+ if (this._isSendCleanupToScene)
+ this._outScene._performRecursive(cc.Node._stateCallbackType.cleanup);
+ },
+
+ /**
+ * initializes a transition with duration and incoming scene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene a scene to transit to
+ * @return {Boolean} return false if error
+ */
+ initWithDuration: function (t, scene) {
+ if (!scene)
+ throw new Error("cc.TransitionScene.initWithDuration(): Argument scene must be non-nil");
+
+ if (this.init()) {
+ this._duration = t;
+ this.attr({
+ x: 0,
+ y: 0,
+ anchorX: 0,
+ anchorY: 0
+ });
+ // retain
+ this._inScene = scene;
+ this._outScene = cc.director.getRunningScene();
+ if (!this._outScene) {
+ this._outScene = new cc.Scene();
+ this._outScene.init();
+ }
+
+ if (this._inScene === this._outScene)
+ throw new Error("cc.TransitionScene.initWithDuration(): Incoming scene must be different from the outgoing scene");
+
+ this._sceneOrder();
+ return true;
+ } else {
+ return false;
+ }
+ },
+
+ /**
+ * called after the transition finishes
+ */
+ finish: function () {
+ // clean up
+ this._inScene.attr({
+ visible: true,
+ x: 0,
+ y: 0,
+ scale: 1.0,
+ rotation: 0.0
+ });
+
+ this._outScene.attr({
+ visible: false,
+ x: 0,
+ y: 0,
+ scale: 1.0,
+ rotation: 0.0
+ });
+
+ //[self schedule:@selector(setNewScene:) interval:0];
+ this.schedule(this._setNewScene, 0);
+ },
+
+ /**
+ * set hide the out scene and show in scene
+ */
+ hideOutShowIn: function () {
+ this._inScene.visible = true;
+ this._outScene.visible = false;
+ }
+});
+/**
+ * creates a base transition with duration and incoming scene
+ * @deprecated since v3.0, please use new cc.TransitionScene(t,scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene the scene to transit with
+ * @return {cc.TransitionScene|Null}
+ */
+cc.TransitionScene.create = function (t, scene) {
+ return new cc.TransitionScene(t, scene);
+};
+
+/**
+ * A cc.Transition that supports orientation like.
+ * Possible orientation: LeftOver, RightOver, UpOver, DownOver
+ * useful for when you want to make a transition happen between 2 orientations
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} orientation
+ * @example
+ * var trans = new cc.TransitionSceneOriented(time,scene,orientation);
+ */
+cc.TransitionSceneOriented = cc.TransitionScene.extend(/** @lends cc.TransitionSceneOriented# */{
+ _orientation: 0,
+
+ /**
+ * Constructor of TransitionSceneOriented
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} orientation
+ */
+ ctor: function (t, scene, orientation) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ orientation != undefined && this.initWithDuration(t, scene, orientation);
+ },
+ /**
+ * initialize the transition
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} orientation
+ * @return {Boolean}
+ */
+ initWithDuration: function (t, scene, orientation) {
+ if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) {
+ this._orientation = orientation;
+ }
+ return true;
+ }
+});
+
+/**
+ * creates a base transition with duration and incoming scene
+ * @deprecated since v3.0 ,please use new cc.TransitionSceneOriented(t, scene, orientation) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} orientation
+ * @return {cc.TransitionSceneOriented}
+ */
+cc.TransitionSceneOriented.create = function (t, scene, orientation) {
+ return new cc.TransitionSceneOriented(t, scene, orientation);
+};
+
+/**
+ * Rotate and zoom out the outgoing scene, and then rotate and zoom in the incoming
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionRotoZoom(t, scene);
+ */
+cc.TransitionRotoZoom = cc.TransitionScene.extend(/** @lends cc.TransitionRotoZoom# */{
+
+ /**
+ * Constructor of TransitionRotoZoom
+ * @function
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * Custom On Enter callback
+ * @override
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+
+ this._inScene.attr({
+ scale: 0.001,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ this._outScene.attr({
+ scale: 1.0,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+
+ var rotoZoom = cc.sequence(
+ cc.spawn(cc.scaleBy(this._duration / 2, 0.001),
+ cc.rotateBy(this._duration / 2, 360 * 2)),
+ cc.delayTime(this._duration / 2));
+
+ this._outScene.runAction(rotoZoom);
+ this._inScene.runAction(
+ cc.sequence(rotoZoom.reverse(),
+ cc.callFunc(this.finish, this)));
+ }
+});
+
+/**
+ * Creates a Transition rotation and zoom
+ * @deprecated since v3.0,please use new cc.TransitionRotoZoom(t, scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene the scene to work with
+ * @return {cc.TransitionRotoZoom}
+ */
+cc.TransitionRotoZoom.create = function (t, scene) {
+ return new cc.TransitionRotoZoom(t, scene);
+};
+
+/**
+ * Zoom out and jump the outgoing scene, and then jump and zoom in the incoming
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionJumpZoom(t, scene);
+ */
+cc.TransitionJumpZoom = cc.TransitionScene.extend(/** @lends cc.TransitionJumpZoom# */{
+ /**
+ * Constructor of TransitionJumpZoom
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * Custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+ var winSize = cc.director.getWinSize();
+
+ this._inScene.attr({
+ scale: 0.5,
+ x: winSize.width,
+ y: 0,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ this._outScene.anchorX = 0.5;
+ this._outScene.anchorY = 0.5;
+
+ var jump = cc.jumpBy(this._duration / 4, cc.p(-winSize.width, 0), winSize.width / 4, 2);
+ var scaleIn = cc.scaleTo(this._duration / 4, 1.0);
+ var scaleOut = cc.scaleTo(this._duration / 4, 0.5);
+
+ var jumpZoomOut = cc.sequence(scaleOut, jump);
+ var jumpZoomIn = cc.sequence(jump, scaleIn);
+
+ var delay = cc.delayTime(this._duration / 2);
+ this._outScene.runAction(jumpZoomOut);
+ this._inScene.runAction(cc.sequence(delay, jumpZoomIn, cc.callFunc(this.finish, this)));
+ }
+});
+
+/**
+ * creates a scene transition that zooms then jump across the screen, the same for the incoming scene
+ * @deprecated since v3.0,please use new cc.TransitionJumpZoom(t, scene);
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionJumpZoom}
+ */
+cc.TransitionJumpZoom.create = function (t, scene) {
+ return new cc.TransitionJumpZoom(t, scene);
+};
+
+/**
+ * Move in from to the left the incoming scene.
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionMoveInL(time,scene);
+ */
+cc.TransitionMoveInL = cc.TransitionScene.extend(/** @lends cc.TransitionMoveInL# */{
+ /**
+ * Constructor of TransitionMoveInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * Custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+ this.initScenes();
+
+ var action = this.action();
+ this._inScene.runAction(
+ cc.sequence(this.easeActionWithAction(action), cc.callFunc(this.finish, this))
+ );
+ },
+
+ /**
+ * initializes the scenes
+ */
+ initScenes: function () {
+ this._inScene.setPosition(-cc.director.getWinSize().width, 0);
+ },
+
+ /**
+ * returns the action that will be performed
+ */
+ action: function () {
+ return cc.moveTo(this._duration, cc.p(0, 0));
+ },
+
+ /**
+ * creates an ease action from action
+ * @param {cc.ActionInterval} action
+ * @return {cc.EaseOut}
+ */
+ easeActionWithAction: function (action) {
+ return new cc.EaseOut(action, 2.0);
+ }
+});
+
+/**
+ * creates an action that Move in from to the left the incoming scene.
+ * @deprecated since v3.0,please use new cc.TransitionMoveInL(t, scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionMoveInL}
+ */
+cc.TransitionMoveInL.create = function (t, scene) {
+ return new cc.TransitionMoveInL(t, scene);
+};
+
+/**
+ * Move in from to the right the incoming scene.
+ * @class
+ * @extends cc.TransitionMoveInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionMoveInR(time,scene);
+ */
+cc.TransitionMoveInR = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveInR# */{
+ /**
+ * Constructor of TransitionMoveInR
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionMoveInL.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * Init function
+ */
+ initScenes: function () {
+ this._inScene.setPosition(cc.director.getWinSize().width, 0);
+ }
+});
+
+/**
+ * create a scene transition that Move in from to the right the incoming scene.
+ * @deprecated since v3.0,please use new cc.TransitionMoveInR(t, scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionMoveInR}
+ */
+cc.TransitionMoveInR.create = function (t, scene) {
+ return new cc.TransitionMoveInR(t, scene);
+};
+
+/**
+ * Move in from to the top the incoming scene.
+ * @class
+ * @extends cc.TransitionMoveInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionMoveInT(time,scene);
+ */
+cc.TransitionMoveInT = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveInT# */{
+ /**
+ * Constructor of TransitionMoveInT
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionMoveInL.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * init function
+ */
+ initScenes: function () {
+ this._inScene.setPosition(0, cc.director.getWinSize().height);
+ }
+});
+
+/**
+ * Move in from to the top the incoming scene.
+ * @deprecated since v3.0,please use new cc.TransitionMoveInT(t, scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionMoveInT}
+ */
+cc.TransitionMoveInT.create = function (t, scene) {
+ return new cc.TransitionMoveInT(t, scene);
+};
+
+/**
+ * Move in from to the bottom the incoming scene.
+ * @class
+ * @extends cc.TransitionMoveInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionMoveInB(time,scene);
+ */
+cc.TransitionMoveInB = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveInB# */{
+ /**
+ * Constructor of TransitionMoveInB
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionMoveInL.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ /**
+ * init function
+ */
+ initScenes: function () {
+ this._inScene.setPosition(0, -cc.director.getWinSize().height);
+ }
+});
+
+/**
+ * create a scene transition that Move in from to the bottom the incoming scene.
+ * @deprecated since v3.0,please use new cc.TransitionMoveInB(t, scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionMoveInB}
+ */
+cc.TransitionMoveInB.create = function (t, scene) {
+ return new cc.TransitionMoveInB(t, scene);
+};
+
+/**
+ * The adjust factor is needed to prevent issue #442
+ * One solution is to use DONT_RENDER_IN_SUBPIXELS images, but NO
+ * The other issue is that in some transitions (and I don't know why)
+ * the order should be reversed (In in top of Out or vice-versa).
+ * @constant
+ * @type Number
+ */
+cc.ADJUST_FACTOR = 0.5;
+
+/**
+ * a transition that a new scene is slided from left
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = cc.TransitionSlideInL(time,scene);
+ */
+cc.TransitionSlideInL = cc.TransitionScene.extend(/** @lends cc.TransitionSlideInL# */{
+ /**
+ * Constructor of TransitionSlideInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ _sceneOrder: function () {
+ this._isInSceneOnTop = false;
+ },
+
+ /**
+ * custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+ this.initScenes();
+
+ var inA = this.action();
+ var outA = this.action();
+
+ var inAction = cc.sequence(this.easeActionWithAction(inA), cc.callFunc(this.finish, this));
+ var outAction = this.easeActionWithAction(outA);
+ this._inScene.runAction(inAction);
+ this._outScene.runAction(outAction);
+ },
+
+ /**
+ * initializes the scenes
+ */
+ initScenes: function () {
+ this._inScene.setPosition(-cc.director.getWinSize().width + cc.ADJUST_FACTOR, 0);
+ },
+ /**
+ * returns the action that will be performed by the incoming and outgoing scene
+ * @return {cc.MoveBy}
+ */
+ action: function () {
+ return cc.moveBy(this._duration, cc.p(cc.director.getWinSize().width - cc.ADJUST_FACTOR, 0));
+ },
+
+ /**
+ * @param {cc.ActionInterval} action
+ * @return {*}
+ */
+ easeActionWithAction: function (action) {
+ return new cc.EaseInOut(action, 2.0);
+ }
+});
+
+/**
+ * create a transition that a new scene is slided from left
+ * @deprecated since v3.0,please use new cc.TransitionSlideInL(t, scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionSlideInL}
+ */
+cc.TransitionSlideInL.create = function (t, scene) {
+ return new cc.TransitionSlideInL(t, scene);
+};
+
+/**
+ * Slide in the incoming scene from the right border.
+ * @class
+ * @extends cc.TransitionSlideInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionSlideInR(time,scene);
+ */
+cc.TransitionSlideInR = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSlideInR# */{
+ /**
+ * Constructor of TransitionSlideInR
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionSlideInL.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ _sceneOrder: function () {
+ this._isInSceneOnTop = true;
+ },
+ /**
+ * initializes the scenes
+ */
+ initScenes: function () {
+ this._inScene.setPosition(cc.director.getWinSize().width - cc.ADJUST_FACTOR, 0);
+ },
+ /**
+ * returns the action that will be performed by the incoming and outgoing scene
+ * @return {cc.MoveBy}
+ */
+ action: function () {
+ return cc.moveBy(this._duration, cc.p(-(cc.director.getWinSize().width - cc.ADJUST_FACTOR), 0));
+ }
+});
+
+/**
+ * create Slide in the incoming scene from the right border.
+ * @deprecated since v3.0,please use new cc.TransitionSlideInR(t, scene) instead
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionSlideInR}
+ */
+cc.TransitionSlideInR.create = function (t, scene) {
+ return new cc.TransitionSlideInR(t, scene);
+};
+
+/**
+ * Slide in the incoming scene from the bottom border.
+ * @class
+ * @extends cc.TransitionSlideInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionSlideInB(time,scene);
+ */
+cc.TransitionSlideInB = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSlideInB# */{
+ /**
+ * Constructor of TransitionSlideInB
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionSlideInL.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ _sceneOrder: function () {
+ this._isInSceneOnTop = false;
+ },
+
+ /**
+ * initializes the scenes
+ */
+ initScenes: function () {
+ this._inScene.setPosition(0, -(cc.director.getWinSize().height - cc.ADJUST_FACTOR));
+ },
+
+ /**
+ * returns the action that will be performed by the incoming and outgoing scene
+ * @return {cc.MoveBy}
+ */
+ action: function () {
+ return cc.moveBy(this._duration, cc.p(0, cc.director.getWinSize().height - cc.ADJUST_FACTOR));
+ }
+});
+
+/**
+ * create a Slide in the incoming scene from the bottom border.
+ * @deprecated since v3.0,please use new cc.TransitionSlideInB(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionSlideInB}
+ */
+cc.TransitionSlideInB.create = function (t, scene) {
+ return new cc.TransitionSlideInB(t, scene);
+};
+
+/**
+ * Slide in the incoming scene from the top border.
+ * @class
+ * @extends cc.TransitionSlideInL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionSlideInT(time,scene);
+ */
+cc.TransitionSlideInT = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSlideInT# */{
+ /**
+ * Constructor of TransitionSlideInT
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionSlideInL.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ _sceneOrder: function () {
+ this._isInSceneOnTop = true;
+ },
+
+ /**
+ * initializes the scenes
+ */
+ initScenes: function () {
+ this._inScene.setPosition(0, cc.director.getWinSize().height - cc.ADJUST_FACTOR);
+ },
+
+ /**
+ * returns the action that will be performed by the incoming and outgoing scene
+ * @return {cc.MoveBy}
+ */
+ action: function () {
+ return cc.moveBy(this._duration, cc.p(0, -(cc.director.getWinSize().height - cc.ADJUST_FACTOR)));
+ }
+});
+
+/**
+ * create a Slide in the incoming scene from the top border.
+ * @deprecated since v3.0,please use new cc.TransitionSlideInT(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionSlideInT}
+ */
+cc.TransitionSlideInT.create = function (t, scene) {
+ return new cc.TransitionSlideInT(t, scene);
+};
+
+/**
+ * Shrink the outgoing scene while grow the incoming scene
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionShrinkGrow(time,scene);
+ */
+cc.TransitionShrinkGrow = cc.TransitionScene.extend(/** @lends cc.TransitionShrinkGrow# */{
+ /**
+ * Constructor of TransitionShrinkGrow
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * Custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+
+ this._inScene.attr({
+ scale: 0.001,
+ anchorX: 2 / 3.0,
+ anchorY: 0.5
+ });
+ this._outScene.attr({
+ scale: 1.0,
+ anchorX: 1 / 3.0,
+ anchorY: 0.5
+ });
+
+ var scaleOut = cc.scaleTo(this._duration, 0.01);
+ var scaleIn = cc.scaleTo(this._duration, 1.0);
+
+ this._inScene.runAction(cc.sequence(this.easeActionWithAction(scaleIn), cc.callFunc(this.finish, this)));
+ this._outScene.runAction(this.easeActionWithAction(scaleOut));
+ },
+
+ /**
+ * @param action
+ * @return {cc.EaseOut}
+ */
+ easeActionWithAction: function (action) {
+ return new cc.EaseOut(action, 2.0);
+ }
+});
+
+/**
+ * Shrink the outgoing scene while grow the incoming scene
+ * @deprecated since v3.0,please use new cc.TransitionShrinkGrow(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionShrinkGrow}
+ */
+cc.TransitionShrinkGrow.create = function (t, scene) {
+ return new cc.TransitionShrinkGrow(t, scene);
+};
+
+/**
+ * Fade out the outgoing scene and then fade in the incoming scene.
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
+ * @example
+ * var trans = new cc.TransitionFade(time,scene,color)
+ */
+cc.TransitionFade = cc.TransitionScene.extend(/** @lends cc.TransitionFade# */{
+ _color: null,
+
+ /**
+ * Constructor of TransitionFade
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.TRANSITION_ORIENTATION_LEFT_OVER|cc.TRANSITION_ORIENTATION_RIGHT_OVER|cc.TRANSITION_ORIENTATION_UP_OVER|cc.TRANSITION_ORIENTATION_DOWN_OVER} o
+ */
+ ctor: function (t, scene, color) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ this._color = cc.color();
+ scene && this.initWithDuration(t, scene, color);
+ },
+
+ /**
+ * custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+
+ var l = new cc.LayerColor(this._color);
+ this._inScene.visible = false;
+
+ this.addChild(l, 2, cc.SCENE_FADE);
+ var f = this.getChildByTag(cc.SCENE_FADE);
+
+ var a = cc.sequence(
+ cc.fadeIn(this._duration / 2),
+ cc.callFunc(this.hideOutShowIn, this),
+ cc.fadeOut(this._duration / 2),
+ cc.callFunc(this.finish, this)
+ );
+ f.runAction(a);
+ },
+
+ /**
+ * custom on exit
+ */
+ onExit: function () {
+ cc.TransitionScene.prototype.onExit.call(this);
+ this.removeChildByTag(cc.SCENE_FADE, false);
+ },
+
+ /**
+ * initializes the transition with a duration and with an RGB color
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.Color} color
+ * @return {Boolean}
+ */
+ initWithDuration: function (t, scene, color) {
+ color = color || cc.color.BLACK;
+ if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) {
+ this._color.r = color.r;
+ this._color.g = color.g;
+ this._color.b = color.b;
+ this._color.a = 0;
+ }
+ return true;
+ }
+});
+
+
+/**
+ * Fade out the outgoing scene and then fade in the incoming scene.
+ * @deprecated since v3.0,please use new cc.TransitionFade(time,scene,color) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {cc.Color} color
+ * @return {cc.TransitionFade}
+ */
+cc.TransitionFade.create = function (t, scene, color) {
+ return new cc.TransitionFade(t, scene, color);
+};
+
+/**
+ * Cross fades two scenes using the cc.RenderTexture object.
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionCrossFade(time,scene);
+ */
+cc.TransitionCrossFade = cc.TransitionScene.extend(/** @lends cc.TransitionCrossFade# */{
+ /**
+ * Constructor of TransitionCrossFade
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+
+ // create a transparent color layer
+ // in which we are going to add our rendertextures
+ var color = cc.color(0, 0, 0, 0);
+ var winSize = cc.director.getWinSize();
+ var layer = new cc.LayerColor(color);
+
+ // create the first render texture for inScene
+ var inTexture = new cc.RenderTexture(winSize.width, winSize.height);
+
+ inTexture.sprite.anchorX = 0.5;
+ inTexture.sprite.anchorY = 0.5;
+ inTexture.attr({
+ x: winSize.width / 2,
+ y: winSize.height / 2,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+
+ // render inScene to its texturebuffer
+ inTexture.begin();
+ this._inScene.visit();
+ inTexture.end();
+
+ // create the second render texture for outScene
+ var outTexture = new cc.RenderTexture(winSize.width, winSize.height);
+ outTexture.setPosition(winSize.width / 2, winSize.height / 2);
+ outTexture.sprite.anchorX = outTexture.anchorX = 0.5;
+ outTexture.sprite.anchorY = outTexture.anchorY = 0.5;
+
+ // render outScene to its texturebuffer
+ outTexture.begin();
+ this._outScene.visit();
+ outTexture.end();
+
+ inTexture.sprite.setBlendFunc(cc.ONE, cc.ONE); // inScene will lay on background and will not be used with alpha
+ outTexture.sprite.setBlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA); // we are going to blend outScene via alpha
+
+ // add render textures to the layer
+ layer.addChild(inTexture);
+ layer.addChild(outTexture);
+
+ // initial opacity:
+ inTexture.sprite.opacity = 255;
+ outTexture.sprite.opacity = 255;
+
+ // create the blend action
+ var layerAction = cc.sequence(
+ cc.fadeTo(this._duration, 0), cc.callFunc(this.hideOutShowIn, this),
+ cc.callFunc(this.finish, this)
+ );
+
+ // run the blend action
+ outTexture.sprite.runAction(layerAction);
+
+ // add the layer (which contains our two rendertextures) to the scene
+ this.addChild(layer, 2, cc.SCENE_FADE);
+ },
+
+ /**
+ * custom on exit
+ */
+ onExit: function () {
+ this.removeChildByTag(cc.SCENE_FADE, false);
+ cc.TransitionScene.prototype.onExit.call(this);
+ },
+});
+
+/**
+ * Cross fades two scenes using the cc.RenderTexture object.
+ * @deprecated since v3.0,please use new cc.TransitionCrossFade(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionCrossFade}
+ */
+cc.TransitionCrossFade.create = function (t, scene) {
+ return new cc.TransitionCrossFade(t, scene);
+};
+
+/**
+ * Turn off the tiles of the outgoing scene in random order
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionTurnOffTiles(time,scene);
+ */
+cc.TransitionTurnOffTiles = cc.TransitionScene.extend(/** @lends cc.TransitionTurnOffTiles# */{
+ _gridProxy: null,
+ /**
+ * Constructor of TransitionCrossFade
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ this._gridProxy = new cc.NodeGrid();
+ scene && this.initWithDuration(t, scene);
+ },
+
+ _sceneOrder: function () {
+ this._isInSceneOnTop = false;
+ },
+
+ /**
+ * custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+ this._gridProxy.setTarget(this._outScene);
+ this._gridProxy._performRecursive(cc.Node._stateCallbackType.onEnter);
+
+ var winSize = cc.director.getWinSize();
+ var aspect = winSize.width / winSize.height;
+ var x = 0 | (12 * aspect);
+ var y = 12;
+ var toff = cc.turnOffTiles(this._duration, cc.size(x, y));
+ var action = this.easeActionWithAction(toff);
+ this._gridProxy.runAction(cc.sequence(action, cc.callFunc(this.finish, this), cc.stopGrid()));
+ },
+
+ visit: function () {
+ this._inScene.visit();
+ this._gridProxy.visit();
+ },
+
+ /**
+ * @param {cc.ActionInterval} action
+ * @return {cc.ActionInterval}
+ */
+ easeActionWithAction: function (action) {
+ return action;
+ }
+});
+
+/**
+ * Turn off the tiles of the outgoing scene in random order
+ * @deprecated since v3.0,please use new cc.TransitionTurnOffTiles(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionTurnOffTiles}
+ */
+cc.TransitionTurnOffTiles.create = function (t, scene) {
+ return new cc.TransitionTurnOffTiles(t, scene);
+};
+
+/**
+ * The odd columns goes upwards while the even columns goes downwards.
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionSplitCols(time,scene);
+ */
+cc.TransitionSplitCols = cc.TransitionScene.extend(/** @lends cc.TransitionSplitCols# */{
+ _gridProxy: null,
+
+ _switchTargetToInscene: function () {
+ this._gridProxy.setTarget(this._inScene);
+ },
+
+ /**
+ * Constructor of TransitionSplitCols
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ this._gridProxy = new cc.NodeGrid();
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+ //this._inScene.visible = false;
+ this._gridProxy.setTarget(this._outScene);
+ this._gridProxy._performRecursive(cc.Node._stateCallbackType.onEnter);
+
+ var split = this.action();
+ var seq = cc.sequence(
+ split, cc.callFunc(this._switchTargetToInscene, this), split.reverse());
+
+ this._gridProxy.runAction(
+ cc.sequence(this.easeActionWithAction(seq), cc.callFunc(this.finish, this), cc.stopGrid())
+ );
+ },
+
+ onExit: function () {
+ this._gridProxy.setTarget(null);
+ this._gridProxy._performRecursive(cc.Node._stateCallbackType.onExit);
+ cc.TransitionScene.prototype.onExit.call(this);
+ },
+
+ visit: function () {
+ this._gridProxy.visit();
+ },
+
+ /**
+ * @param {cc.ActionInterval} action
+ * @return {cc.EaseInOut}
+ */
+ easeActionWithAction: function (action) {
+ return new cc.EaseInOut(action, 3.0);
+ },
+
+ /**
+ * @return {*}
+ */
+ action: function () {
+ return cc.splitCols(this._duration / 2.0, 3);
+ }
+});
+
+/**
+ * The odd columns goes upwards while the even columns goes downwards.
+ * @deprecated since v3.0,please use new cc.TransitionSplitCols(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionSplitCols}
+ */
+cc.TransitionSplitCols.create = function (t, scene) {
+ return new cc.TransitionSplitCols(t, scene);
+};
+
+/**
+ * The odd rows goes to the left while the even rows goes to the right.
+ * @class
+ * @extends cc.TransitionSplitCols
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionSplitRows(time,scene);
+ */
+cc.TransitionSplitRows = cc.TransitionSplitCols.extend(/** @lends cc.TransitionSplitRows# */{
+
+ /**
+ * Constructor of TransitionSplitRows
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionSplitCols.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+ /**
+ * @return {*}
+ */
+ action: function () {
+ return cc.splitRows(this._duration / 2.0, 3);
+ }
+});
+
+/**
+ * The odd rows goes to the left while the even rows goes to the right.
+ * @deprecated since v3.0,please use new cc.TransitionSplitRows(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionSplitRows}
+ */
+cc.TransitionSplitRows.create = function (t, scene) {
+ return new cc.TransitionSplitRows(t, scene);
+};
+
+/**
+ * Fade the tiles of the outgoing scene from the left-bottom corner the to top-right corner.
+ * @class
+ * @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionFadeTR(time,scene);
+ */
+cc.TransitionFadeTR = cc.TransitionScene.extend(/** @lends cc.TransitionFadeTR# */{
+ _gridProxy: null,
+ /**
+ * Constructor of TransitionFadeTR
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ this._gridProxy = new cc.NodeGrid();
+ scene && this.initWithDuration(t, scene);
+ },
+ _sceneOrder: function () {
+ this._isInSceneOnTop = false;
+ },
+
+ /**
+ * Custom on enter
+ */
+ onEnter: function () {
+ cc.TransitionScene.prototype.onEnter.call(this);
+
+ this._gridProxy.setTarget(this._outScene);
+ this._gridProxy._performRecursive(cc.Node._stateCallbackType.onEnter);
+
+ var winSize = cc.director.getWinSize();
+ var aspect = winSize.width / winSize.height;
+ var x = 0 | (12 * aspect);
+ var y = 12;
+
+ var action = this.actionWithSize(cc.size(x, y));
+ this._gridProxy.runAction(
+ cc.sequence(this.easeActionWithAction(action), cc.callFunc(this.finish, this), cc.stopGrid())
+ );
+ },
+
+ visit: function () {
+ this._inScene.visit();
+ this._gridProxy.visit();
+ },
+
+ /**
+ * @param {cc.ActionInterval} action
+ * @return {cc.ActionInterval}
+ */
+ easeActionWithAction: function (action) {
+ return action;
+ },
+
+ /**
+ * @param {cc.Size} size
+ * @return {*}
+ */
+ actionWithSize: function (size) {
+ return cc.fadeOutTRTiles(this._duration, size);
+ }
+});
+
+/**
+ * Fade the tiles of the outgoing scene from the left-bottom corner the to top-right corner.
+ * @deprecated since v3.0 please use new cc.TransitionFadeTR(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionFadeTR}
+ */
+cc.TransitionFadeTR.create = function (t, scene) {
+ return new cc.TransitionFadeTR(t, scene);
+};
+
+/**
+ * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
+ * @class
+ * @extends cc.TransitionFadeTR
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionFadeBL(time,scene)
+ */
+cc.TransitionFadeBL = cc.TransitionFadeTR.extend(/** @lends cc.TransitionFadeBL# */{
+ /**
+ * Constructor of TransitionFadeBL
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionFadeTR.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ /**
+ * @param {cc.Size} size
+ * @return {*}
+ */
+ actionWithSize: function (size) {
+ return cc.fadeOutBLTiles(this._duration, size);
+ }
+});
+
+/**
+ * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
+ * @deprecated since v3.0,please use new cc.TransitionFadeBL(t, scene);
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionFadeBL}
+ */
+cc.TransitionFadeBL.create = function (t, scene) {
+ return new cc.TransitionFadeBL(t, scene);
+};
+
+/**
+ * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
+ * @class
+ * @extends cc.TransitionFadeTR
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionFadeUp(time,scene);
+ */
+cc.TransitionFadeUp = cc.TransitionFadeTR.extend(/** @lends cc.TransitionFadeUp# */{
+
+ /**
+ * Constructor of TransitionFadeUp
+ * @function
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionFadeTR.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ /**
+ * @param {cc.Size} size
+ * @return {cc.FadeOutUpTiles}
+ */
+ actionWithSize: function (size) {
+ return new cc.FadeOutUpTiles(this._duration, size);
+ }
+});
+
+/**
+ * Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner.
+ * @deprecated since v3.0,please use new cc.TransitionFadeUp(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionFadeUp}
+ */
+cc.TransitionFadeUp.create = function (t, scene) {
+ return new cc.TransitionFadeUp(t, scene);
+};
+
+/**
+ * Fade the tiles of the outgoing scene from the top to the bottom.
+ * @class
+ * @extends cc.TransitionFadeTR
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionFadeDown(time,scene);
+ */
+cc.TransitionFadeDown = cc.TransitionFadeTR.extend(/** @lends cc.TransitionFadeDown# */{
+
+ /**
+ * Constructor of TransitionFadeDown
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ */
+ ctor: function (t, scene) {
+ cc.TransitionFadeTR.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ /**
+ * @param {cc.Size} size
+ * @return {*}
+ */
+ actionWithSize: function (size) {
+ return cc.fadeOutDownTiles(this._duration, size);
+ }
+});
+
+/**
+ * Fade the tiles of the outgoing scene from the top to the bottom.
+ * @deprecated since v3.0,please use new cc.TransitionFadeDown(t, scene) instead.
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @return {cc.TransitionFadeDown}
+ */
+cc.TransitionFadeDown.create = function (t, scene) {
+ return new cc.TransitionFadeDown(t, scene);
+};
diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js b/cocos2d/transitions/CCTransitionPageTurn.js
similarity index 59%
rename from cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js
rename to cocos2d/transitions/CCTransitionPageTurn.js
index 168b7e93e0..44a6bedd28 100644
--- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js
+++ b/cocos2d/transitions/CCTransitionPageTurn.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -29,17 +29,36 @@
* to transition to the scene beneath it simulating a page turn.
*
* This uses a 3DAction so it's strongly recommended that depth buffering
- * is turned on in cc.Director using:
+ * is turned on in cc.director using:
*
- * cc.Director.getInstance().setDepthBufferFormat(kDepthBuffer16);
+ * cc.director.setDepthBufferFormat(kDepthBuffer16);
* @class
* @extends cc.TransitionScene
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {Boolean} backwards
+ * @example
+ * var trans = new cc.TransitionPageTurn(t, scene, backwards);
*/
cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTurn# */{
+
+ /**
+ * @param {Number} t time in seconds
+ * @param {cc.Scene} scene
+ * @param {Boolean} backwards
+ */
+ ctor: function (t, scene, backwards) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ this._gridProxy = new cc.NodeGrid();
+ this.initWithDuration(t, scene, backwards);
+ },
+
/**
* @type Boolean
*/
- _back:true,
+ _back: true,
+ _gridProxy: null,
+ _className: "TransitionPageTurn",
/**
* Creates a base transition with duration and incoming scene.
@@ -50,7 +69,7 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu
* @param {Boolean} backwards
* @return {Boolean}
*/
- initWithDuration:function (t, scene, backwards) {
+ initWithDuration: function (t, scene, backwards) {
// XXX: needed before [super init]
this._back = backwards;
@@ -64,19 +83,19 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu
* @param {cc.Size} vector
* @return {cc.ReverseTime|cc.TransitionScene}
*/
- actionWithSize:function (vector) {
+ actionWithSize: function (vector) {
if (this._back)
- return cc.ReverseTime.create(cc.PageTurn3D.create(this._duration, vector)); // Get hold of the PageTurn3DAction
+ return cc.reverseTime(cc.pageTurn3D(this._duration, vector)); // Get hold of the PageTurn3DAction
else
- return cc.PageTurn3D.create(this._duration, vector); // Get hold of the PageTurn3DAction
+ return cc.pageTurn3D(this._duration, vector); // Get hold of the PageTurn3DAction
},
/**
* custom on enter
*/
- onEnter:function () {
+ onEnter: function () {
cc.TransitionScene.prototype.onEnter.call(this);
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
var x, y;
if (winSize.width > winSize.height) {
x = 16;
@@ -86,20 +105,34 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu
y = 16;
}
- var action = this.actionWithSize(cc.size(x, y));
+ var action = this.actionWithSize(cc.size(x, y)), gridProxy = this._gridProxy;
if (!this._back) {
- this._outScene.runAction( cc.Sequence.create(action,cc.CallFunc.create(this.finish, this),cc.StopGrid.create()));
+ gridProxy.setTarget(this._outScene);
+ gridProxy._performRecursive(cc.Node._stateCallbackType.onEnter);
+ gridProxy.runAction(cc.sequence(action, cc.callFunc(this.finish, this), cc.stopGrid()));
} else {
+ gridProxy.setTarget(this._inScene);
+ gridProxy._performRecursive(cc.Node._stateCallbackType.onEnter);
// to prevent initial flicker
- this._inScene.setVisible(false);
- this._inScene.runAction(
- cc.Sequence.create(cc.Show.create(),action, cc.CallFunc.create(this.finish, this), cc.StopGrid.create())
+ this._inScene.visible = false;
+ gridProxy.runAction(
+ cc.sequence(action, cc.callFunc(this.finish, this), cc.stopGrid())
);
+ this._inScene.runAction(cc.show());
}
},
- _sceneOrder:function () {
+ visit: function () {
+ //cc.TransitionScene.prototype.visit.call(this);
+ if (this._back)
+ this._outScene.visit();
+ else
+ this._inScene.visit();
+ this._gridProxy.visit();
+ },
+
+ _sceneOrder: function () {
this._isInSceneOnTop = this._back;
}
});
@@ -108,16 +141,12 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu
* Creates a base transition with duration and incoming scene.
* If back is true then the effect is reversed to appear as if the incoming
* scene is being turned from left over the outgoing scene.
+ * @deprecated since v3.0,please use new cc.TransitionPageTurn(t, scene, backwards) instead.
* @param {Number} t time in seconds
* @param {cc.Scene} scene
* @param {Boolean} backwards
* @return {cc.TransitionPageTurn}
- * @example
- * // Example
- * var myTransition = cc.TransitionPageTurn.create(1.5, nextScene, true)//true means backwards
*/
cc.TransitionPageTurn.create = function (t, scene, backwards) {
- var transition = new cc.TransitionPageTurn();
- transition.initWithDuration(t, scene, backwards);
- return transition;
+ return new cc.TransitionPageTurn(t, scene, backwards);
};
diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js b/cocos2d/transitions/CCTransitionProgress.js
similarity index 51%
rename from cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js
rename to cocos2d/transitions/CCTransitionProgress.js
index e8693b5f55..38e67e2d5f 100644
--- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js
+++ b/cocos2d/transitions/CCTransitionProgress.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -35,13 +35,37 @@ cc.SCENE_RADIAL = 0xc001;
* cc.TransitionProgress transition.
* @class
* @extends cc.TransitionScene
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionProgress(time,scene);
*/
cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgress# */{
_to:0,
_from:0,
_sceneToBeModified:null,
+ _className:"TransitionProgress",
/**
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ */
+ ctor:function (t, scene) {
+ cc.TransitionScene.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ _setAttrs: function(node, x, y) {
+ node.attr({
+ x: x,
+ y: y,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ },
+
+ /**
+ * Custom on enter.
* @override
*/
onEnter:function () {
@@ -50,13 +74,13 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre
// create a transparent color layer
// in which we are going to add our rendertextures
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
// create the second render texture for outScene
- var texture = cc.RenderTexture.create(winSize.width, winSize.height);
- texture.getSprite().setAnchorPoint(cc.p(0.5, 0.5));
- texture.setPosition(winSize.width / 2, winSize.height / 2);
- texture.setAnchorPoint(cc.p(0.5, 0.5));
+ var texture = new cc.RenderTexture(winSize.width, winSize.height);
+ texture.sprite.anchorX = 0.5;
+ texture.sprite.anchorY = 0.5;
+ this._setAttrs(texture, winSize.width / 2, winSize.height / 2);
// render outScene to its texturebuffer
texture.clear(0, 0, 0, 1);
@@ -65,16 +89,16 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre
texture.end();
// Since we've passed the outScene to the texture we don't need it.
- if (this._sceneToBeModified == this._outScene)
+ if (this._sceneToBeModified === this._outScene)
this.hideOutShowIn();
// We need the texture in RenderTexture.
var pNode = this._progressTimerNodeWithRenderTexture(texture);
// create the blend action
- var layerAction = cc.Sequence.create(
- cc.ProgressFromTo.create(this._duration, this._from, this._to),
- cc.CallFunc.create(this.finish, this));
+ var layerAction = cc.sequence(
+ cc.progressFromTo(this._duration, this._from, this._to),
+ cc.callFunc(this.finish, this));
// run the blend action
pNode.runAction(layerAction);
@@ -83,6 +107,7 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre
},
/**
+ * custom on exit
* @override
*/
onExit:function () {
@@ -98,7 +123,7 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre
},
_progressTimerNodeWithRenderTexture:function (texture) {
- cc.Assert(false, "override me - abstract class");
+ cc.log("cc.TransitionProgress._progressTimerNodeWithRenderTexture(): should be overridden in subclass");
return null;
},
@@ -109,17 +134,14 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre
/**
* create a cc.TransitionProgress object
+ * @deprecated since v3.0,please use new cc.TransitionProgress(t, scene) instead.
* @function
* @param {Number} t time
* @param {cc.Scene} scene
* @return {cc.TransitionProgress}
*/
cc.TransitionProgress.create = function (t, scene) {
- var tempScene = new cc.TransitionProgress();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
+ return new cc.TransitionProgress(t, scene);
};
/**
@@ -127,23 +149,35 @@ cc.TransitionProgress.create = function (t, scene) {
* A counter clock-wise radial transition to the next scene
* @class
* @extends cc.TransitionProgress
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionProgressRadialCCW(t, scene);
*/
cc.TransitionProgressRadialCCW = cc.TransitionProgress.extend(/** @lends cc.TransitionProgressRadialCCW# */{
- _progressTimerNodeWithRenderTexture:function (texture) {
- var size = cc.Director.getInstance().getWinSize();
- var pNode = cc.ProgressTimer.create(texture.getSprite());
+ /**
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ */
+ ctor:function (t, scene) {
+ cc.TransitionProgress.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ _progressTimerNodeWithRenderTexture:function (texture) {
+ var size = cc.director.getWinSize();
+ var pNode = new cc.ProgressTimer(texture.sprite);
// but it is flipped upside down so we flip the sprite
- if (cc.renderContextType === cc.WEBGL)
- pNode.getSprite().setFlippedY(true);
- pNode.setType(cc.PROGRESS_TIMER_TYPE_RADIAL);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ pNode.sprite.flippedY = true;
+ pNode.type = cc.ProgressTimer.TYPE_RADIAL;
// Return the radial type that we want to use
- pNode.setReverseDirection(false);
- pNode.setPercentage(100);
- pNode.setPosition(size.width / 2, size.height / 2);
- pNode.setAnchorPoint(cc.p(0.5, 0.5));
+ pNode.reverseDir = false;
+ pNode.percentage = 100;
+ this._setAttrs(pNode, size.width / 2, size.height / 2);
return pNode;
}
@@ -151,17 +185,15 @@ cc.TransitionProgressRadialCCW = cc.TransitionProgress.extend(/** @lends cc.Tran
/**
* create a cc.TransitionProgressRadialCCW object
- * @function
+ * @deprecated since v3.0,please use new cc.TransitionProgressRadialCCW(t, scene) instead.
* @param {Number} t time
* @param {cc.Scene} scene
* @return {cc.TransitionProgressRadialCCW}
+ * @example
+ * var trans = new cc.TransitionProgressRadialCCW(time,scene);
*/
cc.TransitionProgressRadialCCW.create = function (t, scene) {
- var tempScene = new cc.TransitionProgressRadialCCW();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
+ return new cc.TransitionProgressRadialCCW(t, scene);
};
/**
@@ -169,23 +201,34 @@ cc.TransitionProgressRadialCCW.create = function (t, scene) {
* A counter colock-wise radial transition to the next scene
* @class
* @extends cc.TransitionProgress
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionProgressRadialCW(t, scene);
*/
cc.TransitionProgressRadialCW = cc.TransitionProgress.extend(/** @lends cc.TransitionProgressRadialCW# */{
- _progressTimerNodeWithRenderTexture:function (texture) {
- var size = cc.Director.getInstance().getWinSize();
+ /**
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ */
+ ctor:function (t, scene) {
+ cc.TransitionProgress.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
- var pNode = cc.ProgressTimer.create(texture.getSprite());
+ _progressTimerNodeWithRenderTexture:function (texture) {
+ var size = cc.director.getWinSize();
+ var pNode = new cc.ProgressTimer(texture.sprite);
// but it is flipped upside down so we flip the sprite
- if (cc.renderContextType === cc.WEBGL)
- pNode.getSprite().setFlippedY(true);
- pNode.setType(cc.PROGRESS_TIMER_TYPE_RADIAL);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ pNode.sprite.flippedY = true;
+ pNode.type = cc.ProgressTimer.TYPE_RADIAL;
// Return the radial type that we want to use
- pNode.setReverseDirection(true);
- pNode.setPercentage(100);
- pNode.setPosition(size.width / 2, size.height / 2);
- pNode.setAnchorPoint(cc.p(0.5, 0.5));
+ pNode.reverseDir = true;
+ pNode.percentage = 100;
+ this._setAttrs(pNode, size.width / 2, size.height / 2);
return pNode;
}
@@ -193,17 +236,17 @@ cc.TransitionProgressRadialCW = cc.TransitionProgress.extend(/** @lends cc.Trans
/**
* create a cc.TransitionProgressRadialCW object
- * @function
+ * @deprecated since v3.0,please use cc.TransitionProgressRadialCW(t, scene) instead.
* @param {Number} t time
* @param {cc.Scene} scene
* @return {cc.TransitionProgressRadialCW}
*/
cc.TransitionProgressRadialCW.create = function (t, scene) {
var tempScene = new cc.TransitionProgressRadialCW();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
+ if ((tempScene !== null) && (tempScene.initWithDuration(t, scene))) {
return tempScene;
}
- return null;
+ return new cc.TransitionProgressRadialCW(t, scene);
};
/**
@@ -211,24 +254,35 @@ cc.TransitionProgressRadialCW.create = function (t, scene) {
* A colock-wise radial transition to the next scene
* @class
* @extends cc.TransitionProgress
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionProgressHorizontal(t, scene);
*/
cc.TransitionProgressHorizontal = cc.TransitionProgress.extend(/** @lends cc.TransitionProgressHorizontal# */{
- _progressTimerNodeWithRenderTexture:function (texture) {
- var size = cc.Director.getInstance().getWinSize();
+ /**
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ */
+ ctor:function (t, scene) {
+ cc.TransitionProgress.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
- var pNode = cc.ProgressTimer.create(texture.getSprite());
+ _progressTimerNodeWithRenderTexture:function (texture) {
+ var size = cc.director.getWinSize();
+ var pNode = new cc.ProgressTimer(texture.sprite);
// but it is flipped upside down so we flip the sprite
- if (cc.renderContextType === cc.WEBGL)
- pNode.getSprite().setFlippedY(true);
- pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ pNode.sprite.flippedY = true;
+ pNode.type = cc.ProgressTimer.TYPE_BAR;
- pNode.setMidpoint(cc.p(1, 0));
- pNode.setBarChangeRate(cc.p(1, 0));
+ pNode.midPoint = cc.p(1, 0);
+ pNode.barChangeRate = cc.p(1, 0);
- pNode.setPercentage(100);
- pNode.setPosition(size.width / 2, size.height / 2);
- pNode.setAnchorPoint(cc.p(0.5, 0.5));
+ pNode.percentage = 100;
+ this._setAttrs(pNode, size.width / 2, size.height / 2);
return pNode;
}
@@ -236,41 +290,49 @@ cc.TransitionProgressHorizontal = cc.TransitionProgress.extend(/** @lends cc.Tra
/**
* create a cc.TransitionProgressHorizontal object
- * @function
+ * @deprecated since v3.0,please use new cc.TransitionProgressHorizontal(t, scene) instead.
* @param {Number} t time
* @param {cc.Scene} scene
* @return {cc.TransitionProgressHorizontal}
*/
cc.TransitionProgressHorizontal.create = function (t, scene) {
- var tempScene = new cc.TransitionProgressHorizontal();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
+ return new cc.TransitionProgressHorizontal(t, scene);
};
/**
* cc.TransitionProgressVertical transition.
* @class
* @extends cc.TransitionProgress
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ * @example
+ * var trans = new cc.TransitionProgressVertical(t, scene);
*/
cc.TransitionProgressVertical = cc.TransitionProgress.extend(/** @lends cc.TransitionProgressVertical# */{
- _progressTimerNodeWithRenderTexture:function (texture) {
- var size = cc.Director.getInstance().getWinSize();
- var pNode = cc.ProgressTimer.create(texture.getSprite());
+ /**
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ */
+ ctor:function (t, scene) {
+ cc.TransitionProgress.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ _progressTimerNodeWithRenderTexture:function (texture) {
+ var size = cc.director.getWinSize();
+ var pNode = new cc.ProgressTimer(texture.sprite);
// but it is flipped upside down so we flip the sprite
- if (cc.renderContextType === cc.WEBGL)
- pNode.getSprite().setFlippedY(true);
- pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ pNode.sprite.flippedY = true;
+ pNode.type = cc.ProgressTimer.TYPE_BAR;
- pNode.setMidpoint(cc.p(0, 0));
- pNode.setBarChangeRate(cc.p(0, 1));
+ pNode.midPoint = cc.p(0, 0);
+ pNode.barChangeRate = cc.p(0, 1);
- pNode.setPercentage(100);
- pNode.setPosition(size.width / 2, size.height / 2);
- pNode.setAnchorPoint(cc.p(0.5, 0.5));
+ pNode.percentage = 100;
+ this._setAttrs(pNode, size.width / 2, size.height / 2);
return pNode;
}
@@ -278,17 +340,13 @@ cc.TransitionProgressVertical = cc.TransitionProgress.extend(/** @lends cc.Trans
/**
* create a cc.TransitionProgressVertical object
- * @function
+ * @deprecated since v3.0,please use new cc.TransitionProgressVertical(t, scene) instead.
* @param {Number} t time
* @param {cc.Scene} scene
* @return {cc.TransitionProgressVertical}
*/
cc.TransitionProgressVertical.create = function (t, scene) {
- var tempScene = new cc.TransitionProgressVertical();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
+ return new cc.TransitionProgressVertical(t, scene);
};
/**
@@ -297,21 +355,30 @@ cc.TransitionProgressVertical.create = function (t, scene) {
* @extends cc.TransitionProgress
*/
cc.TransitionProgressInOut = cc.TransitionProgress.extend(/** @lends cc.TransitionProgressInOut# */{
- _progressTimerNodeWithRenderTexture:function (texture) {
- var size = cc.Director.getInstance().getWinSize();
- var pNode = cc.ProgressTimer.create(texture.getSprite());
+ /**
+ * The constructor of cc.TransitionProgressInOut. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ */
+ ctor:function (t, scene) {
+ cc.TransitionProgress.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ _progressTimerNodeWithRenderTexture:function (texture) {
+ var size = cc.director.getWinSize();
+ var pNode = new cc.ProgressTimer(texture.sprite);
// but it is flipped upside down so we flip the sprite
- if (cc.renderContextType === cc.WEBGL)
- pNode.getSprite().setFlippedY(true);
- pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ pNode.sprite.flippedY = true;
+ pNode.type = cc.ProgressTimer.TYPE_BAR;
- pNode.setMidpoint(cc.p(0.5, 0.5));
- pNode.setBarChangeRate(cc.p(1, 1));
+ pNode.midPoint = cc.p(0.5, 0.5);
+ pNode.barChangeRate = cc.p(1, 1);
- pNode.setPercentage(0);
- pNode.setPosition(size.width / 2, size.height / 2);
- pNode.setAnchorPoint(cc.p(0.5, 0.5));
+ pNode.percentage = 0;
+ this._setAttrs(pNode, size.width / 2, size.height / 2);
return pNode;
},
@@ -328,16 +395,13 @@ cc.TransitionProgressInOut = cc.TransitionProgress.extend(/** @lends cc.Transiti
/**
* create a cc.TransitionProgressInOut object
* @function
+ * @deprecated
* @param {Number} t time
* @param {cc.Scene} scene
* @return {cc.TransitionProgressInOut}
*/
cc.TransitionProgressInOut.create = function (t, scene) {
- var tempScene = new cc.TransitionProgressInOut();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
+ return new cc.TransitionProgressInOut(t, scene);
};
/**
@@ -346,21 +410,30 @@ cc.TransitionProgressInOut.create = function (t, scene) {
* @extends cc.TransitionProgress
*/
cc.TransitionProgressOutIn = cc.TransitionProgress.extend(/** @lends cc.TransitionProgressOutIn# */{
- _progressTimerNodeWithRenderTexture:function (texture) {
- var size = cc.Director.getInstance().getWinSize();
- var pNode = cc.ProgressTimer.create(texture.getSprite());
+ /**
+ * The constructor of cc.TransitionProgressOutIn. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {Number} t time
+ * @param {cc.Scene} scene
+ */
+ ctor:function (t, scene) {
+ cc.TransitionProgress.prototype.ctor.call(this);
+ scene && this.initWithDuration(t, scene);
+ },
+
+ _progressTimerNodeWithRenderTexture:function (texture) {
+ var size = cc.director.getWinSize();
+ var pNode = new cc.ProgressTimer(texture.sprite);
// but it is flipped upside down so we flip the sprite
- if (cc.renderContextType === cc.WEBGL)
- pNode.getSprite().setFlippedY(true);
- pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ pNode.sprite.flippedY = true;
+ pNode.type = cc.ProgressTimer.TYPE_BAR;
- pNode.setMidpoint(cc.p(0.5, 0.5));
- pNode.setBarChangeRate(cc.p(1, 1));
+ pNode.midPoint = cc.p(0.5, 0.5);
+ pNode.barChangeRate = cc.p(1, 1);
- pNode.setPercentage(100);
- pNode.setPosition(size.width / 2, size.height / 2);
- pNode.setAnchorPoint(cc.p(0.5, 0.5));
+ pNode.percentage = 100;
+ this._setAttrs(pNode, size.width / 2, size.height / 2);
return pNode;
}
@@ -369,14 +442,11 @@ cc.TransitionProgressOutIn = cc.TransitionProgress.extend(/** @lends cc.Transiti
/**
* create a cc.TransitionProgressOutIn object
* @function
+ * @deprecated
* @param {Number} t time
* @param {cc.Scene} scene
* @return {cc.TransitionProgressOutIn}
*/
cc.TransitionProgressOutIn.create = function (t, scene) {
- var tempScene = new cc.TransitionProgressOutIn();
- if ((tempScene != null) && (tempScene.initWithDuration(t, scene))) {
- return tempScene;
- }
- return null;
+ return new cc.TransitionProgressOutIn(t, scene);
};
diff --git a/extensions/CCEditBox.js b/extensions/CCEditBox.js
deleted file mode 100644
index 9b68e37721..0000000000
--- a/extensions/CCEditBox.js
+++ /dev/null
@@ -1,568 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2012 James Chen
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * @constant
- * @type Number
- */
-cc.KEYBOARD_RETURNTYPE_DEFAULT = 0;
-
-/**
- * @constant
- * @type Number
- */
-cc.KEYBOARD_RETURNTYPE_DONE = 1;
-
-/**
- * @constant
- * @type Number
- */
-cc.KEYBOARD_RETURNTYPE_SEND = 2;
-
-/**
- * @constant
- * @type Number
- */
-cc.KEYBOARD_RETURNTYPE_SEARCH = 3;
-
-/**
- * @constant
- * @type Number
- */
-cc.KEYBOARD_RETURNTYPE_GO = 4;
-
-/**
- * The EditBoxInputMode defines the type of text that the user is allowed * to enter.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_MODE_ANY = 0;
-
-/**
- * The user is allowed to enter an e-mail address.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_MODE_EMAILADDR = 1;
-
-/**
- * The user is allowed to enter an integer value.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_MODE_NUMERIC = 2;
-
-/**
- * The user is allowed to enter a phone number.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_MODE_PHONENUMBER = 3;
-
-/**
- * The user is allowed to enter a URL.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_MODE_URL = 4;
-
-/**
- * The user is allowed to enter a real number value.
- * This extends kEditBoxInputModeNumeric by allowing a decimal point.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_MODE_DECIMAL = 5;
-
-/**
- * The user is allowed to enter any text, except for line breaks.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_MODE_SINGLELINE = 6;
-
-/**
- * Indicates that the text entered is confidential data that should be
- * obscured whenever possible. This implies EDIT_BOX_INPUT_FLAG_SENSITIVE.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_FLAG_PASSWORD = 0;
-
-/**
- * Indicates that the text entered is sensitive data that the
- * implementation must never store into a dictionary or table for use
- * in predictive, auto-completing, or other accelerated input schemes.
- * A credit card number is an example of sensitive data.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_FLAG_SENSITIVE = 1;
-
-/**
- * This flag is a hint to the implementation that during text editing,
- * the initial letter of each word should be capitalized.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD = 2;
-
-/**
- * This flag is a hint to the implementation that during text editing,
- * the initial letter of each sentence should be capitalized.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE = 3;
-
-/**
- * Capitalize all characters automatically.
- * @constant
- * @type Number
- */
-cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS = 4;
-
-cc.EditBoxDelegate = cc.Class.extend({
- /**
- * This method is called when an edit box gains focus after keyboard is shown.
- * @param {cc.EditBox} sender
- */
- editBoxEditingDidBegin: function (sender) {
- },
-
- /**
- * This method is called when an edit box loses focus after keyboard is hidden.
- * @param {cc.EditBox} sender
- */
- editBoxEditingDidEnd: function (sender) {
- },
-
- /**
- * This method is called when the edit box text was changed.
- * @param {cc.EditBox} sender
- * @param {String} text
- */
- editBoxTextChanged: function (sender, text) {
- },
-
- /**
- * This method is called when the return button was pressed or the outside area of keyboard was touched.
- * @param {cc.EditBox} sender
- */
- editBoxReturn: function (sender) {
- }
-});
-
-/**
- * brief Class for edit box.
- *
- * You can use this widget to gather small amounts of text from the user.
- *
- */
-cc.EditBox = cc.ControlButton.extend({
- _domInputSprite: null,
-
- _delegate: null,
- _editBoxInputMode: cc.EDITBOX_INPUT_MODE_ANY,
- _editBoxInputFlag: cc.EDITBOX_INPUT_FLAG_SENSITIVE,
- _keyboardReturnType: cc.KEYBOARD_RETURNTYPE_DEFAULT,
-
- _text: "",
- _placeholderText: "",
- _textColor: null,
- _placeholderColor: null,
- _maxLength: 50,
- _adjustHeight: 18,
-
- _edTxt: null,
- _edFontSize: 14,
- _edFontName: "Arial",
-
- _placeholderFontName: "",
- _placeholderFontSize: 14,
-
- _tooltip: false,
-
- /**
- * * Constructor.
- * */
- ctor: function (boxSize) {
- cc.ControlButton.prototype.ctor.call(this);
-
- this._textColor = cc.WHITE;
- this._placeholderColor = cc.GRAY;
- this.setContentSize(boxSize);
- this._domInputSprite = new cc.Sprite();
- this._domInputSprite.draw = function(){ }; //redefine draw function
- this.addChild(this._domInputSprite);
- var selfPointer = this;
- this._edTxt = document.createElement("input");
- this._edTxt.type = "text";
- this._edTxt.style.fontSize = this._edFontSize + "px";
- this._edTxt.style.color = "#000000";
- this._edTxt.style.border = 0;
- this._edTxt.style.background = "transparent";
- //this._edTxt.style.paddingLeft = "2px";
- this._edTxt.style.width = "100%";
- this._edTxt.style.height = "100%";
- this._edTxt.style.active = 0;
- this._edTxt.style.outline = "medium";
-
- // TODO the event listener will be remove when EditBox removes from parent.
- this._edTxt.addEventListener("input", function () {
- if (selfPointer._delegate && selfPointer._delegate.editBoxTextChanged)
- selfPointer._delegate.editBoxTextChanged(selfPointer, this.value);
- });
- this._edTxt.addEventListener("keypress", function (e) {
- if (e.keyCode === cc.KEY.enter) {
- e.stopPropagation();
- e.preventDefault();
- cc.canvas.focus();
- }
- });
- this._edTxt.addEventListener("focus", function () {
- if (this.value == selfPointer._placeholderText) {
- this.value = "";
- this.style.fontSize = selfPointer._edFontSize + "px" ;
- this.style.color = cc.convertColor3BtoHexString(selfPointer._textColor);
- }
- if (selfPointer._delegate && selfPointer._delegate.editBoxEditingDidBegin)
- selfPointer._delegate.editBoxEditingDidBegin(selfPointer);
- });
- this._edTxt.addEventListener("blur", function () {
- if (this.value == "") {
- this.value = selfPointer._placeholderText;
- this.style.fontSize = selfPointer._placeholderFontSize + "px" ;
- this.style.color = cc.convertColor3BtoHexString(selfPointer._placeholderColor);
- }
- if (selfPointer._delegate && selfPointer._delegate.editBoxEditingDidEnd)
- selfPointer._delegate.editBoxEditingDidEnd(selfPointer);
- if (selfPointer._delegate && selfPointer._delegate.editBoxReturn)
- selfPointer._delegate.editBoxReturn(selfPointer);
- });
-
- cc.DOM.convert(this._domInputSprite);
- this._domInputSprite.dom.appendChild(this._edTxt);
- this._domInputSprite.dom.showTooltipDiv = false;
- this._domInputSprite.dom.style.width = (boxSize.width - 6) +"px";
- this._domInputSprite.dom.style.height = (boxSize.height - 6) +"px";
-
- //this._domInputSprite.dom.style.borderWidth = "1px";
- //this._domInputSprite.dom.style.borderStyle = "solid";
- //this._domInputSprite.dom.style.borderRadius = "8px";
- this._domInputSprite.canvas.remove();
- },
-
- /**
- * Set the font.
- * @param {String} fontName The font name.
- * @param {Number} fontSize The font size.
- */
- setFont: function (fontName, fontSize) {
- this._edFontSize = fontSize;
- this._edFontName = fontName;
- this._setFontToEditBox();
- },
-
- /**
- * set fontName
- * @param {String} fontName
- */
- setFontName: function(fontName){
- this._edFontName = fontName;
- this._setFontToEditBox();
- },
-
- /**
- * set fontSize
- * @param {Number} fontSize
- */
- setFontSize: function(fontSize){
- this._edFontSize = fontSize;
- this._setFontToEditBox();
- },
-
- _setFontToEditBox: function () {
- if (this._edTxt.value != this._placeholderText){
- this._edTxt.style.fontFamily = this._edFontName;
- this._edTxt.style.fontSize = this._edFontSize+"px";
- }
- },
-
- /**
- * Set the text entered in the edit box.
- * @param {string} text The given text.
- */
- setText: function (text) {
- if (text != null) {
- if (text == "") {
- this._edTxt.value = this._placeholderText;
- this._edTxt.style.color = cc.convertColor3BtoHexString(this._placeholderColor);
- } else {
- this._edTxt.value = text;
- this._edTxt.style.color = cc.convertColor3BtoHexString(this._textColor);
- }
- }
- },
-
- /**
- * Set the font color of the widget's text.
- * @param {cc.Color3B} color
- */
- setFontColor: function (color) {
- this._textColor = color;
- if (this._edTxt.value != this._placeholderText) {
- this._edTxt.style.color = cc.convertColor3BtoHexString(color);
- }
- },
-
- /**
- *
- * Sets the maximum input length of the edit box.
- * Setting this value enables multiline input mode by default.
- *
- * @param {Number} maxLength The maximum length.
- */
- setMaxLength: function (maxLength) {
- if (!isNaN(maxLength) && maxLength > 0) {
- this._maxLength = maxLength;
- this._edTxt.maxLength = maxLength;
- }
- },
-
- /**
- * Gets the maximum input length of the edit box.
- * @return {Number} Maximum input length.
- */
- getMaxLength: function () {
- return this._maxLength;
- },
-
- /**
- * Set a text in the edit box that acts as a placeholder when an edit box is empty.
- * @param {string} text The given text.
- */
- setPlaceHolder: function (text) {
- if (text != null) {
- var oldPlaceholderText = this._placeholderText;
- this._placeholderText = text;
- if (this._edTxt.value == oldPlaceholderText) {
- this._edTxt.value = text;
- this._edTxt.style.color = cc.convertColor3BtoHexString(this._placeholderColor);
- this._setPlaceholderFontToEditText();
- }
- }
- },
-
- /**
- * Set the placeholder's font.
- * @param {String} fontName
- * @param {Number} fontSize
- */
- setPlaceholderFont: function (fontName, fontSize) {
- this._placeholderFontName = fontName;
- this._placeholderFontSize = fontSize;
- this._setPlaceholderFontToEditText();
- },
-
- /**
- * Set the placeholder's fontName.
- * @param {String} fontName
- */
- setPlaceholderFontName: function (fontName) {
- this._placeholderFontName = fontName;
- this._setPlaceholderFontToEditText();
- },
-
- /**
- * Set the placeholder's fontSize.
- * @param {Number} fontSize
- */
- setPlaceholderFontSize: function (fontSize) {
- this._placeholderFontSize = fontSize;
- this._setPlaceholderFontToEditText();
- },
-
- _setPlaceholderFontToEditText: function () {
- if (this._edTxt.value == this._placeholderText){
- this._edTxt.style.fontFamily = this._placeholderFontName;
- this._edTxt.style.fontSize = this._placeholderFontSize + "px";
- }
- },
-
- /**
- * Set the font color of the placeholder text when the edit box is empty.
- * @param {cc.Color3B} color
- */
- setPlaceholderFontColor: function (color) {
- this._placeholderColor = color;
- if (this._edTxt.value == this._placeholderText) {
- this._edTxt.style.color = cc.convertColor3BtoHexString(color);
- }
- },
-
- /**
- * Set the input flags that are to be applied to the edit box.
- * @param {Number} inputFlag One of the EditBoxInputFlag constants.
- * e.g.cc.EDITBOX_INPUT_FLAG_PASSWORD
- */
- setInputFlag: function (inputFlag) {
- this._editBoxInputFlag = inputFlag;
- if (inputFlag == cc.EDITBOX_INPUT_FLAG_PASSWORD)
- this._edTxt.type = "password";
- else
- this._edTxt.type = "text";
- },
-
- /**
- * Gets the input string of the edit box.
- * @return {string}
- */
- getText: function () {
- return this._edTxt.value;
- },
-
- /**
- * Init edit box with specified size.
- * @param {cc.Size} size
- * @param {cc.Color3B | cc.Scale9Sprite} normal9SpriteBg
- */
- initWithSizeAndBackgroundSprite: function (size, normal9SpriteBg) {
- if (this.initWithBackgroundSprite(normal9SpriteBg)) {
- this._domInputSprite.setPosition(3, 3);
-
- this.setZoomOnTouchDown(false);
- this.setPreferredSize(size);
- this.setPosition(0, 0);
- this._addTargetWithActionForControlEvent(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_UP_INSIDE);
- return true;
- }
- return false;
- },
-
- /* override functions */
- /**
- * Set the delegate for edit box.
- */
- setDelegate: function (delegate) {
- this._delegate = delegate;
- },
-
- /**
- * Get a text in the edit box that acts as a placeholder when an
- * edit box is empty.
- * @return {String}
- */
- getPlaceHolder: function () {
- return this._placeholderText;
- },
-
- /**
- * Set the input mode of the edit box.
- * @param {Number} inputMode One of the EditBoxInputMode constants.
- */
- setInputMode: function (inputMode) {
- this._editBoxInputMode = inputMode;
- },
-
- /**
- * Set the return type that are to be applied to the edit box.
- * @param {Number} returnType One of the CCKeyboardReturnType constants.
- */
- setReturnType: function (returnType) {
- this._keyboardReturnType = returnType;
- },
-
- keyboardWillShow: function (info) {
- var rectTracked = cc.EditBox.getRect(this);
- // some adjustment for margin between the keyboard and the edit box.
- rectTracked.y -= 4;
- // if the keyboard area doesn't intersect with the tracking node area, nothing needs to be done.
- if (!rectTracked.intersectsRect(info.end)) {
- cc.log("needn't to adjust view layout.");
- return;
- }
-
- // assume keyboard at the bottom of screen, calculate the vertical adjustment.
- this._adjustHeight = info.end.getMaxY() - rectTracked.getMinY();
- // CCLOG("CCEditBox:needAdjustVerticalPosition(%f)", m_fAdjustHeight);
-
- //callback
- },
- keyboardDidShow: function (info) {
- },
- keyboardWillHide: function (info) {
- //if (m_pEditBoxImpl != NULL) {
- // m_pEditBoxImpl->doAnimationWhenKeyboardMove(info.duration, -m_fAdjustHeight);
- //}
- },
- keyboardDidHide: function (info) {
- },
-
- touchDownAction: function (sender, controlEvent) {
- //this._editBoxImpl.openKeyboard();
- },
-
- //HTML5 Only
- initWithBackgroundColor: function (size, bgColor) {
- this._edWidth = size.width;
- this.dom.style.width = this._edWidth.toString() + "px";
- this._edHeight = size.height;
- this.dom.style.height = this._edHeight.toString() + "px";
- this.dom.style.backgroundColor = cc.convertColor3BtoHexString(bgColor);
- }
-});
-
-cc.EditBox.getRect = function (node) {
- var contentSize = node.getContentSize();
- var rect = cc.rect(0, 0, contentSize.width, contentSize.height);
- return cc.RectApplyAffineTransform(rect, node.nodeToWorldTransform());
-};
-
-/**
- * create a edit box with size and background-color or
- * @param {cc.Size} size
- * @param {cc.Color3B | cc.Scale9Sprite } normal9SpriteBg
- */
-cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg) {
- var edbox = new cc.EditBox(size);
- if (normal9SpriteBg instanceof cc.Color3B) {
- edbox.setBackgroundColor(normal9SpriteBg);
- } else {
- //Todo
- if (edbox.initWithSizeAndBackgroundSprite(size, normal9SpriteBg)) {
- if (press9SpriteBg)
- edbox.setBackgroundSpriteForState(press9SpriteBg, cc.CONTROL_STATE_HIGHLIGHTED);
-
- if (disabled9SpriteBg)
- edbox.setBackgroundSpriteForState(disabled9SpriteBg, cc.CONTROL_STATE_DISABLED);
- }
- }
- return edbox;
-};
-
-
-
-
diff --git a/extensions/CocoStudio/Action/CCActionFrame.js b/extensions/CocoStudio/Action/CCActionFrame.js
deleted file mode 100644
index 58d65004b2..0000000000
--- a/extensions/CocoStudio/Action/CCActionFrame.js
+++ /dev/null
@@ -1,337 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-cc.FrameType = {
- Move: 0,
- Scale: 1,
- Rotate: 2,
- Tint: 3,
- Fade: 4,
- Max: 5
-};
-
-/**
- * Base class for cc.ActionFrame
- * @class
- * @extends cc.Class
- */
-cc.ActionFrame = cc.Class.extend({
- _frameType: 0,
- _easingType: 0,
- _frameIndex: 0,
- _time: 0,
- ctor: function () {
- this._frameType = 0;
- this._easingType = 0;
- this._frameIndex = 0;
- this._time = 0;
- },
-
- /**
- * Changes the index of action frame
- * @param {number} index
- */
- setFrameIndex: function (index) {
- this._frameIndex = index;
- },
-
- /**
- * Gets the index of action frame
- * @returns {number}
- */
- getFrameIndex: function () {
- return this._frameIndex;
- },
-
- /**
- * Changes the time of action frame
- * @param {number} fTime
- */
- setFrameTime: function (time) {
- this._time = time;
- },
-
- /**
- * Gets the time of action frame
- * @returns {number}
- */
- getFrameTime: function () {
- return this._time;
- },
-
- /**
- * Changes the type of action frame
- * @param {number} frameType
- */
- setFrameType: function (frameType) {
- this._frameType = frameType;
- },
-
- /**
- * Gets the type of action frame
- * @returns {number}
- */
- getFrameType: function () {
- return this._frameType;
- },
-
- /**
- * Changes the easing type.
- * @param {number} easingType
- */
- setEasingType: function (easingType) {
- this._easingType = easingType;
- },
-
- /**
- * Gets the easing type.
- * @returns {number}
- */
- getEasingType: function () {
- return this._easingType;
- },
-
- /**
- * Gets the action of ActionFrame.
- * @param {number} duration
- * @returns {null}
- */
- getAction: function (duration) {
- return null;
- }
-});
-
-/**
- * Base class for cc.ActionMoveFrame
- * @class
- * @extends cc.ActionFrame
- */
-cc.ActionMoveFrame = cc.ActionFrame.extend({
- _position: null,
- ctor: function () {
- cc.ActionFrame.prototype.ctor.call(this);
- this._position = cc.p(0, 0);
- this._frameType = cc.FrameType.Move;
- },
-
- /**
- * Changes the move action position.
- * @param {cc.Point} pos
- */
- setPosition: function (pos) {
- this._position = pos;
- },
-
- /**
- * Gets the move action position.
- * @returns {cc.Point}
- */
- getPosition: function () {
- return this._position;
- },
-
- /**
- * Gets the CCAction of ActionFrame.
- * @param {number} duration
- * @returns {cc.MoveTo}
- */
- getAction: function (duration) {
- return cc.MoveTo.create(duration, this._position);
- }
-});
-
-/**
- * Base class for cc.ActionScaleFrame
- * @class
- * @extends cc.ActionFrame
- */
-cc.ActionScaleFrame = cc.ActionFrame.extend({
- _scaleX: 1,
- _scaleY: 1,
- ctor: function () {
- cc.ActionFrame.prototype.ctor.call(this);
- this._scaleX = 1;
- this._scaleY = 1;
- this._frameType = cc.FrameType.Scale;
- },
-
- /**
- * Changes the scale action scaleX.
- * @param {number} scaleX
- */
- setScaleX: function (scaleX) {
- this._scaleX = scaleX;
- },
-
- /**
- * Gets the scale action scaleX.
- * @returns {number} {number}
- */
- getScaleX: function () {
- return this._scaleX;
- },
-
- /**
- * Changes the scale action scaleY.
- * @param {number} scaleY
- */
- setScaleY: function (scaleY) {
- this._scaleY = scaleY;
- },
-
- /**
- * Gets the scale action scaleY.
- * @returns {number}
- */
- getScaleY: function () {
- return this._scaleY;
- },
-
- /**
- * Gets the action of ActionFrame.
- * @param duration
- * @returns {cc.ScaleTo}
- */
- getAction: function (duration) {
- return cc.ScaleTo.create(duration, this._scaleX, this._scaleY);
- }
-});
-
-/**
- * Base class for cc.ActionRotationFrame
- * @class
- * @extends cc.ActionFrame
- */
-cc.ActionRotationFrame = cc.ActionFrame.extend({
- _rotation: 0,
- ctor: function () {
- cc.ActionFrame.prototype.ctor.call(this);
- this._rotation = 0;
- this._frameType = cc.FrameType.Rotate;
- },
-
- /**
- * Changes rotate action rotation.
- * @param {number} rotation
- */
- setRotation: function (rotation) {
- this._rotation = rotation;
- },
-
- /**
- * Gets the rotate action rotation.
- * @returns {number}
- */
- getRotation: function () {
- return this._rotation;
- },
-
- /**
- * Gets the CCAction of ActionFrame.
- * @param {number} duration
- * @returns {cc.RotateTo}
- */
- getAction: function (duration) {
- return cc.RotateTo.create(duration, this._rotation);
- }
-});
-
-/**
- * Base class for cc.ActionFadeFrame
- * @class
- * @extends cc.ActionFrame
- */
-cc.ActionFadeFrame = cc.ActionFrame.extend({
- _opacity: 255,
- ctor: function () {
- cc.ActionFrame.prototype.ctor.call(this);
- this._opacity = 255;
- this._frameType = cc.FrameType.Fade;
- },
-
- /**
- * Changes the fade action opacity.
- * @param {number} opacity
- */
- setOpacity: function (opacity) {
- this._opacity = opacity;
- },
-
- /**
- * Gets the fade action opacity.
- * @returns {number}
- */
- getOpacity: function () {
- return this._opacity;
- },
-
- /**
- * Gets the CCAction of ActionFrame.
- * @param duration
- * @returns {cc.FadeTo}
- */
- getAction: function (duration) {
- return cc.FadeTo.create(duration, this._opacity);
- }
-});
-
-/**
- * Base class for cc.ActionTintFrame
- * @class
- * @extends cc.ActionFrame
- */
-cc.ActionTintFrame = cc.ActionFrame.extend({
- _color: 255,
- ctor: function () {
- cc.ActionFrame.prototype.ctor.call(this);
- this._color = 255;
- this._frameType = cc.FrameType.Tint;
- },
-
- /**
- * Changes the tint action color.
- * @param {number} color
- */
- setColor: function (color) {
- this._color = color;
- },
-
- /**
- * Gets the tint action color.
- * @returns {number}
- */
- getColor: function () {
- return this._color;
- },
-
- /**
- * Gets the action of ActionFrame.
- * @param duration
- * @returns {cc.TintTo}
- */
- getAction: function (duration) {
- return cc.TintTo.create(duration, this._color.r, this._color.g, this._color.b);
- }
-});
\ No newline at end of file
diff --git a/extensions/CocoStudio/Action/CCActionNode.js b/extensions/CocoStudio/Action/CCActionNode.js
deleted file mode 100644
index 1d779cf270..0000000000
--- a/extensions/CocoStudio/Action/CCActionNode.js
+++ /dev/null
@@ -1,406 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.ActionNode
- * @class
- * @extends cc.Class
- */
-cc.ActionNode = cc.Class.extend({
- _currentFrameIndex: 0,
- _destFrameIndex: 0,
- _unitTime: 0,
- _actionTag: 0,
- _bject: null,
- _actionSpawn: null,
- _action: null,
- _frameArray: null,
- _frameArrayNum: 0,
- ctor: function () {
- this._currentFrameIndex = 0;
- this._destFrameIndex = 0;
- this._unitTime = 0.1;
- this._actionTag = 0;
- this._bject = null;
- this._actionSpawn = null;
- this._action = null;
- this._frameArray = [];
- this._frameArrayNum = cc.FrameType.Max;
- for (var i = 0; i < this._frameArrayNum; i++) {
- this._frameArray.push([]);
- }
- },
-
- /**
- * Init properties with a json dictionary
- * @param {Object} dic
- * @param {Object} root
- */
- initWithDictionary: function (dic, root) {
- this.setActionTag(dic["ActionTag"]);
- var actionframelist = dic["actionframelist"];
- for (var i = 0; i < actionframelist.length; i++) {
- var actionFrameDic = actionframelist[i];
- var frameInex = actionFrameDic["frameid"];
- if (actionFrameDic.hasOwnProperty("positionx")) {
- var positionX = actionFrameDic["positionx"];
- var positionY = actionFrameDic["positiony"];
- var actionFrame = new cc.ActionMoveFrame();
- actionFrame.setFrameIndex(frameInex);
- actionFrame.setPosition(cc.p(positionX, positionY));
- var actionArray = this._frameArray[cc.FrameType.Move];
- actionArray.push(actionFrame);
- }
-
- if (actionFrameDic.hasOwnProperty("scalex")) {
- var scaleX = actionFrameDic["scalex"];
- var scaleY = actionFrameDic["scaley"];
- var actionFrame = new cc.ActionScaleFrame();
- actionFrame.setFrameIndex(frameInex);
- actionFrame.setScaleX(scaleX);
- actionFrame.setScaleY(scaleY);
- var actionArray = this._frameArray[cc.FrameType.Scale];
- actionArray.push(actionFrame);
- }
-
- if (actionFrameDic.hasOwnProperty("rotation")) {
- var rotation = actionFrameDic["rotation"];
- var actionFrame = new cc.ActionRotationFrame();
- actionFrame.setFrameIndex(frameInex);
- actionFrame.setRotation(rotation);
- var actionArray = this._frameArray[cc.FrameType.Rotate];
- actionArray.push(actionFrame);
- }
-
- if (actionFrameDic.hasOwnProperty("opacity")) {
- var opacity = actionFrameDic["opacity"];
- var actionFrame = new cc.ActionFadeFrame();
- actionFrame.setFrameIndex(frameInex);
- actionFrame.setOpacity(opacity);
- var actionArray = this._frameArray[cc.FrameType.Fade];
- actionArray.push(actionFrame);
- }
-
- if (actionFrameDic.hasOwnProperty("colorr")) {
- var colorR = actionFrameDic["colorr"];
- var colorG = actionFrameDic["colorg"];
- var colorB = actionFrameDic["colorb"];
- var actionFrame = new cc.ActionTintFrame();
- actionFrame.setFrameIndex(frameInex);
- actionFrame.setColor(cc.c3b(colorR, colorG, colorB));
- var actionArray = this._frameArray[cc.FrameType.Tint];
- actionArray.push(actionFrame);
- }
- actionFrameDic = null;
- }
- },
-
- /**
- * Sets the time interval of frame.
- * @param {number} time
- */
- setUnitTime: function (time) {
- this._unitTime = time;
- this.refreshActionProperty();
- },
-
- /**
- * Gets the time interval of frame.
- * @returns {number}
- */
- getUnitTime: function () {
- return this._unitTime;
- },
-
- /**
- * Sets tag for ActionNode
- * @param tag
- */
- setActionTag: function (tag) {
- this._actionTag = tag;
- },
-
- /**
- * Gets tag for ActionNode
- * @returns {number}
- */
- getActionTag: function () {
- return this._actionTag;
- },
-
- /**
- * Sets node which will run a action.
- * @param {Object} node
- */
- setObject: function (node) {
- this._object = node;
- },
-
- /**
- * Gets node which will run a action.
- * @returns {*}
- */
- getObject: function () {
- return this._object;
- },
-
- /**
- * get actionNode
- * @returns {cc.Node}
- */
- getActionNode: function () {
- if (this._object instanceof cc.Node) {
- return this._object;
- }
- else if (this._object instanceof cc.UIWidget) {
- return this._object.getRenderer();
- }
- return null;
- },
-
- /**
- * Insets a ActionFrame to ActionNode.
- * @param {number} index
- * @param {cc.ActionFrame} frame
- */
- insertFrame: function (index, frame) {
- if (frame == null) {
- return;
- }
- var frameType = frame.getFrameType();
- var array = this._frameArray[frameType];
- array[index] = frame;
- },
-
- /**
- * Pushs back a ActionFrame to ActionNode.
- * @param {cc.ActionFrame} frame
- */
- addFrame: function (frame) {
- if (!frame) {
- return;
- }
- var frameType = frame.getFrameType();
- var array = this._frameArray[frameType];
- array.push(frame);
- },
-
- /**
- * Remove a ActionFrame from ActionNode.
- * @param {cc.ActionFrame} frame
- */
- deleteFrame: function (frame) {
- if (frame == null) {
- return;
- }
- var frameType = frame.getFrameType();
- var array = this._frameArray[frameType];
- cc.ArrayRemoveObject(array, frame);
- },
-
- /**
- * Remove all ActionFrames from ActionNode.
- */
- clearAllFrame: function () {
- for (var i = 0; i < this._frameArrayNum; i++) {
- this._frameArray[i] = [];
- }
- },
-
- /**
- * Refresh property of action
- * @returns {null}
- */
- refreshActionProperty: function () {
- if (this._object == null) {
- return null;
- }
- var locSpawnArray = [];
- for (var i = 0; i < this._frameArrayNum; i++) {
- var locArray = this._frameArray[i];
- if (locArray.length <= 0) {
- continue;
- }
- var locSequenceArray = [];
- for (var j = 0; j < locArray.length; j++) {
- var locFrame = locArray[j];
- if (j != 0) {
- var locSrcFrame = locArray[j - 1];
- var locDuration = (locFrame.getFrameIndex() - locSrcFrame.getFrameIndex()) * this.getUnitTime();
- var locAction = locFrame.getAction(locDuration);
- locSequenceArray.push(locAction);
- }
- }
- var locSequence = cc.Sequence.create(locSequenceArray);
- if (locSequence != null) {
- locSpawnArray.push(locSequence);
- }
- }
-
- this._action = null;
- this._actionSpawn = cc.Spawn.create(locSpawnArray);
- return this._actionSpawn;
- },
-
- /**
- * Play the action.
- * @param {Boolean} loop
- */
- playAction: function (loop) {
- if (this._object == null || this._actionSpawn == null) {
- return;
- }
- if (loop) {
- this._action = cc.RepeatForever.create(this._actionSpawn);
- }
- else {
- this._action = cc.Sequence.create(this._actionSpawn, null);
- }
- this._action.retain();
- this.runAction();
- },
-
- /**
- * Run action.
- */
- runAction: function () {
- var node = this.getActionNode();
- if (node != null && this._action != null) {
- node.runAction(this._action);
- }
- },
-
- /**
- * Stop action.
- */
- stopAction: function () {
- var node = this.getActionNode();
- if (node != null && this._action != null) {
- node.stopAction(this._action);
- }
- },
-
- /**
- * Gets index of first ActionFrame.
- * @returns {number}
- */
- getFirstFrameIndex: function () {
- var locFrameindex = 99999;
- var locIsFindFrame = false;
- for (var i = 0; i < this._frameArrayNum; i++) {
- var locArray = this._frameArray[i];
- if (locArray.length <= 0) {
- continue;
- }
- locIsFindFrame = true;
- var locFrame = locArray[0];
- var locFrameIndex = locFrame.getFrameIndex();
- locFrameindex = locFrameindex > locFrameIndex ? locFrameIndex : locFrameindex;
- }
- if (!locIsFindFrame) {
- locFrameindex = 0;
- }
- return locFrameindex;
- },
-
- /**
- * Gets index of last ActionFrame.
- * @returns {number}
- */
- getLastFrameIndex: function () {
- var locFrameindex = -1;
- var locIsFindFrame = false;
- for (var i = 0; i < this._frameArrayNum; i++) {
- var locArray = this._frameArray[i];
- if (locArray.length <= 0) {
- continue;
- }
- locIsFindFrame = true;
- var locFrame = locArray[locArray.length - 1];
- var locFrameIndex = locFrame.getFrameIndex();
- locFrameindex = locFrameindex < locFrameIndex ? locFrameIndex : locFrameindex;
- }
- if (!locIsFindFrame) {
- locFrameindex = 0;
- }
- return locFrameindex;
- },
-
- /**
- * Updates action states to some time.
- * @param time
- * @returns {boolean}
- */
- updateActionToTimeLine: function (time) {
- var locIsFindFrame = false;
- var locUnitTime = this.getUnitTime();
- for (var i = 0; i < this._frameArrayNum; i++) {
- var locArray = this._frameArray[i];
- if (locArray == null) {
- continue;
- }
-
- for (var i = 0; i < locArray.length; i++) {
- var locFrame = locArray[i];
- if (locFrame.getFrameIndex() * locUnitTime == time) {
- this.easingToFrame(1.0, 1.0, locFrame);
- locIsFindFrame = true;
- break;
- }
- else if (locFrame.getFrameIndex() * locUnitTime > time) {
- if (i == 0) {
- this.easingToFrame(1.0, 1.0, locFrame);
- locIsFindFrame = false;
- }
- else {
- var locSrcFrame = locArray[i - 1];
- var locDuration = (locFrame.getFrameIndex() - locSrcFrame.getFrameIndex()) * locUnitTime;
- var locDelaytime = time - locSrcFrame.getFrameIndex() * locUnitTime;
- this.easingToFrame(locDuration, 1.0, locSrcFrame);
- this.easingToFrame(locDuration, locDelaytime / locDuration, locFrame);
- locIsFindFrame = true;
- }
- break;
- }
- }
- }
- return locIsFindFrame;
- },
-
- /**
- * Easing to frame
- * @param {number} duration
- * @param {number} delayTime
- * @param {cc.ActionFrame} destFrame
- */
- easingToFrame: function (duration, delayTime, destFrame) {
- var action = destFrame.getAction(duration);
- var node = this.getActionNode();
- if (action == null || node == null) {
- return;
- }
- action.startWithTarget(node);
- action.update(delayTime);
- }
-});
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/CCArmature.js b/extensions/CocoStudio/Armature/CCArmature.js
deleted file mode 100644
index 7e1e88d632..0000000000
--- a/extensions/CocoStudio/Armature/CCArmature.js
+++ /dev/null
@@ -1,621 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.Armature objects.
- * @class
- * @extends cc.NodeRGBA
- */
-cc.Armature = cc.NodeRGBA.extend({
- _animation:null,
- _armatureData:null,
- _batchNode:null,
- _name:"",
- _textureAtlas:null,
- _parentBone:null,
- _boneDic:null,
- _topBoneList:null,
- _armatureIndexDic:null,
- _offsetPoint:null,
- _version:0,
- _armatureTransformDirty:false,
- _body:null,
- ctor:function () {
- cc.NodeRGBA.prototype.ctor.call(this);
- this._animation = null;
- this._armatureData = null;
- this._batchNode = null;
- this._name = "";
- this._textureAtlas = null;
- this._parentBone = null;
- this._boneDic = null;
- this._topBoneList = [];
- this._armatureIndexDic = {};
- this._offsetPoint = cc.p(0, 0);
- this._version = 0;
- this._armatureTransformDirty = false;
- this._body = null;
- },
-
- /**
- * Initializes a CCArmature with the specified name and CCBone
- * @param {String} name
- * @param {cc.Bone} parentBone
- * @return {Boolean}
- */
- init:function (name, parentBone) {
- cc.NodeRGBA.prototype.init.call(this);
- if (parentBone) {
- this._parentBone = parentBone;
- }
- this.removeAllChildren();
- this._animation = new cc.ArmatureAnimation();
- this._animation.init(this);
- this._boneDic = {};
- this._boneList = [];
-
- this._name = (!name) ? "" : name;
- var armatureDataManager = cc.ArmatureDataManager.getInstance();
- if (name != "") {
- //animationData
- var animationData = armatureDataManager.getAnimationData(name);
- if (!animationData) {
- cc.log("AnimationData not exist! ");
- return false;
- }
- this._animation.setAnimationData(animationData);
-
- //armatureData
- var armatureData = armatureDataManager.getArmatureData(name);
- this._armatureData = armatureData;
-
- //boneDataDic
- var boneDataDic = armatureData.getBoneDataDic();
- for (var key in boneDataDic) {
- var bone = this.createBone(String(key));
- //! init bone's Tween to 1st movement's 1st frame
- do {
- var movData = animationData.getMovement(animationData.movementNames[0]);
- if (!movData) {
- break;
- }
- var _movBoneData = movData.getMovementBoneData(bone.getName());
- if (!_movBoneData || _movBoneData.frameList.length <= 0) {
- break;
- }
- var frameData = _movBoneData.getFrameData(0);
- if (!frameData) {
- break;
- }
- bone.getTweenData().copy(frameData);
- bone.changeDisplayByIndex(frameData.displayIndex, false);
- } while (0);
- }
- this.update(0);
- this.updateOffsetPoint();
- } else {
- this._name = "new_armature";
- this._armatureData = new cc.ArmatureData();
- this._armatureData.name = this._name;
-
- var animationData = new cc.AnimationData();
- animationData.name = this._name;
-
- armatureDataManager.addArmatureData(this._name, this._armatureData);
- armatureDataManager.addAnimationData(this._name, animationData);
-
- this._animation.setAnimationData(animationData);
- }
- if (cc.renderContextType === cc.WEBGL) {
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR));
- }
-
- this.unscheduleUpdate();
- this.scheduleUpdate();
-
- this.setCascadeOpacityEnabled(true);
- this.setCascadeColorEnabled(true);
- return true;
- },
-
- /**
- * create a bone
- * @param {String} boneName
- * @return {cc.Bone}
- */
- createBone:function (boneName) {
- var existedBone = this.getBone(boneName);
- if (existedBone) {
- return existedBone;
- }
- var boneData = this._armatureData.getBoneData(boneName);
- var parentName = boneData.parentName;
- var bone = null;
- if (parentName != "") {
- this.createBone(parentName);
- bone = cc.Bone.create(boneName);
- this.addBone(bone, parentName);
- } else {
- bone = cc.Bone.create(boneName);
- this.addBone(bone, "");
- }
-
- bone.setBoneData(boneData);
- bone.getDisplayManager().changeDisplayByIndex(-1, false);
- return bone;
- },
-
- /**
- * add a bone
- * @param {cc.Bone} bone
- * @param {String} parentName
- */
- addBone:function (bone, parentName) {
- if (!bone) {
- cc.log("Argument must be non-nil");
- return;
- }
- if (this._boneDic[bone.getName()]) {
- cc.log("bone already added. It can't be added again");
- return;
- }
-
- if (parentName) {
- var boneParent = this._boneDic[parentName];
- if (boneParent) {
- boneParent.addChildBone(bone);
- }
- else {
- if (this._parentBone)
- this._parentBone.addChildBone(bone);
- else
- this._topBoneList.push(bone);
- }
- }
- else {
- if (this._parentBone)
- this._parentBone.addChildBone(bone);
- else
- this._topBoneList.push(bone);
- }
- bone.setArmature(this);
- this._boneDic[bone.getName()] = bone;
- this.addChild(bone);
- },
-
- /**
- * remove a bone
- * @param {cc.Bone} bone
- * @param {Boolean} recursion
- */
- removeBone:function (bone, recursion) {
- if (!bone) {
- cc.log("bone must be added to the bone dictionary!");
- return;
- }
-
- bone.setArmature(null);
- bone.removeFromParent(recursion);
- cc.ArrayRemoveObject(this._boneList, bone);
- delete this._boneDic[bone.getName()];
- this.removeChild(bone, true);
- },
-
- /**
- * get a bone by name
- * @param {String} name
- * @return {cc.Bone}
- */
- getBone:function (name) {
- return this._boneDic[name];
- },
-
- /**
- * Change a bone's parent with the specified parent name.
- * @param {cc.Bone} bone
- * @param {String} parentName
- */
- changeBoneParent:function (bone, parentName) {
- if (!bone) {
- cc.log("bone must be added to the bone dictionary!");
- return;
- }
- var parentBone = bone.getParentBone();
- if(parentBone){
- cc.ArrayRemoveObject(parentBone.getChildrenBone(), bone);
- bone.setParentBone(null);
- }
-
- if (parentName) {
- var boneParent = this._boneDic[parentName];
- if (boneParent) {
- boneParent.addChildBone(bone);
- cc.ArrayRemoveObject(this._topBoneList,bone);
- }else{
- this._topBoneList.push(bone);
- }
- }
- },
-
- /**
- * Get CCArmature's bone dictionary
- * @return {Object}
- */
- getBoneDic:function () {
- return this._boneDic;
- },
-
- /**
- * Set contentSize and Calculate anchor point.
- */
- updateOffsetPoint:function () {
- // Set contentsize and Calculate anchor point.
- var rect = this.boundingBox();
- this.setContentSize(rect.size);
- var locOffsetPoint = this._offsetPoint;
- locOffsetPoint.x = -rect.x;
- locOffsetPoint.y = -rect.y;
- if (rect.width != 0 && rect.height != 0) {
- this.setAnchorPoint(cc.p(locOffsetPoint.x / rect.width, locOffsetPoint.y / rect.height));
- }
- },
-
- update:function (dt) {
- this._animation.update(dt);
- var locTopBoneList = this._topBoneList;
- for (var i = 0; i < locTopBoneList.length; i++) {
- locTopBoneList[i].update(dt);
- }
- this._armatureTransformDirty = false;
- },
-
- nodeToParentTransform:function () {
- return cc.Browser.supportWebGL ? this.nodeToParentTransformWEBGL() : this.nodeToParentTransformCanvas();
- },
-
- nodeToParentTransformWEBGL:function () {
- if (this._transformDirty) {
- this._armatureTransformDirty = true;
- // Translate values
- var x = this._position.x;
- var y = this._position.y;
- var apx = this._anchorPointInPoints.x, napx = -apx;
- var apy = this._anchorPointInPoints.y, napy = -apy;
- var scx = this._scaleX, scy = this._scaleY;
-
- if (this._ignoreAnchorPointForPosition) {
- x += apx;
- y += apy;
- }
-
- // Rotation values
- // Change rotation code to handle X and Y
- // If we skew with the exact same value for both x and y then we're simply just rotating
- var cx = 1, sx = 0, cy = 1, sy = 0;
- if (this._rotationX !== 0 || this._rotationY !== 0) {
- cx = Math.cos(-this._rotationRadiansX);
- sx = Math.sin(-this._rotationRadiansX);
- cy = Math.cos(-this._rotationRadiansY);
- sy = Math.sin(-this._rotationRadiansY);
- }
-
- // Add offset point
- x += cy * this._offsetPoint.x * this._scaleX + -sx * this._offsetPoint.y * this._scaleY;
- y += sy * this._offsetPoint.x * this._scaleX + cx * this._offsetPoint.y * this._scaleY;
-
- var needsSkewMatrix = ( this._skewX || this._skewY );
-
- // optimization:
- // inline anchor point calculation if skew is not needed
- // Adjusted transform calculation for rotational skew
- if (!needsSkewMatrix && (apx !== 0 || apy !== 0)) {
- x += cy * napx * scx + -sx * napy * scy;
- y += sy * napx * scx + cx * napy * scy;
- }
-
- // Build Transform Matrix
- // Adjusted transform calculation for rotational skew
- var t = {a:cy * scx, b:sy * scx, c:-sx * scy, d:cx * scy, tx:x, ty:y};
-
- // XXX: Try to inline skew
- // If skew is needed, apply skew and then anchor point
- if (needsSkewMatrix) {
- t = cc.AffineTransformConcat({a:1.0, b:Math.tan(cc.DEGREES_TO_RADIANS(this._skewY)),
- c:Math.tan(cc.DEGREES_TO_RADIANS(this._skewX)), d:1.0, tx:0.0, ty:0.0}, t);
-
- // adjust anchor point
- if (apx !== 0 || apy !== 0)
- t = cc.AffineTransformTranslate(t, napx, napy);
- }
-
- if (this._additionalTransformDirty) {
- t = cc.AffineTransformConcat(t, this._additionalTransform);
- this._additionalTransformDirty = false;
- }
- this._transform = t;
- this._transformDirty = false;
- }
- return this._transform;
- },
-
- nodeToParentTransformCanvas:function () {
- if (!this._transform)
- this._transform = {a:1, b:0, c:0, d:1, tx:0, ty:0};
- if (this._transformDirty) {
- this._armatureTransformDirty = true;
- var t = this._transform;// quick reference
- // base position
- t.tx = this._position.x;
- t.ty = this._position.y;
-
- // rotation Cos and Sin
- var Cos = 1, Sin = 0;
- if (this._rotationX) {
- Cos = Math.cos(this._rotationRadiansX);
- Sin = Math.sin(this._rotationRadiansX);
- }
-
- // base abcd
- t.a = t.d = Cos;
- t.c = -Sin;
- t.b = Sin;
-
- var lScaleX = this._scaleX, lScaleY = this._scaleY;
- var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y;
-
- // Firefox on Vista and XP crashes
- // GPU thread in case of scale(0.0, 0.0)
- var sx = (lScaleX < 0.000001 && lScaleX > -0.000001) ? 0.000001 : lScaleX,
- sy = (lScaleY < 0.000001 && lScaleY > -0.000001) ? 0.000001 : lScaleY;
-
-
- // Add offset point
- t.tx += Cos * this._offsetPoint.x * lScaleX + -Sin * this._offsetPoint.y * lScaleY;
- t.ty += Sin * this._offsetPoint.x * lScaleX + Cos * this._offsetPoint.y * lScaleY;
-
-
- // skew
- if (this._skewX || this._skewY) {
- // offset the anchorpoint
- var skx = Math.tan(-this._skewX * Math.PI / 180);
- var sky = Math.tan(-this._skewY * Math.PI / 180);
- var xx = appY * skx * sx;
- var yy = appX * sky * sy;
- t.a = Cos + -Sin * sky;
- t.c = Cos * skx + -Sin;
- t.b = Sin + Cos * sky;
- t.d = Sin * skx + Cos;
- t.tx += Cos * xx + -Sin * yy;
- t.ty += Sin * xx + Cos * yy;
- }
-
- // scale
- if (lScaleX !== 1 || lScaleY !== 1) {
- t.a *= sx;
- t.b *= sx;
- t.c *= sy;
- t.d *= sy;
- }
-
- // adjust anchorPoint
- t.tx += Cos * -appX * sx + -Sin * appY * sy;
- t.ty -= Sin * -appX * sx + Cos * appY * sy;
-
- // if ignore anchorPoint
- if (this._ignoreAnchorPointForPosition) {
- t.tx += appX
- t.ty += appY;
- }
-
- if (this._additionalTransformDirty) {
- this._transform = cc.AffineTransformConcat(this._transform, this._additionalTransform);
- this._additionalTransformDirty = false;
- }
-
- t.tx = t.tx | 0;
- t.ty = t.ty | 0;
- this._transformDirty = false;
- }
- return this._transform;
- },
-
- draw:function () {
- //cc.g_NumberOfDraws++;
- },
-
- /**
- * update blendType
- * @param {cc.BlendType} blendType
- */
- updateBlendType: function (blendType) {
- var blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
- switch (blendType) {
- case cc.BlendType.NORMAL:
- blendFunc.src = cc.BLEND_SRC;
- blendFunc.dst = cc.BLEND_DST;
- break;
- case cc.BlendType.ADD:
- blendFunc.src = gl.SRC_ALPHA;
- blendFunc.dst = gl.ONE;
- break;
- case cc.BlendType.MULTIPLY:
- blendFunc.src = gl.ONE_MINUS_SRC_ALPHA;
- blendFunc.dst = gl.ONE_MINUS_DST_COLOR;
- break;
- case cc.BlendType.SCREEN:
- blendFunc.src = gl.ONE;
- blendFunc.dst = gl.ONE_MINUS_DST_COLOR;
- break;
- default:
- break;
- }
- this.setBlendFunc(blendFunc.src, blendFunc.dst);
- },
-
- /**
- * This boundingBox will calculate all bones' boundingBox every time
- * @return {cc.rect}
- */
- boundingBox:function () {
- var minx, miny, maxx, maxy = 0;
- var first = true;
- var boundingBox = cc.rect(0, 0, 0, 0);
- for (var i = 0; i < this._children.length; i++) {
- var bone = this._children[i];
- if (bone instanceof cc.Bone) {
- var r = bone.getDisplayManager().getBoundingBox();
- if (first) {
- minx = cc.rectGetMinX(r);
- miny = cc.rectGetMinY(r);
- maxx = cc.rectGetMaxX(r);
- maxy = cc.rectGetMaxY(r);
-
- first = false;
- }
- else {
- minx = cc.rectGetMinX(r) < cc.rectGetMinX(boundingBox) ? cc.rectGetMinX(r) : cc.rectGetMinX(boundingBox);
- miny = cc.rectGetMinY(r) < cc.rectGetMinY(boundingBox) ? cc.rectGetMinY(r) : cc.rectGetMinY(boundingBox);
- maxx = cc.rectGetMaxX(r) > cc.rectGetMaxX(boundingBox) ? cc.rectGetMaxX(r) : cc.rectGetMaxX(boundingBox);
- maxy = cc.rectGetMaxY(r) > cc.rectGetMaxY(boundingBox) ? cc.rectGetMaxY(r) : cc.rectGetMaxY(boundingBox);
- }
- boundingBox = cc.rect(minx, miny, maxx - minx, maxy - miny);
- }
- }
- return boundingBox;
- },
-
- /**
- * armatureAnimation getter
- * @return {cc.ArmatureAnimation}
- */
- getAnimation:function () {
- return this._animation;
- },
-
- /**
- * armatureAnimation setter
- * @param {cc.ArmatureAnimation} animation
- */
- setAnimation:function (animation) {
- this._animation = animation;
- },
-
- /**
- * armatureData getter
- * @return {cc.ArmatureData}
- */
- getArmatureData:function () {
- return this._armatureData;
- },
-
- /**
- * armatureData setter
- * @param {cc.ArmatureData} armatureData
- */
- setArmatureData:function (armatureData) {
- this._armatureData = armatureData;
- },
- getName:function () {
- return this._name;
- },
- setName:function (name) {
- this._name = name;
- },
- getBatchNode:function () {
- return this._batchNode;
- },
- setBatchNode:function (batchNode) {
- this._batchNode = batchNode;
- },
-
- /**
- * version getter
- * @returns {Number}
- */
- getVersion:function () {
- return this._version;
- },
-
- /**
- * version setter
- * @param {Number} version
- */
- setVersion:function (version) {
- this._version = version;
- },
-
- /**
- * armatureTransformDirty getter
- * @returns {Boolean}
- */
- getArmatureTransformDirty:function () {
- return this._armatureTransformDirty;
- },
- getBody:function(){
- return this._body;
- },
-
- setBody:function(body){
- if (this._body == body)
- return;
-
- this._body = body;
- this._body.data = this;
- var child,displayObject;
- for (var i = 0; i < this._children.length; i++) {
- child = this._children[i];
- if (child instanceof cc.Bone) {
- var displayList = child.getDisplayManager().getDecorativeDisplayList();
- for (var j = 0; j < displayList.length; j++) {
- displayObject = displayList[j];
- var detector = displayObject.getColliderDetector();
- if (detector)
- detector.setBody(this._body);
- }
- }
- }
- },
- getShapeList:function(){
- if(this._body)
- return this._body.shapeList;
- return [];
- }
-
-});
-
-/**
- * allocates and initializes a armature.
- * @constructs
- * @return {cc.Armature}
- * @example
- * // example
- * var armature = cc.Armature.create();
- */
-cc.Armature.create = function (name, parentBone) {
- var armature = new cc.Armature();
- if (armature && armature.init(name, parentBone)) {
- return armature;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/CCBone.js b/extensions/CocoStudio/Armature/CCBone.js
deleted file mode 100644
index d63ef0998a..0000000000
--- a/extensions/CocoStudio/Armature/CCBone.js
+++ /dev/null
@@ -1,499 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.Bone objects.
- * @class
- * @extends cc.NodeRGBA
- */
-cc.Bone = cc.NodeRGBA.extend({
- _boneData:null,
- _armature:null,
- _childArmature:null,
- _displayManager:null,
- _ignoreMovementBoneData:false,
- _tween:null,
- _tweenData:null,
- _name:"",
- _childrenBone:null,
- _parentBone:null,
- _boneTransformDirty:false,
- _worldTransform:null,
- _blendType:0,
- ctor:function () {
- cc.NodeRGBA.prototype.ctor.call(this);
- this._boneData = null;
- this._armature = null;
- this._childArmature = null;
- this._displayManager = null;
- this._ignoreMovementBoneData = false;
- this._tween = null;
- this._tweenData = null;
- this._name = "";
- this._childrenBone = [];
- this._parentBone = null;
- this._boneTransformDirty = true;
- this._worldTransform = cc.AffineTransformMake(1, 0, 0, 1, 0, 0);
- this._blendType=cc.BlendType.NORMAL;
- },
-
- /**
- * release objects
- */
- release:function () {
- CC_SAFE_RELEASE(this._tweenData);
- for (var i = 0; i < this._childrenBone.length; i++) {
- CC_SAFE_RELEASE(this._childrenBone[i]);
- }
- this._childrenBone = [];
- CC_SAFE_RELEASE(this._tween);
- CC_SAFE_RELEASE(this._displayManager);
- CC_SAFE_RELEASE(this._boneData);
- CC_SAFE_RELEASE(this._childArmature);
- },
-
- /**
- * Initializes a CCBone with the specified name
- * @param {String} name
- * @return {Boolean}
- */
- init:function (name) {
- cc.NodeRGBA.prototype.init.call(this);
- if (name) {
- this._name = name;
- }
- this._tweenData = new cc.FrameData();
- this._tween = new cc.Tween();
- this._tween.init(this);
- this._displayManager = new cc.DisplayManager();
- this._displayManager.init(this);
- return true;
- },
-
- /**
- * set the boneData
- * @param {cc.BoneData} boneData
- */
- setBoneData:function (boneData) {
- if (!boneData) {
- cc.log("boneData must not be null");
- return;
- }
- this._boneData = boneData;
- this._name = this._boneData.name;
- this._zOrder = this._boneData.zOrder;
- this._displayManager.initDisplayList(boneData);
- },
-
- /**
- * boneData getter
- * @return {cc.BoneData}
- */
- getBoneData:function () {
- return this._boneData;
- },
-
- /**
- * set the armature
- * @param {cc.Armature} armature
- */
- setArmature:function (armature) {
- this._armature = armature;
- if(armature){
- this._tween.setAnimation(this._armature.getAnimation());
- }
- },
-
- /**
- * armature getter
- * @return {cc.Armature}
- */
- getArmature:function () {
- return this._armature;
- },
-
- /**
- * update worldTransform
- * @param dt
- */
- update:function (dt) {
- var locParentBone = this._parentBone;
- var locArmature = this._armature;
- var locTweenData = this._tweenData;
- var locWorldTransform = this._worldTransform;
-
- if (locParentBone) {
- this._boneTransformDirty = this._boneTransformDirty || locParentBone.isTransformDirty();
- }
- if (this._boneTransformDirty) {
- if (locArmature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) {
- cc.TransformHelp.nodeConcat(locTweenData, this._boneData);
- locTweenData.scaleX -= 1;
- locTweenData.scaleY -= 1;
- }
-
- cc.TransformHelp.nodeToMatrix(locTweenData, locWorldTransform);
-
- this._worldTransform = cc.AffineTransformConcat(this.nodeToParentTransform(), locWorldTransform);
-
- if (locParentBone) {
- this._worldTransform = cc.AffineTransformConcat(this._worldTransform, locParentBone._worldTransform);
- }
- }
- cc.DisplayFactory.updateDisplay(this, this._displayManager.getCurrentDecorativeDisplay(), dt, this._boneTransformDirty || locArmature.getArmatureTransformDirty());
-
- var locChildrenBone = this._childrenBone;
- for (var i = 0; i < locChildrenBone.length; i++) {
- locChildrenBone[i].update(dt);
- }
- this._boneTransformDirty = false;
- },
-
- /**
- * Rewrite visit ,when node draw, g_NumberOfDraws is changeless
- */
- visit:function (ctx) {
- var node = this.getDisplayManager().getDisplayRenderNode();
- if (node) {
- node.visit(ctx);
- }
- },
-
- /**
- * update display color
- * @param {cc.c3b} color
- */
- updateDisplayedColor:function (color) {
- this._realColor = cc.c3b(255,255,255);
- cc.NodeRGBA.prototype.updateDisplayedColor.call(this, color);
- this.updateColor();
- },
-
- /**
- * update display opacity
- * @param {Number} opacity
- */
- updateDisplayedOpacity:function (opacity) {
- this._realOpacity = 255;
- cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, opacity);
- this.updateColor();
- },
-
- /**
- * update display color
- */
- updateColor:function () {
- var display = this._displayManager.getDisplayRenderNode();
- if (display&&display instanceof cc.Skin) {
- //display.setColor(cc.c3b(this._displayedColor.r * this._tweenData.r / 255, this._displayedColor.g * this._tweenData.g / 255, this._displayedColor.b * this._tweenData.b / 255));
- if(cc.Browser.supportWebGL){
- display.setOpacity(this._displayedOpacity * this._tweenData.a / 255);
- }else{
- cc.NodeRGBA.prototype.setOpacity.call(display, this._displayedOpacity * this._tweenData.a / 255);
- }
-
- }
- },
-
- /**
- * update display zOrder
- */
- updateZOrder: function () {
- if (this._armature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) {
- var zorder = this._tweenData.zOrder + this._boneData.zOrder;
- this.setZOrder(zorder);
- }
- else {
- this.setZOrder(this._tweenData.zOrder);
- }
- },
-
- /**
- * Add a child to this bone, and it will let this child call setParent(cc.Bone) function to set self to it's parent
- * @param {cc.Bone} child
- */
- addChildBone:function (child) {
- if (!child) {
- cc.log("Argument must be non-nil");
- return;
- }
- if (child._parentBone) {
- cc.log("child already added. It can't be added again");
- return;
- }
- if (cc.ArrayGetIndexOfObject(this._childrenBone, child) < 0) {
- this._childrenBone.push(child);
- child.setParentBone(this);
- }
- },
-
- /**
- * Removes a child bone
- * @param {cc.Bone} bone
- * @param {Boolean} recursion
- */
- removeChildBone:function (bone, recursion) {
- for (var i = 0; i < this._childrenBone.length; i++) {
- if (this._childrenBone[i] == bone) {
- if (recursion) {
- var ccbones = bone._childrenBone;
- for (var j = 0; j < ccbones.length; j++) {
- bone.removeChildBone(ccbones[j], recursion);
- }
- }
- bone.setParentBone(null);
- bone.getDisplayManager().setCurrentDecorativeDisplay(null);
- cc.ArrayRemoveObject(this._childrenBone, bone);
- }
- }
- },
-
- /**
- * Remove itself from its parent CCBone.
- * @param {Boolean} recursion
- */
- removeFromParent:function (recursion) {
- if (this._parentBone) {
- this._parentBone.removeChildBone(this, recursion);
- }
- },
-
- /**
- * Set parent bone.
- * If _parent is NUll, then also remove this bone from armature.
- * It will not set the CCArmature, if you want to add the bone to a CCArmature, you should use cc.Armature.addBone(bone, parentName).
- * @param {cc.Bone} parent the parent bone.
- */
- setParentBone:function (parent) {
- this._parentBone = parent;
- },
-
- /**
- * parent bone getter
- * @return {cc.Bone}
- */
- getParentBone:function () {
- return this._parentBone;
- },
-
- /**
- * child armature setter
- * @param {cc.Armature} armature
- */
- setChildArmature:function (armature) {
- if (this._childArmature != armature) {
- this._childArmature = armature;
- }
- },
-
- /**
- * child armature getter
- * @return {cc.Armature}
- */
- getChildArmature:function () {
- return this._childArmature;
- },
-
- /**
- * child bone getter
- * @return {Array}
- */
- getChildrenBone:function () {
- return this._childrenBone;
- },
-
- /**
- * tween getter
- * @return {cc.Tween}
- */
- getTween:function () {
- return this._tween;
- },
-
- /**
- * zOrder setter
- * @param {Number}
- */
- setZOrder:function (zOrder) {
- if (this._zOrder != zOrder)
- cc.Node.prototype.setZOrder.call(this, zOrder);
- },
-
- /**
- * transform dirty setter
- * @param {Boolean}
- */
- setTransformDirty:function (dirty) {
- this._boneTransformDirty = dirty;
- },
-
- /**
- * transform dirty getter
- * @return {Boolean}
- */
- isTransformDirty:function () {
- return this._boneTransformDirty;
- },
-
- /**
- * return world transform
- * @return {{a:0.b:0,c:0,d:0,tx:0,ty:0}}
- */
- nodeToArmatureTransform:function () {
- return this._worldTransform;
- },
-
- /**
- * Returns the world affine transform matrix. The matrix is in Pixels.
- * @returns {cc.AffineTransform}
- */
- nodeToWorldTransform: function () {
- return cc.AffineTransformConcat(this._worldTransform, this._armature.nodeToWorldTransform());
- },
-
- /**
- * get render node
- * @returns {cc.Node}
- */
- getDisplayRenderNode: function () {
- return this._displayManager.getDisplayRenderNode();
- },
-
- /**
- * Add display and use _displayData init the display.
- * If index already have a display, then replace it.
- * If index is current display index, then also change display to _index
- * @param {cc.Display} displayData it include the display information, like DisplayType.
- * If you want to create a sprite display, then create a CCSpriteDisplayData param
- *@param {Number} index the index of the display you want to replace or add to
- * -1 : append display from back
- */
- addDisplay:function (displayData, index) {
- index = index || 0;
- return this._displayManager.addDisplay(displayData, index);
- },
-
- addSkin:function (skin, index) {
- index = index||0;
- return this._displayManager.addSkin(skin, index);
- },
-
- /**
- * change display by index
- * @param {Number} index
- * @param {Boolean} force
- */
- changeDisplayByIndex:function (index, force) {
- this._displayManager.changeDisplayByIndex(index, force);
- },
-
- /**
- * displayManager setter
- * @param {cc.DisplayManager}
- */
- setDisplayManager:function (displayManager) {
- this._displayManager = displayManager;
- },
-
- /**
- * displayManager dirty getter
- * @return {cc.DisplayManager}
- */
- getDisplayManager:function () {
- return this._displayManager;
- },
-
- /**
- * When CCArmature play a animation, if there is not a CCMovementBoneData of this bone in this CCMovementData, this bone will hide.
- * Set IgnoreMovementBoneData to true, then this bone will also show.
- * @param {Boolean} bool
- */
- setIgnoreMovementBoneData:function (bool) {
- this._ignoreMovementBoneData = bool;
- },
-
- /**
- * ignoreMovementBoneData getter
- * @return {Boolean}
- */
- getIgnoreMovementBoneData:function () {
- return this._ignoreMovementBoneData;
- },
-
- /**
- * tweenData getter
- * @return {cc.FrameData}
- */
- getTweenData:function () {
- return this._tweenData;
- },
-
- /**
- * name setter
- * @param {String} name
- */
- setName:function (name) {
- this._name = name;
- },
-
- /**
- * name getter
- * @return {String}
- */
- getName:function () {
- return this._name;
- },
-
- /**
- * blendType setter
- * @param {cc.BlendType} blendType
- */
- setBlendType:function (blendType) {
- this._blendType = blendType;
- },
-
- /**
- * blendType getter
- * @return {cc.BlendType}
- */
- getBlendType:function () {
- return this._blendType;
- }
-});
-
-/**
- * allocates and initializes a bone.
- * @constructs
- * @return {cc.Bone}
- * @example
- * // example
- * var bone = cc.Bone.create();
- */
-cc.Bone.create = function (name) {
- var bone = new cc.Bone();
- if (bone && bone.init(name)) {
- return bone;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js b/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js
deleted file mode 100644
index 8bcfd5100f..0000000000
--- a/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js
+++ /dev/null
@@ -1,429 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-//movement event type
-CC_MovementEventType_START = 0;
-CC_MovementEventType_COMPLETE = 1;
-CC_MovementEventType_LOOP_COMPLETE = 2;
-
-/**
- * Base class for cc.MovementEvent objects.
- * @class
- * @extends cc.Class
- */
-cc.AnimationEvent = cc.Class.extend({
- _arguments:null,
- _callFunc:null,
- _selectorTarget:null,
- ctor:function (target, callFunc, data) {
- this._data = data;
- this._callFunc = callFunc;
- this._selectorTarget = target;
- },
- call:function () {
- if (this._callFunc) {
- this._callFunc.apply(this._selectorTarget, this._arguments);
- }
- },
- setArguments:function (args) {
- this._arguments = args;
- }
-});
-
-/**
- * Base class for cc.ArmatureAnimation objects.
- * @class
- * @extends cc.ProcessBase
- */
-cc.ArmatureAnimation = cc.ProcessBase.extend({
- _animationData:null,
- _movementData:null,
- _armature:null,
- _movementID:"",
- _prevFrameIndex:0,
- _toIndex:0,
- _tweenList:null,
- _frameEvent:null,
- _movementEvent:null,
- _speedScale:1,
- ctor:function () {
- cc.ProcessBase.prototype.ctor.call(this);
- this._animationData = null;
- this._movementData = null;
- this._movementID = "";
- this._armature = null;
- this._prevFrameIndex = 0;
- this._toIndex = 0;
- this._tweenList = [];
- this._frameEvent = null;
- this._movementEvent = null;
- this._speedScale = 1;
- },
-
- /**
- * init with a CCArmature
- * @param {cc.Armature} armature
- * @return {Boolean}
- */
- init:function (armature) {
- this._armature = armature;
- this._tweenList = [];
- return true;
- },
- pause:function () {
- for (var i = 0; i < this._tweenList.length; i++) {
- this._tweenList[i].pause();
- }
- cc.ProcessBase.prototype.pause.call(this);
- },
- resume:function () {
- for (var i = 0; i < this._tweenList.length; i++) {
- this._tweenList[i].resume();
- }
- cc.ProcessBase.prototype.resume.call(this);
- },
-
- stop:function () {
- for (var i = 0; i < this._tweenList.length; i++) {
- this._tweenList[i].stop();
- }
- this._tweenList = [];
- cc.ProcessBase.prototype.stop.call(this);
- },
-
- /**
- * scale animation play speed
- * @param {Number} speedScale
- */
- setSpeedScale:function (speedScale) {
- if (speedScale == this._speedScale) {
- return;
- }
- this._speedScale = speedScale;
- this._processScale = !this._movementData ? this._speedScale : this._speedScale * this._movementData.scale;
- var dict = this._armature.getBoneDic();
- for (var key in dict) {
- var bone = dict[key];
- bone.getTween().setProcessScale(this._processScale);
- if (bone.getChildArmature()) {
- bone.getChildArmature().getAnimation().setProcessScale(this._processScale);
- }
- }
- },
-
- getSpeedScale:function(){
- return this._speedScale;
- },
-
- getAnimationScale:function(){
- return this.getSpeedScale();
- },
- setAnimationScale:function(animationScale){
- return this.setSpeedScale(animationScale);
- },
-
- setAnimationInternal:function (animationInternal) {
- if (animationInternal == this._animationInternal) {
- return;
- }
- this._animationInternal = animationInternal;
-
- var dict = this._armature.getBoneDic();
- for (var key in dict) {
- var bone = dict[key];
- bone.getTween().setAnimationInternal(this._animationInternal);
- if (bone.getChildArmature()) {
- bone.getChildArmature().getAnimation().setAnimationInternal(this._animationInternal);
- }
- }
- },
-
- /**
- * play animation by animation name.
- * @param {Number} animationName The animation name you want to play
- * @param {Number} durationTo
- * he frames between two animation changing-over.It's meaning is changing to this animation need how many frames
- * -1 : use the value from CCMovementData get from flash design panel
- * @param {Number} durationTween he
- * frame count you want to play in the game.if _durationTween is 80, then the animation will played 80 frames in a loop
- * -1 : use the value from CCMovementData get from flash design panel
- * @param {Number} loop
- * Whether the animation is loop.
- * loop < 0 : use the value from CCMovementData get from flash design panel
- * loop = 0 : this animation is not loop
- * loop > 0 : this animation is loop
- * @param {Number} tweenEasing
- * CCTween easing is used for calculate easing effect
- * TWEEN_EASING_MAX : use the value from CCMovementData get from flash design panel
- * -1 : fade out
- * 0 : line
- * 1 : fade in
- * 2 : fade in and out
- */
- play:function (animationName, durationTo, durationTween, loop, tweenEasing) {
- if (this._animationData == null) {
- cc.log("this._animationData can not be null");
- return;
- }
- this._movementData = this._animationData.getMovement(animationName);
- if (this._movementData == null) {
- cc.log("this._movementData can not be null");
- return;
- }
- if (typeof durationTo == "undefined") {
- durationTo = -1;
- }
- if (typeof durationTween == "undefined") {
- durationTween = -1;
- }
- if (typeof loop == "undefined") {
- loop = -1;
- }
- if (typeof tweenEasing == "undefined") {
- tweenEasing = cc.TweenType.TWEEN_EASING_MAX;
- }
- var locMovementData = this._movementData;
- //Get key frame count
- this._rawDuration = locMovementData.duration;
- this._movementID = animationName;
- this._processScale = this._speedScale * locMovementData.scale;
- //Further processing parameters
- durationTo = (durationTo == -1) ? locMovementData.durationTo : durationTo;
- durationTween = (durationTween == -1) ? locMovementData.durationTween : durationTween;
- durationTween = (durationTween == 0) ? locMovementData.duration : durationTween;//todo
- tweenEasing = (tweenEasing == cc.TweenType.TWEEN_EASING_MAX) ? locMovementData.tweenEasing : tweenEasing;
- loop = (loop < 0) ? locMovementData.loop : loop;
-
- cc.ProcessBase.prototype.play.call(this, animationName, durationTo, durationTween, loop, tweenEasing);
-
- if (this._rawDuration == 0) {
- this._loopType = CC_ANIMATION_TYPE_SINGLE_FRAME;
- }
- else {
- if (loop) {
- this._loopType = CC_ANIMATION_TYPE_TO_LOOP_FRONT;
- }
- else {
- this._loopType = CC_ANIMATION_TYPE_NO_LOOP;
- this._rawDuration--;
- }
- this._durationTween = durationTween;
- }
-
- this._tweenList = [];
-
- var movementBoneData;
- var dict = this._armature.getBoneDic();
- for (var key in dict) {
- var bone = dict[key];
- movementBoneData = locMovementData.getMovementBoneData(bone.getName());
- var tween = bone.getTween();
- if (movementBoneData && movementBoneData.frameList.length > 0) {
- this._tweenList.push(tween);
- movementBoneData.duration = locMovementData.duration;
- tween.play(movementBoneData, durationTo, durationTween, loop, tweenEasing);
-
- tween.setProcessScale(this._processScale);
- tween.setAnimationInternal(this._animationInternal);
- if (bone.getChildArmature()) {
- bone.getChildArmature().getAnimation().setProcessScale(this._processScale);
- bone.getChildArmature().getAnimation().setAnimationInternal(this._animationInternal);
- }
- } else {
- if (!bone.getIgnoreMovementBoneData()) {
- bone.getDisplayManager().changeDisplayByIndex(-1, false);
- tween.stop();
- }
- }
- }
- },
-
- /**
- * Play animation by index, the other param is the same to play.
- * @param {Number} animationIndex
- * @param {Number} durationTo
- * @param {Number} durationTween
- * @param {Number} loop
- * @param {Number} tweenEasing
- */
- playByIndex:function (animationIndex, durationTo, durationTween, loop, tweenEasing) {
- if (typeof durationTo == "undefined") {
- durationTo = -1;
- }
- if (typeof durationTween == "undefined") {
- durationTween = -1;
- }
- if (typeof loop == "undefined") {
- loop = -1;
- }
- if (typeof tweenEasing == "undefined") {
- tweenEasing = 10000;
- }
- var moveNames = this._animationData.movementNames;
- if (animationIndex < -1 || animationIndex >= moveNames.length) {
- return;
- }
- var animationName = moveNames[animationIndex];
- this.play(animationName, durationTo, durationTween, loop, tweenEasing);
- },
-
- /**
- * get movement count
- * @return {Number}
- */
- getMovementCount:function () {
- return this._animationData.getMovementCount();
- },
-
- update:function (dt) {
- if(cc.ProcessBase.prototype.update.call(this, dt)){
- for (var i = 0; i < this._tweenList.length; i++) {
- this._tweenList[i].update(dt);
- }
- }
- },
-
- /**
- * update will call this handler, you can handle your logic here
- */
- updateHandler:function () {
- var locCurrentPercent = this._currentPercent;
- if (locCurrentPercent >= 1) {
- switch (this._loopType) {
- case CC_ANIMATION_TYPE_NO_LOOP:
- this._loopType = CC_ANIMATION_TYPE_MAX;
- this._currentFrame = (locCurrentPercent - 1) * this._nextFrameIndex;
- locCurrentPercent = this._currentFrame / this._durationTween;
- if (locCurrentPercent < 1.0) {
- this._nextFrameIndex = this._durationTween;
- this.callMovementEvent([this._armature, CC_MovementEventType_START, this._movementID]);
- break;
- }
- case CC_ANIMATION_TYPE_MAX:
- case CC_ANIMATION_TYPE_SINGLE_FRAME:
- locCurrentPercent = 1;
- this._isComplete = true;
- this._isPlaying = false;
- this.callMovementEvent([this._armature, CC_MovementEventType_COMPLETE, this._movementID]);
- break;
- case CC_ANIMATION_TYPE_TO_LOOP_FRONT:
- this._loopType = CC_ANIMATION_TYPE_LOOP_FRONT;
- locCurrentPercent = cc.fmodf(locCurrentPercent, 1);
- this._currentFrame = this._nextFrameIndex == 0 ? 0 : cc.fmodf(this._currentFrame, this._nextFrameIndex);
- this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1;
- this.callMovementEvent([this, CC_MovementEventType_START, this._movementID]);
- break;
- default:
- locCurrentPercent = cc.fmodf(locCurrentPercent, 1);
- this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex);
- this._toIndex = 0;
- this.callMovementEvent([this._armature, CC_MovementEventType_LOOP_COMPLETE, this._movementID]);
- break;
- }
- this._currentPercent = locCurrentPercent;
- }
- },
-
- /**
- * Get current movementID
- * @returns {String}
- */
- getCurrentMovementID: function () {
- if (this._isComplete)
- return "";
- return this._movementID;
- },
-
- /**
- * connect a event
- * @param {Object} target
- * @param {function} callFunc
- */
- setMovementEventCallFunc:function (callFunc, target) {
- this._movementEvent = new cc.AnimationEvent(target, callFunc);
- },
-
- /**
- * call event
- * @param {Array} args
- */
- callMovementEvent:function (args) {
- if (this._movementEvent) {
- this._movementEvent.setArguments(args);
- this._movementEvent.call();
- }
- },
-
- /**
- * connect a event
- * @param {Object} target
- * @param {function} callFunc
- */
- setFrameEventCallFunc:function (callFunc, target) {
- this._frameEvent = new cc.AnimationEvent(target, callFunc);
- },
-
- /**
- * call event
- * @param {Array} args
- */
- callFrameEvent:function (args) {
- if (this._frameEvent) {
- this._frameEvent.setArguments(args);
- this._frameEvent.call();
- }
- },
-
- /**
- * animationData setter
- * @param {cc.AnimationData} aniData
- */
- setAnimationData:function (aniData) {
- this._animationData = aniData;
- },
-
- /**
- * animationData getter
- * @return {cc.AnimationData}
- */
- getAnimationData:function () {
- return this._animationData;
- }
-});
-
-/**
- * allocates and initializes a ArmatureAnimation.
- * @constructs
- * @return {cc.ArmatureAnimation}
- * @example
- * // example
- * var animation = cc.ArmatureAnimation.create();
- */
-cc.ArmatureAnimation.create = function (armature) {
- var animation = new cc.ArmatureAnimation();
- if (animation && animation.init(armature)) {
- return animation;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/animation/CCProcessBase.js b/extensions/CocoStudio/Armature/animation/CCProcessBase.js
deleted file mode 100644
index a67ade99f6..0000000000
--- a/extensions/CocoStudio/Armature/animation/CCProcessBase.js
+++ /dev/null
@@ -1,211 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-//animation type
-CC_ANIMATION_TYPE_SINGLE_FRAME = -4;//the animation just have one frame
-CC_ANIMATION_TYPE_NO_LOOP = -3;//the animation isn't loop
-CC_ANIMATION_TYPE_TO_LOOP_FRONT = -2;//the animation to loop from front
-CC_ANIMATION_TYPE_TO_LOOP_BACK = -1;//the animation to loop from back
-CC_ANIMATION_TYPE_LOOP_FRONT = 0;//the animation loop from front
-CC_ANIMATION_TYPE_LOOP_BACK = 1;//the animation loop from back
-CC_ANIMATION_TYPE_MAX = 2;//the animation max
-
-/**
- * Base class for cc.ProcessBase objects.
- * @class
- * @extends cc.Class
- */
-cc.ProcessBase = cc.Class.extend({
- _processScale:1,
- _isComplete:true,
- _isPause:true,
- _isPlaying:false,
- _currentPercent:0.0,
- _rawDuration:0,
- _loopType:0,
- _tweenEasing:0,
- _animationInternal:null,
- _currentFrame:0,
- _durationTween:0,
- _nextFrameIndex:0,
- _curFrameIndex:null,
- _isLoopBack:false,
- ctor:function () {
- this._processScale = 1;
- this._isComplete = true;
- this._isPause = true;
- this._isPlaying = false;
- this._currentFrame = 0;
- this._currentPercent = 0.0;
- this._durationTween = 0;
- this._rawDuration = 0;
- this._loopType = CC_ANIMATION_TYPE_LOOP_BACK;
- this._tweenEasing = cc.TweenType.Linear;
- this._animationInternal = cc.Director.getInstance().getAnimationInterval();
- this._curFrameIndex = 0;
- this._durationTween = 0;
- this._isLoopBack = false;
- },
-
-
- pause:function () {
- this._isPause = true;
- this._isPlaying = false;
- },
-
-
- resume:function () {
- this._isPause = false;
- this._isPlaying = true;
- },
-
- stop:function () {
- this._isComplete = true;
- this._isPlaying = false;
- this._currentFrame = 0;
- this._currentPercent = 0;
- },
-
- /**
- * play animation by animation name.
- * @param {Number} animationName The animation name you want to play
- * @param {Number} durationTo
- * he frames between two animation changing-over.It's meaning is changing to this animation need how many frames
- * -1 : use the value from CCMovementData get from flash design panel
- * @param {Number} durationTween he
- * frame count you want to play in the game.if _durationTween is 80, then the animation will played 80 frames in a loop
- * -1 : use the value from CCMovementData get from flash design panel
- * @param {Number} loop
- * Whether the animation is loop.
- * loop < 0 : use the value from CCMovementData get from flash design panel
- * loop = 0 : this animation is not loop
- * loop > 0 : this animation is loop
- * @param {Number} tweenEasing
- * CCTween easing is used for calculate easing effect
- * TWEEN_EASING_MAX : use the value from CCMovementData get from flash design panel
- * -1 : fade out
- * 0 : line
- * 1 : fade in
- * 2 : fade in and out
- */
- play:function (animation, durationTo, durationTween, loop, tweenEasing) {
- this._isComplete = false;
- this._isPause = false;
- this._isPlaying = true;
- this._currentFrame = 0;
-
- /*
- * Set this._nextFrameIndex to durationTo, it is used for change tween between two animation.
- * When changing end, this._nextFrameIndex will be setted to _durationTween
- */
- this._nextFrameIndex = durationTo;
- this._tweenEasing = tweenEasing;
- },
-
- update:function (dt) {
- if (this._isComplete || this._isPause) {
- return false;
- }
- if (this._rawDuration <= 0 || dt > 1) {
- return false;
- }
- var locNextFrameIndex = this._nextFrameIndex;
- if (locNextFrameIndex <= 0) {
- this._currentPercent = 1;
- this._currentFrame = 0;
- }else{
- /*
- * update this._currentFrame, every update add the frame passed.
- * dt/this._animationInternal determine it is not a frame animation. If frame speed changed, it will not make our
- * animation speed slower or quicker.
- */
- this._currentFrame += this._processScale * (dt / this._animationInternal);
-
- this._currentPercent = this._currentFrame / locNextFrameIndex;
-
- /*
- * if this._currentFrame is bigger or equal than this._nextFrameIndex, then reduce it util this._currentFrame is
- * smaller than this._nextFrameIndex
- */
- this._currentFrame = cc.fmodf(this._currentFrame, locNextFrameIndex);
- }
- this.updateHandler();
- return true;
- },
-
- /**
- * update will call this handler, you can handle your logic here
- */
- updateHandler:function () {
- //override
- },
- gotoFrame:function (keyFrameIndex) {
- this._curFrameIndex = keyFrameIndex;
- this.pause();
- },
-
- /**
- * get currentFrameIndex
- * @return {Number}
- */
- getCurrentFrameIndex:function () {
- this._curFrameIndex = this._rawDuration * this._currentPercent;
- return this._curFrameIndex;
- },
-
- isPause:function () {
- return this._isPause;
- },
- isComplete:function () {
- return this._isComplete;
- },
- getCurrentPercent:function () {
- return this._currentPercent;
- },
- getRawDuration:function () {
- return this._rawDuration;
- },
- getLoop:function () {
- return this._loopType;
- },
- getTweenEasing:function () {
- return this._tweenEasing;
- },
- getAnimationInternal:function () {
- return this._animationInternal;
- },
- setAnimationInternal:function(animationInternal){
- this._animationInternal = animationInternal;
- },
- getProcessScale:function () {
- return this._processScale;
- },
- setProcessScale:function (processScale) {
- this._processScale = processScale;
- },
- isPlaying:function () {
- return this._isPlaying;
- }
-});
diff --git a/extensions/CocoStudio/Armature/datas/CCDatas.js b/extensions/CocoStudio/Armature/datas/CCDatas.js
deleted file mode 100644
index 3e5bd83cef..0000000000
--- a/extensions/CocoStudio/Armature/datas/CCDatas.js
+++ /dev/null
@@ -1,452 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.BlendType = {
- NORMAL: 0,
- LAYER: 1,
- DARKEN: 2,
- MULTIPLY: 3,
- LIGHTEN: 4,
- SCREEN: 5,
- OVERLAY: 6,
- HARD_LIGHT: 7,
- ADD: 8,
- SUBSTRACT: 9,
- DIFFERENCE: 10,
- INVERT: 11,
- ALPHA: 12,
- ERASE: 13
-};
-
-CC_DISPLAY_SPRITE = 0;
-CC_DISPLAY_ARMATURE = 1;
-CC_DISPLAY_PARTICLE = 2;
-CC_DISPLAY_MAX = 3;
-
-cc.BaseData = cc.Class.extend({
- x:0,
- y:0,
- zOrder:0,
- skewX:0,
- skewY:0,
- scaleX:1,
- scaleY:1,
- tweenRotate:0,
- isUseColorInfo:false,
- r:255,
- g:255,
- b:255,
- a:255,
-
- ctor:function () {
- this.x = 0;
- this.y = 0;
- this.zOrder = 0;
- this.skewX = 0;
- this.skewY = 0;
- this.scaleX = 1;
- this.scaleY = 1;
- this.tweenRotate = 0;
- this.isUseColorInfo = false;
- this.color = cc.c4f(1, 1, 1, 1);
- },
-
-
- copy:function (node) {
- this.x = node.x;
- this.y = node.y;
- this.zOrder = node.zOrder;
- this.scaleX = node.scaleX;
- this.scaleY = node.scaleY;
- this.skewX = node.skewX;
- this.skewY = node.skewY;
- this.tweenRotate = node.tweenRotate;
- this.isUseColorInfo = node.isUseColorInfo;
- this.r = node.r;
- this.g = node.g;
- this.b = node.b;
- this.a = node.a;
- },
-
- setColor:function(color){
- this.r = color.r;
- this.g = color.g;
- this.b = color.b;
- this.a = color.a;
- },
-
- getColor:function(){
- return cc.c4f(this.r, this.g, this.b, this.a);
- },
-
- subtract:function (from, to) {
- this.x = to.x - from.x;
- this.y = to.y - from.y;
- this.scaleX = to.scaleX - from.scaleX;
- this.scaleY = to.scaleY - from.scaleY;
- this.skewX = to.skewX - from.skewX;
- this.skewY = to.skewY - from.skewY;
-
- if (this.isUseColorInfo || from.isUseColorInfo || to.isUseColorInfo) {
- this.a = to.a - from.a;
- this.r = to.r - from.r;
- this.g = to.g - from.g;
- this.b = to.b - from.b;
- this.isUseColorInfo = true;
- } else {
- this.a = this.r = this.g = this.b = 0;
- this.isUseColorInfo = false;
- }
-
- if (this.skewX > cc.PI) {
- this.skewX -= 2 * cc.PI;
- }
- if (this.skewX < -cc.PI) {
- this.skewX += 2 * cc.PI;
- }
- if (this.skewY > cc.PI) {
- this.skewY -= 2 * cc.PI;
- }
- if (this.skewY < -cc.PI) {
- this.skewY += 2 * cc.PI;
- }
-
- if (to.tweenRotate) {
- this.skewX += to.tweenRotate;
- this.skewY += to.tweenRotate;
- }
- }
-});
-
-cc.DisplayData = cc.Class.extend({
- displayType:CC_DISPLAY_SPRITE,
- ctor:function () {
- this.displayType = CC_DISPLAY_MAX;
- },
- changeDisplayToTexture:function (displayName) {
- // remove .xxx
- var textureName = displayName;
- var startPos = textureName.lastIndexOf(".");
-
- if (startPos != -1) {
- textureName = textureName.substring(0, startPos);
- }
- return textureName;
- }
-});
-
-cc.SpriteDisplayData = cc.DisplayData.extend({
- displayName:"",
- skinData:null,
- ctor:function () {
- this.displayName = "";
- this.skinData = new cc.BaseData();
- this.displayType = CC_DISPLAY_SPRITE;
- },
- setParam:function (displayName) {
- this.displayName = displayName;
- },
- copy:function (displayData) {
- this.displayName = displayData.displayName;
- this.displayType = displayData.displayType;
- this.skinData = displayData.skinData;
- }
-});
-
-cc.NodeDisplayData = cc.DisplayData.extend({
- node:null,
- ctor:function () {
- this.displayName = "";
- this.displayType = CC_DISPLAY_NODE;
- this.node = null;
- },
- copy:function (displayData) {
- this.displayName = displayData.displayName;
- this.displayType = displayData.displayType;
- this.node = displayData.node;
- }
-});
-
-cc.ArmatureDisplayData = cc.DisplayData.extend({
- displayName:"",
- ctor:function () {
- this.displayName = "";
- this.displayType = CC_DISPLAY_ARMATURE;
-
- },
- setParam:function (displayName) {
- this.displayName = displayName;
- },
- copy:function (displayData) {
- this.displayName = displayData.displayName;
- this.displayType = displayData.displayType;
- }
-});
-
-cc.ParticleDisplayData = cc.DisplayData.extend({
- plist:"",
- ctor:function () {
- this.plist = "";
- this.displayType = CC_DISPLAY_PARTICLE;
-
- },
- setParam:function (plist) {
- this.plist = plist;
- },
- copy:function (displayData) {
- this.plist = displayData.plist;
- this.displayType = displayData.displayType;
- }
-});
-
-cc.ShaderDisplayData = cc.DisplayData.extend({
- vert:"",
- frag:"",
- ctor:function () {
- this.vert = "";
- this.frag = "";
- this.displayType = CC_DISPLAY_SHADER;
-
- },
- setParam:function (vert, frag) {
- this.vert = vert;
- this.frag = frag;
- },
- copy:function (displayData) {
- this.vert = displayData.vert;
- this.frag = displayData.frag;
- this.displayType = displayData.displayType;
- }
-});
-
-cc.BoneData = cc.BaseData.extend({
- displayDataList:null,
- name:"",
- parentName:"",
- boneDataTransform:null,
- ctor:function () {
- this.displayDataList = [];
- this.name = "";
- this.parentName = "";
- this.boneDataTransform = null;
-
- },
- init:function () {
-
- },
- addDisplayData:function (displayData) {
- this.displayDataList.push(displayData);
- },
-
- getDisplayData:function (index) {
- return this.displayDataList[index];
- }
-});
-
-cc.ArmatureData = cc.Class.extend({
- boneDataDic:null,
- name:"",
- dataVersion:0,
- ctor:function () {
- this.boneDataDic = {};
- this.name = "";
- this.dataVersion = 0;
- },
- init:function () {
- return true;
- },
- addBoneData:function (boneData) {
- this.boneDataDic[boneData.name] = boneData;
- },
- getBoneDataDic:function () {
- return this.boneDataDic;
- },
- getBoneData:function (boneName) {
- return this.boneDataDic[boneName];
- }
-});
-
-cc.FrameData = cc.BaseData.extend({
- duration:0,
- tweenEasing:0,
- displayIndex:-1,
- movement:"",
- event:"",
- sound:"",
- soundEffect:"",
- blendType:0,
- frameID:0,
-
- ctor:function () {
- cc.BaseData.prototype.ctor.call(this);
- this.duration = 1;
- this.tweenEasing = cc.TweenType.Linear;
- this.displayIndex = 0;
- this.movement = "";
- this.event = "";
- this.sound = "";
- this.soundEffect = "";
- this.blendType = cc.BlendType.NORMAL;
- this.frameID = 0;
- },
-
- copy:function (frameData) {
- cc.BaseData.prototype.copy.call(this, frameData);
- this.duration = frameData.duration;
- this.tweenEasing = frameData.tweenEasing;
- this.displayIndex = frameData.displayIndex;
- this.movement = frameData.movement;
- this.event = frameData.event;
- this.sound = frameData.sound;
- this.soundEffect = frameData.soundEffect;
- this.blendType = frameData.blendType;
- }
- }
-);
-
-cc.MovementBoneData = cc.Class.extend({
- delay:0,
- scale:1,
- duration:0,
- frameList:null,
- name:"",
- ctor:function () {
- this.delay = 0;
- this.scale = 1;
- this.duration = 0;
- this.frameList = [];
- this.name = "";
- },
- init:function () {
- this.frameList = [];
- },
- addFrameData:function (frameData) {
- this.frameList.push(frameData);
- },
- getFrameData:function (index) {
- return this.frameList[index];
- }
-});
-
-cc.MovementData = cc.Class.extend({
- movBoneDataDic:null,
- duration:0,
- scale:0,
- durationTo:0,
- durationTween:cc.TweenType.Linear,
- loop:true,
- tweenEasing:2,
- name:"",
- ctor:function () {
- this.name = "";
- this.duration = 0;
- this.scale = 1;
- this.durationTo = 0;
- this.durationTween = 0;
- this.loop = true;
- this.tweenEasing = cc.TweenType.Linear;
- this.movBoneDataDic = {};
- },
-
- addMovementBoneData:function (movBoneData) {
- this.movBoneDataDic[ movBoneData.name] = movBoneData;
- },
- getMovementBoneData:function (boneName) {
- return this.movBoneDataDic[boneName];
- }
-});
-
-cc.AnimationData = cc.Class.extend({
- moveDataDic:null,
- movementNames:null,
- name:"",
- ctor:function () {
- this.moveDataDic = {};
- this.movementNames = [];
- },
- addMovement:function (moveData) {
- this.moveDataDic[moveData.name] = moveData;
- this.movementNames.push(moveData.name);
- },
- getMovement:function (moveName) {
- return this.moveDataDic[moveName];
- },
- getMovementCount:function () {
- return Object.keys(this.moveDataDic).length;
- }
-});
-
-cc.ContourVertex2 = function (x, y) {
- this.x = x || 0;
- this.y = y || 0;
-};
-
-cc.ContourData = cc.Class.extend({
- vertexList:null,
- ctor:function () {
- this.vertexList = [];
- },
-
- init:function () {
- this.vertexList = [];
- return true;
- },
-
- /**
- *
- * @param {cc.p} p
- */
- addVertex: function (p) {
- var v = cc.ContourVertex2(p.x, p.y);
- this.vertexList.push(v);
- }
-});
-
-cc.TextureData = cc.Class.extend({
- height:0,
- width:0,
- pivotX:0,
- pivotY:0,
- name:"",
- contourDataList:null,
- ctor:function () {
- this.height = 0;
- this.width = 0;
- this.pivotX = 0.5;
- this.pivotY = 0.5;
- this.name = "";
- this.contourDataList = [];
- },
-
- init:function () {
- this.contourDataList = [];
- },
-
- addContourData:function (contourData) {
- this.contourDataList.push(contourData);
- },
- getContourData:function (index) {
- return this.contourDataList[index];
- }
-});
diff --git a/extensions/CocoStudio/Armature/display/CCDisplayFactory.js b/extensions/CocoStudio/Armature/display/CCDisplayFactory.js
deleted file mode 100644
index 9def225c85..0000000000
--- a/extensions/CocoStudio/Armature/display/CCDisplayFactory.js
+++ /dev/null
@@ -1,200 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.DisplayFactory = cc.DisplayFactory || {};
-cc.DisplayFactory.addDisplay = function (bone, decoDisplay, displayData) {
- switch (displayData.displayType) {
- case CC_DISPLAY_SPRITE:
- this.addSpriteDisplay(bone, decoDisplay, displayData);
- break;
- case CC_DISPLAY_PARTICLE:
- this.addParticleDisplay(bone, decoDisplay, displayData);
- break;
- case CC_DISPLAY_ARMATURE:
- this.addArmatureDisplay(bone, decoDisplay, displayData);
- break;
- default:
- break;
- }
-};
-cc.DisplayFactory.createDisplay = function (bone, decoDisplay) {
- switch (decoDisplay.getDisplayData().displayType) {
- case CC_DISPLAY_SPRITE:
- this.createSpriteDisplay(bone, decoDisplay);
- break;
- case CC_DISPLAY_PARTICLE:
- this.createParticleDisplay(bone, decoDisplay);
- break;
- case CC_DISPLAY_ARMATURE:
- this.createArmatureDisplay(bone, decoDisplay);
- break;
- default:
- break;
- }
-};
-
-cc.DisplayFactory.updateDisplay = function (bone, decoDisplay, dt, dirty) {
- if (!decoDisplay) {
- return;
- }
-
- if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) {
- if (dirty) {
- var detector = decoDisplay.getColliderDetector();
- if (detector&&detector.getBody()) {
- var node = decoDisplay.getDisplay();
- var displayTransform = node.nodeToParentTransform();
- var anchorPoint = node.getAnchorPointInPoints();
- anchorPoint = cc.PointApplyAffineTransform(anchorPoint, displayTransform);
- displayTransform.tx = anchorPoint.x;
- displayTransform.ty = anchorPoint.y;
- var t = cc.AffineTransformConcat(displayTransform, bone.getArmature().nodeToParentTransform());
- detector.updateTransform(t);
- }
- }
- }
- var display = decoDisplay.getDisplay();
- switch (decoDisplay.getDisplayData().displayType) {
- case CC_DISPLAY_SPRITE:
- this.updateSpriteDisplay(bone, display, dt, dirty);
- break;
- case CC_DISPLAY_PARTICLE:
- this.updateParticleDisplay(bone, display, dt, dirty);
- break;
- case CC_DISPLAY_ARMATURE:
- this.updateArmatureDisplay(bone, display, dt, dirty);
- break;
- default:
- display.setAdditionalTransform(bone.nodeToArmatureTransform());
- break;
- }
-};
-cc.DisplayFactory.addSpriteDisplay = function (bone, decoDisplay, displayData) {
- var sdp = new cc.SpriteDisplayData();
- sdp.copy(displayData);
- decoDisplay.setDisplayData(sdp);
- this.createSpriteDisplay(bone, decoDisplay);
-};
-
-cc.DisplayFactory.createSpriteDisplay = function (bone, decoDisplay) {
- var skin = null;
- var displayData = decoDisplay.getDisplayData();
- //! remove .xxx
- var textureName = displayData.displayName;
- var startPos = textureName.lastIndexOf(".");
- if (startPos != -1) {
- textureName = textureName.substring(0, startPos);
- }
- //! create display
- if (textureName == "") {
- skin = cc.Skin.create();
- }
- else {
- skin = cc.Skin.createWithSpriteFrameName(textureName + ".png");
- }
- this.initSpriteDisplay(bone, decoDisplay, displayData.displayName, skin);
- skin.setBone(bone);
- var armature = bone.getArmature();
- if (armature) {
- if (armature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED)
- skin.setSkinData(displayData.skinData);
- else
- skin.setSkinData(bone.getBoneData());
- }
-
- decoDisplay.setDisplay(skin);
-};
-
-cc.DisplayFactory.initSpriteDisplay = function(bone, decoDisplay, displayName, skin){
- var textureName = displayName;
- var startPos = textureName.lastIndexOf(".");
- if (startPos != -1) {
- textureName = textureName.substring(0, startPos);
- }
- var textureData = cc.ArmatureDataManager.getInstance().getTextureData(textureName);
- if (textureData) {
- //! Init display anchorPoint, every Texture have a anchor point
- skin.setAnchorPoint(cc.p(textureData.pivotX, textureData.pivotY));
- }
- if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) {
- if (textureData && textureData.contourDataList.length > 0) {
- var colliderDetector = cc.ColliderDetector.create(bone);
- colliderDetector.addContourDataList(textureData.contourDataList);
- decoDisplay.setColliderDetector(colliderDetector);
- }
- }
-},
-
-cc.DisplayFactory.updateSpriteDisplay = function (bone, skin, dt, dirty) {
- if(!dirty)
- return;
- skin.updateBlendType(bone.getBlendType());
- skin.updateArmatureTransform();
-};
-
-cc.DisplayFactory.addArmatureDisplay = function (bone, decoDisplay, displayData) {
- var adp = new cc.ArmatureDisplayData();
- adp.copy(displayData);
- decoDisplay.setDisplayData(adp);
-
- this.createArmatureDisplay(bone, decoDisplay);
-};
-cc.DisplayFactory.createArmatureDisplay = function (bone, decoDisplay) {
- var displayData = decoDisplay.getDisplayData();
- var armature = cc.Armature.create(displayData.displayName, bone);
- /*
- * because this bone have called this name, so armature should change it's name, or it can't add to
- * CCArmature's bone children.
- */
- armature.setName(bone.getName() + "_armatureChild");
- decoDisplay.setDisplay(armature);
-};
-cc.DisplayFactory.updateArmatureDisplay = function (bone, armature, dt, dirty) {
- if (!dirty)
- return;
- if (armature) {
- armature.sortAllChildren();
- armature.update(dt);
- }
-};
-
-cc.DisplayFactory.addParticleDisplay = function (bone, decoDisplay, displayData) {
- var adp = new cc.ParticleDisplayData();
- adp.copy(displayData);
- decoDisplay.setDisplayData(adp);
- this.createParticleDisplay(bone, decoDisplay);
-};
-cc.DisplayFactory.createParticleDisplay = function (bone, decoDisplay) {
- var displayData = decoDisplay.getDisplayData();
- var system = cc.ParticleSystem.create(displayData.plist);
- decoDisplay.setDisplay(system);
-};
-cc.DisplayFactory.updateParticleDisplay = function (bone, particleSystem, dt, dirty) {
- var node = new cc.BaseData();
- cc.TransformHelp.matrixToNode(bone.nodeToArmatureTransform(), node);
- particleSystem.setPosition(cc.p(node.x, node.y));
- particleSystem.setScaleX(node.scaleX);
- particleSystem.setScaleY(node.scaleY);
- particleSystem.update(dt);
-};
diff --git a/extensions/CocoStudio/Armature/display/CCDisplayManager.js b/extensions/CocoStudio/Armature/display/CCDisplayManager.js
deleted file mode 100644
index 55550f6655..0000000000
--- a/extensions/CocoStudio/Armature/display/CCDisplayManager.js
+++ /dev/null
@@ -1,313 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.DisplayManager = cc.Class.extend({
- _decoDisplayList:null,
- _currentDecoDisplay:null,
- _displayRenderNode:null,
- _displayIndex:-1,
- _forceChangeDisplay:false,
- _bone:null,
- _visible:true,
- ctor:function () {
- this._decoDisplayList = [];
- this._currentDecoDisplay = null;
- this._displayRenderNode = null;
- this._displayIndex = -1;
- this._forceChangeDisplay = false;
- this._bone = null;
- this._visible = true;
- },
-
- init:function (bone) {
- this._bone = bone;
- this.initDisplayList(bone.getBoneData());
- return true;
- },
-
- addDisplay: function (displayData, index) {
- var decoDisplay = null;
- if (index >= 0 && index < this._decoDisplayList.length) {
- decoDisplay = this._decoDisplayList[index];
- }
- else {
- decoDisplay = cc.DecotativeDisplay.create();
- this._decoDisplayList.push(decoDisplay);
- }
-
- if(displayData instanceof cc.DisplayData){
- cc.DisplayFactory.addDisplay(this._bone, decoDisplay, displayData);
- }else{
- this._addDisplayOther(decoDisplay,displayData);
- }
-
- //! if changed display index is current display index, then change current display to the new display
- if (index == this._displayIndex) {
- this._displayIndex = -1;
- this.changeDisplayByIndex(index, false);
- }
- },
-
- _addDisplayOther:function(decoDisplay,display){
- var displayData = null;
- if (display instanceof cc.Skin){
- var skin = display;
- skin.setBone(this._bone);
- displayData = new cc.SpriteDisplayData();
- cc.DisplayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin);
- var spriteDisplayData = decoDisplay.getDisplayData();
- if (spriteDisplayData instanceof cc.SpriteDisplayData)
- skin.setSkinData(spriteDisplayData.skinData);
- else
- skin.setSkinData(new cc.BaseData());
- }
- else if (display instanceof cc.ParticleSystem){
- displayData = new cc.ParticleDisplayData();
- }
- else if (display instanceof cc.Armature){
- displayData = new cc.ArmatureDisplayData();
- display.setParentBone(this._bone);
- }
- else {
- displayData = new cc.DisplayData();
- }
- decoDisplay.setDisplay(display);
- decoDisplay.setDisplayData(displayData);
- },
-
- removeDisplay:function (index) {
- //cc.ArrayRemoveObjectAtIndex(this._decoDisplayList, index);
- this._decoDisplayList[index] = null;
- if (index == this._displayIndex) {
- this.setCurrentDecorativeDisplay(null);
- }
- },
-
- getDecorativeDisplayList:function(){
- return this._decoDisplayList;
- },
-
- changeDisplayByIndex:function (index, force) {
- if (index >= this._decoDisplayList.length) {
- cc.log("the index value is out of range");
- return;
- }
-
- this._forceChangeDisplay = force;
-
- //this._displayIndex == -1, it means you want to hide you display
- if (index < 0) {
- this._displayIndex = index;
- if (this._displayRenderNode) {
- this._displayRenderNode.removeFromParent(true);
- this.setCurrentDecorativeDisplay(null);
- this._displayRenderNode = null;
- }
- return;
- }
-
- //if index is equal to current display index,then do nothing
- if (this._displayIndex == index) {
- return;
- }
-
- this._displayIndex = index;
-
- var decoDisplay = this._decoDisplayList[this._displayIndex];
-
- if(!decoDisplay){
- return;
- }
-
- this.setCurrentDecorativeDisplay(decoDisplay);
- },
-
- setCurrentDecorativeDisplay:function (decoDisplay) {
- var locCurrentDecoDisplay = this._currentDecoDisplay;
- if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) {
- if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
- locCurrentDecoDisplay.getColliderDetector().setActive(false);
- }
- }
-
- this._currentDecoDisplay = decoDisplay;
- locCurrentDecoDisplay = this._currentDecoDisplay;
- if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) {
- if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
- locCurrentDecoDisplay.getColliderDetector().setActive(true);
- }
- }
-
- var displayRenderNode = locCurrentDecoDisplay == null ? null : locCurrentDecoDisplay.getDisplay();
- if (this._displayRenderNode) {
- if (this._displayRenderNode instanceof cc.Armature) {
- this._bone.setChildArmature(null);
- }
- this._displayRenderNode.removeFromParent(true);
- this._displayRenderNode.release();
- this._displayRenderNode = null;
- }
-
- this._displayRenderNode = displayRenderNode;
-
- if (displayRenderNode) {
- if (displayRenderNode instanceof cc.Armature) {
- this._bone.setChildArmature(displayRenderNode);
- }else if(displayRenderNode instanceof cc.ParticleSystem) {
- displayRenderNode.resetSystem();
- }
- if (displayRenderNode.RGBAProtocol) {
- //this._displayRenderNode.setColor(this._bone.getColor());
- //this._displayRenderNode.setOpacity(this._bone.getOpacity());
- }
- displayRenderNode.retain();
- //todo
- //this._displayRenderNode.setVisible(this._visible);
- }
- },
-
- getDisplayRenderNode:function () {
- return this._displayRenderNode;
- },
-
- getCurrentDisplayIndex:function () {
- return this._displayIndex;
- },
-
- getCurrentDecorativeDisplay:function () {
- return this._currentDecoDisplay;
- },
-
- getDecorativeDisplayByIndex:function (index) {
- return this._decoDisplayList[index];
- },
-
- initDisplayList:function (boneData) {
- this._decoDisplayList = [];
- if (!boneData) {
- return;
- }
- var displayList = boneData.displayDataList;
- for (var i = 0; i < displayList.length; i++) {
- var displayData = displayList[i];
- var decoDisplay = cc.DecotativeDisplay.create();
- decoDisplay.setDisplayData(displayData);
-
- cc.DisplayFactory.createDisplay(this._bone, decoDisplay);
-
- this._decoDisplayList.push(decoDisplay);
- }
- },
-
- containPoint:function (point) {
- if (!this._visible || this._displayIndex < 0) {
- return false;
- }
-
- var ret = false;
- switch (this._currentDecoDisplay.getDisplayData().displayType) {
- case CC_DISPLAY_SPRITE:
- /*
- * First we first check if the point is in the sprite content rect. If false, then we continue to check
- * the contour point. If this step is also false, then we can say the bone not contain this point.
- *
- */
- var outPoint = cc.p(0, 0);
- var sprite = this._currentDecoDisplay.getDisplay();
- sprite = sprite.getChildByTag(0);
- ret = cc.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, point, outPoint);
- break;
- default:
- break;
- }
- return ret;
- },
-
- containPoint:function (x, y) {
- var p = cc.p(x, y);
- return this.containPoint(p);
- },
-
-
- setVisible:function (visible) {
- if (!this._displayRenderNode) {
- return;
- }
- this._visible = visible;
- this._displayRenderNode.setVisible(visible);
- },
-
- isVisible:function () {
- return this._visible;
- },
-
- getContentSize:function () {
- if (!this._displayRenderNode) {
- return cc.size(0, 0);
- }
- return this._displayRenderNode.getContentSize();
- },
-
- getBoundingBox:function () {
- if (!this._displayRenderNode) {
- return cc.rect(0, 0, 0, 0);
- }
- return this._displayRenderNode.getBoundingBox();
- },
-
- getAnchorPoint:function () {
- if (!this._displayRenderNode) {
- return cc.p(0, 0);
- }
- return this._displayRenderNode.getAnchorPoint();
- },
-
- getAnchorPointInPoints:function () {
- if (!this._displayRenderNode) {
- return cc.p(0, 0);
- }
- return this._displayRenderNode.getAnchorPointInPoints();
- },
-
- getForceChangeDisplay:function () {
- return this._forceChangeDisplay;
- },
-
- release:function () {
- this._decoDisplayList = [];
- if (this._displayRenderNode) {
- this._displayRenderNode.removeFromParent(true);
- this._displayRenderNode = null;
- }
- }
-
-});
-
-cc.DisplayManager.create = function (bone) {
- var displayManager = new cc.DisplayManager();
- if (displayManager && displayManager.init(bone)) {
- return displayManager;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/display/CCSkin.js b/extensions/CocoStudio/Armature/display/CCSkin.js
deleted file mode 100644
index 421f2175f2..0000000000
--- a/extensions/CocoStudio/Armature/display/CCSkin.js
+++ /dev/null
@@ -1,207 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.Skin = cc.Sprite.extend({
- _skinData:null,
- _bone:null,
- _skinTransform:null,
- _displayName:"",
- ctor:function () {
- cc.Sprite.prototype.ctor.call(this);
- this._skinData = null;
- this._bone = null;
- this._displayName = "";
- this._skinTransform = cc.AffineTransformIdentity();
- },
- initWithSpriteFrameName:function(spriteFrameName){
- var ret = cc.Sprite.prototype.initWithSpriteFrameName.call(this,spriteFrameName);
- var atlas = cc.SpriteFrameCacheHelper.getInstance().getTexureAtlasWithTexture(this._texture);
- this.setTextureAtlas(atlas);
- this._displayName = spriteFrameName;
- return ret;
- },
- initWithFile:function(spriteFrameName){
- var ret = cc.Sprite.prototype.initWithFile.call(this,spriteFrameName);
- var atlas = cc.SpriteFrameCacheHelper.getInstance().getTexureAtlasWithTexture(this._texture);
- this.setTextureAtlas(atlas);
- this._displayName = spriteFrameName;
- return ret;
- },
- setSkinData:function (skinData) {
- this._skinData = skinData;
-
- this.setScaleX(skinData.scaleX);
- this.setScaleY(skinData.scaleY);
- this.setRotation(cc.RADIANS_TO_DEGREES(skinData.skewX));
- this.setPosition(skinData.x, skinData.y);
-
- this._skinTransform = this.nodeToParentTransform();
- },
-
- getSkinData:function () {
- return this._skinData;
- },
-
- setBone:function (bone) {
- this._bone = bone;
- },
-
- getBone:function () {
- return this._bone;
- },
-
- updateArmatureTransform:function () {
- this._transform = cc.AffineTransformConcat(this._skinTransform, this._bone.nodeToArmatureTransform());
- },
- /** returns a "local" axis aligned bounding box of the node.
- * The returned box is relative only to its parent.
- * @return {cc.Rect}
- */
- getBoundingBox:function () {
- var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
- var transForm = this.nodeToParentTransform();
- return cc.RectApplyAffineTransform(rect, transForm);
- },
-
- /**
- * display name getter
- * @returns {String}
- */
- getDisplayName:function(){
- return this._displayName;
- },
-
- nodeToWorldTransform: function () {
- return cc.AffineTransformConcat(this._transform, this._bone.getArmature().nodeToWorldTransform());
- },
-
- nodeToWorldTransformAR: function () {
- var displayTransform = this._transform;
- var anchorPoint = this._anchorPointInPoints;
-
- anchorPoint = cc.PointApplyAffineTransform(anchorPoint, displayTransform);
- displayTransform.tx = anchorPoint.x;
- displayTransform.ty = anchorPoint.y;
-
- return cc.AffineTransformConcat(displayTransform, this._bone.getArmature().nodeToWorldTransform());
- },
- /**
- * update blendType
- * @param {cc.BlendType} blendType
- */
- updateBlendType: function (blendType) {
- var blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
- switch (blendType) {
- case cc.BlendType.NORMAL:
- blendFunc.src = cc.BLEND_SRC;
- blendFunc.dst = cc.BLEND_DST;
- break;
- case cc.BlendType.ADD:
- blendFunc.src = gl.SRC_ALPHA;
- blendFunc.dst = gl.ONE;
- break;
- case cc.BlendType.MULTIPLY:
- blendFunc.src = gl.ONE_MINUS_SRC_ALPHA;
- blendFunc.dst = gl.ONE_MINUS_DST_COLOR;
- break;
- case cc.BlendType.SCREEN:
- blendFunc.src = gl.ONE;
- blendFunc.dst = gl.ONE_MINUS_DST_COLOR;
- break;
- default:
- break;
- }
- this.setBlendFunc(blendFunc.src, blendFunc.dst);
- },
- updateQuad:function () {
- return;
- // If it is not visible, or one of its ancestors is not visible, then do nothing:
- if (!this._visible) {
- this._quad.br.vertices = {x:0, y:0, z:0};
- this._quad.tl.vertices = {x:0, y:0, z:0};
- this._quad.tr.vertices = {x:0, y:0, z:0};
- this._quad.bl.vertices = {x:0, y:0, z:0};
- } else {
- // calculate the Quad based on the Affine Matrix
- var size = this._rect.size;
-
- var x1 = this._offsetPosition.x;
- var y1 = this._offsetPosition.y;
-
- var x2 = x1 + size.width;
- var y2 = y1 + size.height;
-
- var x = this._transform.tx;
- var y = this._transform.ty;
-
- var cr = this._transform.a;
- var sr = this._transform.b;
- var cr2 = this._transform.d;
- var sr2 = -this._transform.c;
- var ax = x1 * cr - y1 * sr2 + x;
- var ay = x1 * sr + y1 * cr2 + y;
-
- var bx = x2 * cr - y1 * sr2 + x;
- var by = x2 * sr + y1 * cr2 + y;
-
- var cx = x2 * cr - y2 * sr2 + x;
- var cy = x2 * sr + y2 * cr2 + y;
-
- var dx = x1 * cr - y2 * sr2 + x;
- var dy = x1 * sr + y2 * cr2 + y;
-
- this._quad.bl.vertices = {x:cc.RENDER_IN_SUBPIXEL(ax), y:cc.RENDER_IN_SUBPIXEL(ay), z:this._vertexZ};
- this._quad.br.vertices = {x:cc.RENDER_IN_SUBPIXEL(bx), y:cc.RENDER_IN_SUBPIXEL(by), z:this._vertexZ};
- this._quad.tl.vertices = {x:cc.RENDER_IN_SUBPIXEL(dx), y:cc.RENDER_IN_SUBPIXEL(dy), z:this._vertexZ};
- this._quad.tr.vertices = {x:cc.RENDER_IN_SUBPIXEL(cx), y:cc.RENDER_IN_SUBPIXEL(cy), z:this._vertexZ};
-
- }
-
- // MARMALADE CHANGE: ADDED CHECK FOR NULL, TO PERMIT SPRITES WITH NO BATCH NODE / TEXTURE ATLAS
- if (this._textureAtlas) {
- this._textureAtlas.updateQuad(this._quad, this._textureAtlas.getTotalQuads());
- }
- }
-});
-
-cc.Skin.create = function (fileName, rect) {
- var argnum = arguments.length;
- var sprite = new cc.Skin();
- if (argnum === 0) {
- if (sprite.init())
- return sprite;
- } else {
- if (sprite && sprite.initWithFile(fileName, rect))
- return sprite;
- }
- return null;
-};
-
-cc.Skin.createWithSpriteFrameName = function (pszSpriteFrameName) {
- var skin = new cc.Skin();
- if (skin && skin.initWithSpriteFrameName(pszSpriteFrameName)) {
- return skin;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/physics/CCColliderDetector.js b/extensions/CocoStudio/Armature/physics/CCColliderDetector.js
deleted file mode 100644
index 00044399a2..0000000000
--- a/extensions/CocoStudio/Armature/physics/CCColliderDetector.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.ColliderBody = cc.Class.extend({
- _shape: null,
- _contourData: null,
- ctor: function (contourData) {
- this._contourData = contourData;
- },
- getContourData: function () {
- return this._contourData;
- },
- setContourData: function (contourData) {
- this._contourData = contourData;
- },
- getShape: function () {
- return this._shape;
- },
- setShape: function (shage) {
- this._shape = shage;
- }
-});
-cc.ColliderDetector = cc.Class.extend({
- _colliderBodyList: null,
- _bone: null,
- _body: null,
- _active: false,
- ctor: function () {
- this._colliderBodyList = [];
- },
- init: function (bone) {
- this._colliderBodyList = [];
- if (bone)
- this._bone = bone;
- return true;
- },
- addContourData: function (contourData) {
- var colliderBody = new cc.ColliderBody(contourData);
- this._colliderBodyList.push(colliderBody);
- },
- addContourDataList: function (contourDataList) {
- for (var i = 0; i < contourDataList.length; i++) {
- this.addContourData(contourDataList[i]);
- }
- },
- removeContourData: function (contourData) {
- var locColliderBodyList = this._colliderBodyList;
- for (var i = 0; i < locColliderBodyList.length; i++) {
- if(locColliderBodyList[i].getContourData()==contourData){
- locColliderBodyList.splice(i, 1);
- return;
- }
- }
- },
- removeAll: function () {
- this._colliderBodyList = [];
- },
-
- setColliderFilter: function (filter) {
-
- },
- setActive: function (active) {
- if (this._active == active)
- return;
- this._active = active;
- var locBody = this._body;
- var locShape;
- if (locBody) {
- var colliderBody = null;
- if (this._active) {
- for (var i = 0; i < this._colliderBodyList.length; i++) {
- colliderBody = this._colliderBodyList[i];
- locShape = colliderBody.getShape();
- locBody.space.addShape(locShape);
- }
- }
- else {
- for (var i = 0; i < this._colliderBodyList.length; i++) {
- colliderBody = this._colliderBodyList[i];
- locShape = colliderBody.getShape();
- locBody.space.removeShape(locShape);
- }
- }
- }
- },
- getActive: function () {
- return this._active;
- },
- getColliderBodyList: function () {
- return this._colliderBodyList;
- },
- helpPoint: cc.p(0, 0),
- updateTransform: function (t) {
- if (!this._active)
- return;
-
- var colliderBody = null;
- var locBody = this._body;
- var locHelpPoint = this.helpPoint;
- for (var i = 0; i < this._colliderBodyList.length; i++) {
- colliderBody = this._colliderBodyList[i];
- var contourData = colliderBody.getContourData();
- var shape = null;
- if (locBody) {
- shape = colliderBody.getShape();
- locBody.p.x = t.tx;
- locBody.p.y = t.ty;
- locBody.p.a = t.a;
- var vs = contourData.vertexList;
- for (var i = 0; i < vs.length; i++) {
- locHelpPoint.x = vs[i].x;
- locHelpPoint.y = vs[i].y;
- locHelpPoint = cc.PointApplyAffineTransform(locHelpPoint, t);
- if (shape) {
- var v = new cp.Vect(0, 0);
- v.x = locHelpPoint.x;
- v.y = locHelpPoint.y;
- shape.verts[i * 2] = locHelpPoint.x - t.tx;
- shape.verts[i * 2 + 1] = locHelpPoint.y - t.ty;
- }
- }
- }
- }
- },
- getBody: function () {
- return this._body;
- },
- setBody: function (body) {
- this._body = body;
- var colliderBody;
- for (var i = 0; i < this._colliderBodyList.length; i++) {
- colliderBody = this._colliderBodyList[i];
- var contourData = colliderBody.getContourData();
- var verts = [];
- var vs = contourData.vertexList;
- for (var i = 0; i < vs.length; i++) {
- var v = vs[i];
- verts.push(v.x);
- verts.push(v.y);
- }
- var shape = new cp.PolyShape(this._body, verts, cp.vzero);
- shape.sensor = true;
- shape.data = this._bone;
- this._body.space.addShape(shape);
- colliderBody.setShape(shape);
- }
- }
-});
-cc.ColliderDetector.create = function (bone) {
- var colliderDetector = new cc.ColliderDetector();
- if (colliderDetector && colliderDetector.init(bone)) {
- return colliderDetector;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js b/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js
deleted file mode 100644
index 18d0b96666..0000000000
--- a/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js
+++ /dev/null
@@ -1,826 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.CONST_VERSION = "version";
-cc.CONST_VERSION_2_0 = 2.0;
-cc.CONST_VERSION_COMBINED = 0.3;
-
-cc.CONST_SKELETON = "skeleton";
-cc.CONST_ARMATURES = "armatures";
-cc.CONST_ARMATURE = "armature";
-cc.CONST_BONE = "b";
-cc.CONST_DISPLAY = "d";
-
-cc.CONST_ANIMATIONS = "animations";
-cc.CONST_ANIMATION = "animation";
-cc.CONST_MOVEMENT = "mov";
-cc.CONST_FRAME = "f";
-
-cc.CONST_TEXTURE_ATLAS = "TextureAtlas";
-cc.CONST_SUB_TEXTURE = "SubTexture";
-
-cc.CONST_A_NAME = "name";
-cc.CONST_A_DURATION = "dr";
-cc.CONST_A_FRAME_INDEX = "fi";
-cc.CONST_A_DURATION_TO = "to";
-cc.CONST_A_DURATION_TWEEN = "drTW";
-cc.CONST_A_LOOP = "lp";
-cc.CONST_A_MOVEMENT_SCALE = "sc";
-cc.CONST_A_MOVEMENT_DELAY = "dl";
-cc.CONST_A_DISPLAY_INDEX = "dI";
-
-cc.CONST_A_VERT = "vert";
-cc.CONST_A_FRAG = "frag";
-cc.CONST_A_PLIST = "plist";
-
-cc.CONST_A_PARENT = "parent";
-cc.CONST_A_SKEW_X = "kX";
-cc.CONST_A_SKEW_Y = "kY";
-cc.CONST_A_SCALE_X = "cX";
-cc.CONST_A_SCALE_Y = "cY";
-cc.CONST_A_Z = "z";
-cc.CONST_A_EVENT = "evt";
-cc.CONST_A_SOUND = "sd";
-cc.CONST_A_SOUND_EFFECT = "sdE";
-cc.CONST_A_TWEEN_EASING = "twE";
-cc.CONST_A_TWEEN_ROTATE = "twR";
-cc.CONST_A_IS_ARMATURE = "isArmature";
-cc.CONST_A_DISPLAY_TYPE = "displayType";
-cc.CONST_A_MOVEMENT = "mov";
-cc.CONST_A_BLEND_TYPE = "bd";
-
-cc.CONST_A_X = "x";
-cc.CONST_A_Y = "y";
-
-cc.CONST_A_COCOS2DX_X = "cocos2d_x";
-cc.CONST_A_COCOS2DX_Y = "cocos2d_y";
-
-cc.CONST_A_WIDTH = "width";
-cc.CONST_A_HEIGHT = "height";
-cc.CONST_A_PIVOT_X = "pX";
-cc.CONST_A_PIVOT_Y = "pY";
-
-cc.CONST_A_COCOS2D_PIVOT_X = "cocos2d_pX";
-cc.CONST_A_COCOS2D_PIVOT_Y = "cocos2d_pY";
-
-cc.CONST_A_ALPHA = "a";
-cc.CONST_A_RED = "r";
-cc.CONST_A_GREEN = "g";
-cc.CONST_A_BLUE = "b";
-cc.CONST_A_ALPHA_OFFSET = "aM";
-cc.CONST_A_RED_OFFSET = "rM";
-cc.CONST_A_GREEN_OFFSET = "gM";
-cc.CONST_A_BLUE_OFFSET = "bM";
-cc.CONST_A_COLOR_TRANSFORM = "colorTransform";
-cc.CONST_A_ROTATION = "rotation";
-cc.CONST_A_USE_COLOR_INFO = "uci";
-
-cc.CONST_CONTOUR = "con";
-cc.CONST_CONTOUR_VERTEX = "con_vt";
-
-cc.CONST_MOVEMENT_EVENT_FRAME = "movementEventFrame";
-cc.CONST_SOUND_FRAME = "soundFrame";
-
-cc.CONST_FL_NAN = "NaN";
-
-cc.CONST_FRAME_DATA = "frame_data";
-cc.CONST_MOVEMENT_BONE_DATA = "mov_bone_data";
-cc.CONST_MOVEMENT_FRAME_DATA = "mov_frame_data";
-cc.CONST_MOVEMENT_DATA = "mov_data";
-cc.CONST_ANIMATION_DATA = "animation_data";
-cc.CONST_DISPLAY_DATA = "display_data";
-cc.CONST_SKIN_DATA = "skin_data";
-cc.CONST_BONE_DATA = "bone_data";
-cc.CONST_ARMATURE_DATA = "armature_data";
-cc.CONST_CONTOUR_DATA = "contour_data";
-cc.CONST_TEXTURE_DATA = "texture_data";
-cc.CONST_VERTEX_POINT = "vertex";
-cc.CONST_COLOR_INFO = "color";
-
-cc.CONST_CONFIG_FILE_PATH = "config_file_path";
-
-cc.DataReaderHelper = cc.DataReaderHelper || {};
-cc.DataReaderHelper._configFileList = [];
-cc.DataReaderHelper._flashToolVersion = cc.CONST_VERSION_2_0;
-cc.DataReaderHelper._cocoStudioVersion = cc.CONST_VERSION_COMBINED;
-cc.DataReaderHelper._positionReadScale = 1;
-cc.DataReaderHelper._basefilePath = "";
-cc.DataReaderHelper._asyncRefCount = 0;
-cc.DataReaderHelper._asyncRefTotalCount = 0;
-
-cc.DataReaderHelper.setPositionReadScale = function (scale) {
- this._positionReadScale = scale;
-};
-
-cc.DataReaderHelper.getPositionReadScale = function () {
- return this._positionReadScale;
-};
-
-cc.DataReaderHelper.clear = function () {
- this._configFileList = [];
- this._basefilePath = "";
- cc.DataReaderHelper._asyncRefCount = 0;
- cc.DataReaderHelper._asyncRefTotalCount = 0;
-};
-
-cc.DataReaderHelper.addDataFromFile = function (filePath,isLoadSpriteFrame) {
- var fileUtils = cc.FileUtils.getInstance();
- var fullFilePath = fileUtils.fullPathForFilename(filePath);
-
- if (cc.ArrayContainsObject(this._configFileList, fullFilePath)) {
- return;
- }
- this._configFileList.push(fullFilePath);
-
- this._initBaseFilePath(filePath);
-
- var startPos = fullFilePath.lastIndexOf(".");
- var str = fullFilePath.substring(startPos, fullFilePath.length);
-
- if (str == ".xml") {
- this.addDataFromXML(fullFilePath);
- }
- else if (str == ".json" || str == ".ExportJson") {
- this.addDataFromJson(fullFilePath,isLoadSpriteFrame);
- }
-};
-
-cc.DataReaderHelper.addDataFromFileAsync = function (filePath,target,selector,isLoadSpriteFrame) {
- var fileUtils = cc.FileUtils.getInstance();
- var fullFilePath = fileUtils.fullPathForFilename(filePath);
-
- if (cc.ArrayContainsObject(this._configFileList, fullFilePath)) {
- if (target && selector) {
- if (this._asyncRefTotalCount == 0 && this._asyncRefCount == 0)
- this._asyncCallBack(target, selector, 1);
- else
- this._asyncCallBack(target, selector, (this._asyncRefTotalCount - this._asyncRefCount) / this._asyncRefTotalCount);
- }
- return;
- }
- this._asyncRefTotalCount++;
- this._asyncRefCount++;
- var self = this;
- var fun = function () {
- self.addDataFromFile(filePath,isLoadSpriteFrame);
- self._asyncRefCount--;
- self._asyncCallBack(target, selector, (self._asyncRefTotalCount - self._asyncRefCount) / self._asyncRefTotalCount);
- };
- cc.Director.getInstance().getScheduler().scheduleCallbackForTarget(this, fun, 0.1, false);
-};
-
-cc.DataReaderHelper._asyncCallBack=function (target, selector,percent) {
- if (target && (typeof(selector) == "string")) {
- target[selector](percent);
- } else if (target && (typeof(selector) == "function")) {
- selector.call(target,percent);
- }
-};
-cc.DataReaderHelper._initBaseFilePath = function(filePath){
- //! find the base file path
- this._basefilePath = filePath;
- var pos = this._basefilePath.lastIndexOf("/");
- if(pos>-1)
- this._basefilePath = this._basefilePath.substr(0, pos + 1);
- else
- this._basefilePath = "";
-};
-
-cc.DataReaderHelper.addDataFromXML = function (xml) {
- /*
- * Need to get the full path of the xml file, or the Tiny XML can't find the xml at IOS
- */
- var skeletonXML = cc.SAXParser.getInstance().tmxParse(xml);
- var skeleton = skeletonXML.documentElement;
- if (skeleton) {
- this.addDataFromCache(skeleton);
- }
-};
-
-cc.DataReaderHelper.addDataFromCache = function (skeleton) {
- if (!skeleton) {
- cc.log("XML error or XML is empty.");
- return;
- }
- this._flashToolVersion = parseFloat(skeleton.getAttribute(cc.CONST_VERSION));
- var _armaturesXML = skeleton.querySelectorAll(cc.CONST_SKELETON + " > " + cc.CONST_ARMATURES + " > " + cc.CONST_ARMATURE + "");
- var armatureDataManager = cc.ArmatureDataManager.getInstance();
- for (var i = 0; i < _armaturesXML.length; i++) {
- var armatureData = this.decodeArmature(_armaturesXML[i]);
- armatureDataManager.addArmatureData(armatureData.name, armatureData);
- }
-
- var _animationsXML = skeleton.querySelectorAll(cc.CONST_SKELETON + " > " + cc.CONST_ANIMATIONS + " > " + cc.CONST_ANIMATION + "");
- for (var i = 0; i < _animationsXML.length; i++) {
- var animationData = this.decodeAnimation(_animationsXML[i]);
- armatureDataManager.addAnimationData(animationData.name, animationData);
- }
-
- var _texturesXML = skeleton.querySelectorAll(cc.CONST_SKELETON + " > " + cc.CONST_TEXTURE_ATLAS + " > " + cc.CONST_SUB_TEXTURE + "");
- for (var i = 0; i < _texturesXML.length; i++) {
- var textureData = this.decodeTexture(_texturesXML[i]);
- armatureDataManager.addTextureData(textureData.name, textureData);
- }
- skeleton = null;
-};
-
-cc.DataReaderHelper.decodeArmature = function (armatureXML) {
- var name = armatureXML.getAttribute(cc.CONST_A_NAME);
- var armatureData = new cc.ArmatureData();
- armatureData.name = name;
-
- var bonesXML = armatureXML.querySelectorAll(cc.CONST_ARMATURE + " > " + cc.CONST_BONE);
-
- for (var i = 0; i < bonesXML.length; i++) {
- var boneXML = bonesXML[i];
- var parentName = boneXML.getAttribute(cc.CONST_A_PARENT);
- var parentXML = null;
- if (parentName) {
- //parentXML = armatureXML.querySelectorAll(cc.CONST_ARMATURE+" > "+cc.CONST_BONE);
- for (var j = 0; j < bonesXML.length; j++) {
- parentXML = bonesXML[j];
- if (parentName == bonesXML[j].getAttribute(cc.CONST_A_NAME)) {
- //todo
- break;
- }
- }
- }
- var boneData = this.decodeBone(boneXML, parentXML);
- armatureData.addBoneData(boneData);
- }
- return armatureData;
-};
-
-cc.DataReaderHelper.decodeBone = function (boneXML, parentXML) {
-
- var _name = boneXML.getAttribute(cc.CONST_A_NAME);
- if (_name == "") {
- return;
- }
- var boneData = new cc.BoneData();
- boneData.name = _name;
- boneData.parentName = boneXML.getAttribute(cc.CONST_A_PARENT) || "";
- boneData.zOrder = parseInt(boneXML.getAttribute(cc.CONST_A_Z)) || 0;
-
- var _displaysXML = boneXML.querySelectorAll(cc.CONST_BONE + " > " + cc.CONST_DISPLAY);
-
- var _displayXML
- for (var i = 0; i < _displaysXML.length; i++) {
- _displayXML = _displaysXML[i];
- var displayData = this.decodeBoneDisplay(_displayXML, boneData);
- boneData.addDisplayData(displayData);
-
- }
- return boneData;
-};
-
-cc.DataReaderHelper.decodeBoneDisplay = function (_displayXML) {
- var _isArmature = parseFloat(_displayXML.getAttribute(cc.CONST_A_IS_ARMATURE)) || 0;
-
- var _displayData = null;
-
- if (_isArmature == 1) {
- _displayData = new cc.ArmatureDisplayData();
- _displayData.displayType = CC_DISPLAY_ARMATURE;
- }
- else {
- _displayData = new cc.SpriteDisplayData();
- _displayData.displayType = CC_DISPLAY_SPRITE;
- }
- var displayName = _displayXML.getAttribute(cc.CONST_A_NAME) || "";
- if (displayName) {
- _displayData.displayName = displayName;
- }
- return _displayData;
-};
-
-
-cc.DataReaderHelper.decodeAnimation = function (_animationXML) {
- var name = _animationXML.getAttribute(cc.CONST_A_NAME);
- var aniData = new cc.AnimationData();
- var _armatureData = cc.ArmatureDataManager.getInstance().getArmatureData(name);
- aniData.name = name;
-
- var movementsXML = _animationXML.querySelectorAll(cc.CONST_ANIMATION + " > " + cc.CONST_MOVEMENT);
- var movementXML = null;
- for (var i = 0; i < movementsXML.length; i++) {
- movementXML = movementsXML[i];
- var movementData = this.decodeMovement(movementXML, _armatureData);
- aniData.addMovement(movementData);
- }
- return aniData;
-};
-
-cc.DataReaderHelper.decodeMovement = function (movementXML, _armatureData) {
- var movName = movementXML.getAttribute(cc.CONST_A_NAME);
- var movementData = new cc.MovementData();
- movementData.name = movName;
- var duration, durationTo, durationTween, loop = 0, tweenEasing = 0;
-
- duration = parseFloat(movementXML.getAttribute(cc.CONST_A_DURATION)) || 0;
- movementData.duration = duration;
-
- durationTo = parseFloat(movementXML.getAttribute(cc.CONST_A_DURATION_TO)) || 0;
- movementData.durationTo = durationTo;
-
- durationTween = parseFloat(movementXML.getAttribute(cc.CONST_A_DURATION_TWEEN)) || 0;
- movementData.durationTween = durationTween;
-
- loop = movementXML.getAttribute(cc.CONST_A_LOOP);
- movementData.loop = loop ? Boolean(parseFloat(loop)):true;
-
- var easing = movementXML.getAttribute(cc.CONST_A_TWEEN_EASING);
- if (easing) {
- if (easing != cc.CONST_FL_NAN) {
- tweenEasing = parseFloat(easing) || 0;
- movementData.tweenEasing = tweenEasing;
- } else {
- movementData.tweenEasing = cc.TweenType.TWEEN_EASING_MAX;
- }
- }
-
- var movBonesXml = movementXML.querySelectorAll(cc.CONST_MOVEMENT + " > " + cc.CONST_BONE);
- var movBoneXml = null;
- for (var i = 0; i < movBonesXml.length; i++) {
- movBoneXml = movBonesXml[i];
- var boneName = movBoneXml.getAttribute(cc.CONST_A_NAME);
-
- if (movementData.getMovementBoneData(boneName)) {
- continue;
- }
-
- // var _armatureData = this._armarureDatas[_aniData.getName()];
- var boneData = _armatureData.getBoneData(boneName);
- var parentName = boneData.parentName;
-
- var parentXML = null;
- if (parentName != "") {
- for (var j = 0; j < movBonesXml.length; j++) {
- parentXML = movBonesXml[j];
- if (parentName == parentXML.getAttribute(cc.CONST_A_NAME)) {
- break;
- }
- }
- }
- var moveBoneData = this.decodeMovementBone(movBoneXml, parentXML, boneData);
- movementData.addMovementBoneData(moveBoneData);
- }
- return movementData;
-};
-
-cc.DataReaderHelper.decodeMovementBone = function (movBoneXml, parentXml, boneData) {
- var movBoneData = new cc.MovementBoneData();
- var scale, delay;
-
- if (movBoneXml) {
- scale = parseFloat(movBoneXml.getAttribute(cc.CONST_A_MOVEMENT_SCALE)) || 0;
- movBoneData.scale = scale;
-
- delay = parseFloat(movBoneXml.getAttribute(cc.CONST_A_MOVEMENT_DELAY)) || 0;
- if (delay > 0) {
- delay -= 1;
- }
- movBoneData.delay = delay;
- }
-
- var length = 0;
- var parentTotalDuration = 0;
- var currentDuration = 0;
- var parentFrameXML = null;
- var parentXMLList = [];
-
- //* get the parent frame xml list, we need get the origin data
- if (parentXml != null) {
- var parentFramesXML = parentXml.querySelectorAll(cc.CONST_BONE + " > " + cc.CONST_FRAME);
- for (var i = 0; i < parentFramesXML.length; i++) {
- parentXMLList.push(parentFramesXML[i]);
- }
- length = parentXMLList.length;
- }
-
-
- var totalDuration = 0;
-
- var name = movBoneXml.getAttribute(cc.CONST_A_NAME);
- movBoneData.name = name;
- var framesXML = movBoneXml.querySelectorAll(cc.CONST_BONE + " > " + cc.CONST_FRAME);
- var j = 0;
- for (var ii = 0; ii < framesXML.length; ii++) {
- var frameXML = framesXML[ii];
- if (parentXml) {
- //* in this loop we get the corresponding parent frame xml
- while (j < length && (parentFrameXML ? (totalDuration < parentTotalDuration || totalDuration >= parentTotalDuration + currentDuration) : true)) {
- parentFrameXML = parentXMLList[j];
- parentTotalDuration += currentDuration;
- currentDuration = parseFloat(parentFrameXML.getAttribute(cc.CONST_A_DURATION));
- j++;
- }
- }
- var frameData = this.decodeFrame(frameXML, parentFrameXML, boneData, movBoneData);
- movBoneData.addFrameData(frameData);
- frameData.frameID = totalDuration;
- totalDuration += frameData.duration;
- movBoneData.duration = totalDuration;
- }
-
- if(movBoneData.frameList.length>0){
- var frameData = new cc.FrameData();
- frameData.copy(movBoneData.frameList[movBoneData.frameList.length-1]);
- frameData.frameID = movBoneData.duration;
- movBoneData.addFrameData(frameData);
- }
- return movBoneData;
-};
-
-cc.DataReaderHelper.decodeFrame = function (frameXML, parentFrameXml, boneData, movBoneData) {
- var frameData = new cc.FrameData();
- frameData.movement = frameXML.getAttribute(cc.CONST_A_MOVEMENT) || "";
- frameData.event = frameXML.getAttribute(cc.CONST_A_EVENT) || "";
- frameData.blendType = parseInt(frameXML.getAttribute(cc.CONST_A_BLEND_TYPE)) || cc.BlendType.NORMAL;
- frameData.sound = frameXML.getAttribute(cc.CONST_A_SOUND) || "";
- frameData.soundEffect = frameXML.getAttribute(cc.CONST_A_SOUND_EFFECT) || "";
-
- if (this._flashToolVersion >= cc.CONST_VERSION_2_0) {
- frameData.x = parseFloat(frameXML.getAttribute(cc.CONST_A_COCOS2DX_X)) || 0;
- frameData.y = -parseFloat(frameXML.getAttribute(cc.CONST_A_COCOS2DX_Y)) || 0;
- }
- else {
- frameData.x = parseFloat(frameXML.getAttribute(cc.CONST_A_X)) || 0;
- frameData.y = -parseFloat(frameXML.getAttribute(cc.CONST_A_Y)) || 0;
- }
- frameData.x *= this._positionReadScale;
- frameData.y *= this._positionReadScale;
- frameData.scaleX = parseFloat(frameXML.getAttribute(cc.CONST_A_SCALE_X)) || 0;
- frameData.scaleY = parseFloat(frameXML.getAttribute(cc.CONST_A_SCALE_Y)) || 0;
- frameData.skewX = cc.DEGREES_TO_RADIANS(parseFloat(frameXML.getAttribute(cc.CONST_A_SKEW_X)) || 0);
- frameData.skewY = cc.DEGREES_TO_RADIANS(-parseFloat(frameXML.getAttribute(cc.CONST_A_SKEW_Y)) || 0);
- frameData.duration = parseFloat(frameXML.getAttribute(cc.CONST_A_DURATION)) || 0;
- frameData.displayIndex = parseFloat(frameXML.getAttribute(cc.CONST_A_DISPLAY_INDEX)) || 0;
- frameData.zOrder = parseFloat(frameXML.getAttribute(cc.CONST_A_Z)) || 0;
-
- var colorTransformXMLList = frameXML.querySelectorAll(cc.CONST_FRAME + " > " + cc.CONST_A_COLOR_TRANSFORM);
- if (colorTransformXMLList.length > 0) {
- var colorTransformXML = colorTransformXMLList[0];
- var alpha = red = green = blue = 0;
- var alphaOffset = redOffset = greenOffset = blueOffset = 100;
-
- alpha = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_ALPHA)) || alpha;
- red = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_RED)) || red;
- green = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_GREEN)) || green;
- blue = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_BLUE)) || blue;
-
- var str_alphaOffset = colorTransformXML.getAttribute(cc.CONST_A_ALPHA_OFFSET);
- if(str_alphaOffset){
- alphaOffset = parseFloat(str_alphaOffset);
- }
- var str_redOffset = colorTransformXML.getAttribute(cc.CONST_A_RED_OFFSET);
- if(str_redOffset){
- redOffset = parseFloat(str_redOffset);
- }
- var str_greenOffset = colorTransformXML.getAttribute(cc.CONST_A_GREEN_OFFSET);
- if(str_redOffset){
- greenOffset = parseFloat(str_greenOffset);
- }
- var str_blueOffset = colorTransformXML.getAttribute(cc.CONST_A_BLUE_OFFSET);
- if(str_blueOffset){
- blueOffset = parseFloat(str_blueOffset);
- }
-
- frameData.a = 2.55 * alphaOffset + alpha;
- frameData.r = 2.55 * redOffset + red;
- frameData.g = 2.55 * greenOffset + green;
- frameData.b = 2.55 * blueOffset + blue;
-
- frameData.isUseColorInfo = true;
- }
- if(frameData.displayIndex==-1){
- frameData.a = 0;
- }
-
- var easing = frameXML.getAttribute(cc.CONST_A_TWEEN_EASING);
- if (easing) {
- if (easing != cc.CONST_FL_NAN) {
- frameData.tweenEasing = parseFloat(easing) || 0;
- } else {
- frameData.tweenEasing = cc.TweenType.TWEEN_EASING_MAX;
- }
- }
-
- if (parentFrameXml) {
- //* recalculate frame data from parent frame data, use for translate matrix
- var helpNode = new cc.BaseData();
- if (this._flashToolVersion >= cc.CONST_VERSION_2_0) {
- helpNode.x = parseFloat(parentFrameXml.getAttribute(cc.CONST_A_COCOS2DX_X)) || 0;
- helpNode.y = parseFloat(parentFrameXml.getAttribute(cc.CONST_A_COCOS2DX_Y)) || 0;
- }
- else {
- helpNode.x = parseFloat(parentFrameXml.getAttribute(cc.CONST_A_X)) || 0;
- helpNode.y = parseFloat(parentFrameXml.getAttribute(cc.CONST_A_Y)) || 0;
- }
- helpNode.skewX = parseFloat(parentFrameXml.getAttribute(cc.CONST_A_SKEW_X)) || 0;
- helpNode.skewY = parseFloat(parentFrameXml.getAttribute(cc.CONST_A_SKEW_Y)) || 0;
-
- helpNode.y = -helpNode.y;
- helpNode.skewX = cc.DEGREES_TO_RADIANS(helpNode.skewX);
- helpNode.skewY = cc.DEGREES_TO_RADIANS(-helpNode.skewY);
- cc.TransformHelp.transformFromParent(frameData, helpNode);
- }
- return frameData;
-};
-
-cc.DataReaderHelper.decodeTexture = function (textureXML) {
- var textureData = new cc.TextureData();
- if (textureXML.getAttribute(cc.CONST_A_NAME)) {
- textureData.name = textureXML.getAttribute(cc.CONST_A_NAME);
- }
- var px, py, width, height = 0;
- if (this._flashToolVersion >= cc.CONST_VERSION_2_0) {
- px = parseFloat(textureXML.getAttribute(cc.CONST_A_COCOS2D_PIVOT_X)) || 0;
- py = parseFloat(textureXML.getAttribute(cc.CONST_A_COCOS2D_PIVOT_Y)) || 0;
- }
- else {
- px = parseFloat(textureXML.getAttribute(cc.CONST_A_PIVOT_X)) || 0;
- py = parseFloat(textureXML.getAttribute(cc.CONST_A_PIVOT_Y)) || 0;
- }
- width = parseFloat(textureXML.getAttribute(cc.CONST_A_WIDTH)) || 0;
- height = parseFloat(textureXML.getAttribute(cc.CONST_A_HEIGHT)) || 0;
-
- var anchorPointX = px / width;
- var anchorPointY = (height - py) / height;
-
- textureData.pivotX = anchorPointX;
- textureData.pivotY = anchorPointY;
-
- var contoursXML = textureXML.querySelectorAll(cc.CONST_SUB_TEXTURE + " > " + cc.CONST_CONTOUR);
- for (var i = 0; i < contoursXML.length; i++) {
- this.decodeContour(contoursXML[i], textureData);
- }
- return textureData;
-};
-
-cc.DataReaderHelper.decodeContour = function (contourXML) {
- var contourData = new cc.ContourData();
- var vertexDatasXML = contourXML.querySelectorAll(cc.CONST_CONTOUR + " > " + cc.CONST_CONTOUR_VERTEX);
- var vertexDataXML;
- for (var i = 0; i < vertexDatasXML.length; i++) {
- vertexDataXML = vertexDatasXML[i];
- var vertex = cc.p(0, 0);
- vertex.x = parseFloat(vertexDataXML.getAttribute(cc.CONST_A_X)) || 0;
- vertex.y = parseFloat(vertexDataXML.getAttribute(cc.CONST_A_Y)) || 0;
- //vertex.y = - vertex.y;//todo
- contourData.vertexList.push(vertex);
- }
- return contourData;
-
-};
-
-cc.DataReaderHelper.addDataFromJson = function (filePath,isLoadSpriteFrame) {
- var fileContent = cc.FileUtils.getInstance().getTextFileData(filePath);
- this.addDataFromJsonCache(fileContent,isLoadSpriteFrame);
-};
-cc.DataReaderHelper.addDataFromJsonCache = function (content,isLoadSpriteFrame) {
- var dic = JSON.parse(content);
- var armatureDataArr = dic[cc.CONST_ARMATURE_DATA] || [];
- var armatureData;
- for (var i = 0; i < armatureDataArr.length; i++) {
- armatureData = this.decodeArmatureFromJSON(armatureDataArr[i]);
- cc.ArmatureDataManager.getInstance().addArmatureData(armatureData.name, armatureData);
- }
-
- var animationDataArr = dic[cc.CONST_ANIMATION_DATA] || [];
- var animationData;
- for (var i = 0; i < animationDataArr.length; i++) {
- animationData = this.decodeAnimationFromJson(animationDataArr[i]);
- cc.ArmatureDataManager.getInstance().addAnimationData(animationData.name, animationData);
- }
-
- var textureDataArr = dic[cc.CONST_TEXTURE_DATA] || [];
- var textureData;
- for (var i = 0; i < textureDataArr.length; i++) {
- textureData = this.decodeTextureFromJson(textureDataArr[i]);
- cc.ArmatureDataManager.getInstance().addTextureData(textureData.name, textureData);
- }
-
- if (isLoadSpriteFrame) {
- var configFiles = dic[cc.CONST_CONFIG_FILE_PATH] || [];
- var locFilePath, locPos, locPlistPath, locImagePath;
- for (var i = 0; i < configFiles.length; i++) {
- locFilePath = configFiles[i];
- locPos = locFilePath.lastIndexOf(".");
- locFilePath = locFilePath.substring(0, locPos);
- locPlistPath = this._basefilePath + locFilePath + ".plist";
- locImagePath = this._basefilePath + locFilePath + ".png";
- cc.ArmatureDataManager.getInstance().addSpriteFrameFromFile(locPlistPath, locImagePath);
- }
- }
-
- armatureData = null;
- animationData = null;
- textData = null;
-};
-
-cc.DataReaderHelper.decodeArmatureFromJSON = function (json) {
- var armatureData = new cc.ArmatureData();
-
- var name = json[cc.CONST_A_NAME];
- if (name) {
- armatureData.name = name;
- }
-
- this._cocoStudioVersion = armatureData.dataVersion = json[cc.CONST_VERSION] || 0.1;
-
- var boneDataList = json[cc.CONST_BONE_DATA];
- for (var i = 0; i < boneDataList.length; i++) {
- armatureData.addBoneData(this.decodeBoneFromJson(boneDataList[i]));
- }
- return armatureData;
-};
-
-cc.DataReaderHelper.decodeBoneFromJson = function (json) {
- var boneData = new cc.BoneData();
- this.decodeNodeFromJson(boneData, json);
- boneData.name = json[cc.CONST_A_NAME] || "";
- boneData.parentName = json[cc.CONST_A_PARENT] || "";
- var displayDataList = json[cc.CONST_DISPLAY_DATA] || [];
- for (var i = 0; i < displayDataList.length; i++) {
- boneData.addDisplayData(this.decodeBoneDisplayFromJson(displayDataList[i]));
- }
- return boneData;
-};
-
-cc.DataReaderHelper.decodeBoneDisplayFromJson = function (json) {
- var displayType = json[cc.CONST_A_DISPLAY_TYPE] || CC_DISPLAY_SPRITE;
- var displayData = null;
- switch (displayType) {
- case CC_DISPLAY_SPRITE:
- displayData = new cc.SpriteDisplayData();
- displayData.displayName = json[cc.CONST_A_NAME] || "";
-
- var dicArray = json[cc.CONST_SKIN_DATA]|| [];
- var dic = dicArray[0];
- if(dic){
- displayData.skinData.x = (dic[cc.CONST_A_X]|| 0) * this._positionReadScale;
- displayData.skinData.y = (dic[cc.CONST_A_Y]||0) * this._positionReadScale;
- displayData.skinData.scaleX = dic[cc.CONST_A_SCALE_X]|| 1;
- displayData.skinData.scaleY = dic[cc.CONST_A_SCALE_Y]|| 1;
- displayData.skinData.skewX = dic[cc.CONST_A_SKEW_X]|| 0;
- displayData.skinData.skewY = dic[cc.CONST_A_SKEW_Y]||0;
- dic = null;
- }
- break;
- case CC_DISPLAY_ARMATURE:
- displayData = new cc.ArmatureDisplayData();
- displayData.displayName = json[cc.CONST_A_NAME] || "";
- break;
- case CC_DISPLAY_PARTICLE:
- displayData = new cc.ParticleDisplayData();
- displayData.plist = this._basefilePath + json[cc.CONST_A_PLIST] || "";
- break;
- default:
- displayData = new cc.SpriteDisplayData();
- break;
- }
-
- displayData.displayType = displayType;
-
- return displayData;
-};
-
-cc.DataReaderHelper.decodeAnimationFromJson = function (json) {
- var aniData = new cc.AnimationData();
- aniData.name = json[cc.CONST_A_NAME] || "";
- var movementDataList = json[cc.CONST_MOVEMENT_DATA] || [];
- for (var i = 0; i < movementDataList.length; i++) {
- aniData.addMovement(this.decodeMovementFromJson(movementDataList[i]));
- }
- return aniData;
-};
-
-cc.DataReaderHelper.decodeMovementFromJson = function (json) {
- var movementData = new cc.MovementData();
-
- movementData.loop = json[cc.CONST_A_LOOP] || false;
- movementData.durationTween = json[cc.CONST_A_DURATION_TWEEN] || 0;
- movementData.durationTo = json[cc.CONST_A_DURATION_TO] || 0;
- movementData.duration = json[cc.CONST_A_DURATION] || 0;
- movementData.scale = json[cc.CONST_A_MOVEMENT_SCALE] || 1;
- movementData.tweenEasing = json[cc.CONST_A_TWEEN_EASING] || cc.TweenType.Linear;
- movementData.name = json[cc.CONST_A_NAME] || "";
-
- var movementBoneList = json[cc.CONST_MOVEMENT_BONE_DATA] || [];
- for (var i = 0; i < movementBoneList.length; i++) {
- movementData.addMovementBoneData(this.decodeMovementBoneFromJson(movementBoneList[i]));
- }
- return movementData;
-};
-
-cc.DataReaderHelper.decodeMovementBoneFromJson = function (json) {
- var movementBoneData = new cc.MovementBoneData();
- movementBoneData.delay = json[cc.CONST_A_MOVEMENT_DELAY] || 0;
- movementBoneData.scale = json[cc.CONST_A_MOVEMENT_SCALE] || 1;
-
- movementBoneData.name = json[cc.CONST_A_NAME] || "";
- var frameDataList = json[cc.CONST_FRAME_DATA] || [];
- for (var i = 0; i < frameDataList.length; i++) {
- var frameData = this.decodeFrameFromJson(frameDataList[i]);
- movementBoneData.addFrameData(frameData);
- if (this._cocoStudioVersion < cc.CONST_VERSION_COMBINED) {
- frameData.frameID = movementBoneData.duration;
- movementBoneData.duration += frameData.duration;
- }
- }
- if (this._cocoStudioVersion < cc.CONST_VERSION_COMBINED) {
- if (movementBoneData.frameList.length > 0) {
- var frameData = new cc.FrameData();
- frameData.copy(movementBoneData.frameList[movementBoneData.frameList.length - 1]);
- movementBoneData.addFrameData(frameData);
- frameData.frameID = movementBoneData.duration;
- }
- }
- return movementBoneData;
-};
-
-cc.DataReaderHelper.decodeFrameFromJson = function (json) {
- var frameData = new cc.FrameData();
- this.decodeNodeFromJson(frameData, json);
- frameData.duration = json[cc.CONST_A_DURATION] || 0;
- frameData.tweenEasing = json[cc.CONST_A_TWEEN_EASING] || cc.TweenType.Linear;
- frameData.displayIndex = json[cc.CONST_A_DISPLAY_INDEX] || 0;
- frameData.blendType = json[cc.CONST_A_BLEND_TYPE] || 0;
- frameData.event = json[cc.CONST_A_EVENT] || null;
- if (this._cocoStudioVersion < cc.CONST_VERSION_COMBINED)
- frameData.duration = json[cc.CONST_A_DURATION] || 0;
- else
- frameData.frameID = json[cc.CONST_A_FRAME_INDEX] || 0;
- return frameData;
-};
-
-cc.DataReaderHelper.decodeTextureFromJson = function (json) {
- var textureData = new cc.TextureData();
- textureData.name = json[cc.CONST_A_NAME] || "";
- textureData.width = json[cc.CONST_A_WIDTH] || 0;
- textureData.height = json[cc.CONST_A_HEIGHT] || 0;
- textureData.pivotX = json[cc.CONST_A_PIVOT_X] || 0;
- textureData.pivotY = json[cc.CONST_A_PIVOT_Y] || 0;
-
- var contourDataList = json[cc.CONST_CONTOUR_DATA] || [];
- for (var i = 0; i < contourDataList.length; i++) {
- textureData.contourDataList.push(this.decodeContourFromJson(contourDataList[i]));
- }
- return textureData;
-};
-
-cc.DataReaderHelper.decodeContourFromJson = function (json) {
- var contourData = new cc.ContourData();
- var vertexPointList = json[cc.CONST_VERTEX_POINT] || [];
- for (var i = 0; i < vertexPointList.length; i++) {
- var dic = vertexPointList[i];
- var vertex = cc.p(0, 0);
- vertex.x = dic[cc.CONST_A_X] || 0;
- vertex.y = dic[cc.CONST_A_Y] || 0;
- contourData.vertexList.push(vertex);
- }
- return contourData;
-};
-
-cc.DataReaderHelper.decodeNodeFromJson = function (node, json) {
- node.x = (json[cc.CONST_A_X] || 0) * this._positionReadScale;
- node.y = (json[cc.CONST_A_Y] || 0) * this._positionReadScale;
- node.zOrder = json[cc.CONST_A_Z] || 0;
-
- node.skewX = json[cc.CONST_A_SKEW_X] || 0;
- node.skewY = json[cc.CONST_A_SKEW_Y] || 0;
- node.scaleX = json[cc.CONST_A_SCALE_X] || 1;
- node.scaleY = json[cc.CONST_A_SCALE_Y] || 1;
-
- var colorDic = json[cc.CONST_COLOR_INFO] || null;
- if (colorDic) {
- node.a = colorDic[cc.CONST_A_ALPHA] || 255;
- node.r = colorDic[cc.CONST_A_RED] || 255;
- node.g = colorDic[cc.CONST_A_GREEN] || 255;
- node.b = colorDic[cc.CONST_A_BLUE] || 255;
- node.isUseColorInfo = true;
- delete colorDic;
- }
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/utils/CCTransformHelp.js b/extensions/CocoStudio/Armature/utils/CCTransformHelp.js
deleted file mode 100644
index 5cd4887b90..0000000000
--- a/extensions/CocoStudio/Armature/utils/CCTransformHelp.js
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.TransformHelp = {};
-
-cc.TransformHelp.helpMatrix1 = cc.AffineTransformMake(1, 0, 0, 1, 0, 0);
-cc.TransformHelp.helpMatrix2 = cc.AffineTransformMake(1, 0, 0, 1, 0, 0);
-cc.TransformHelp.helpPoint1 = cc.p(0, 0);
-cc.TransformHelp.helpPoint2 = cc.p(0, 0);
-
-/**
- * @function
- * @param {cc.BaseData} bone
- * @return {cc.AffineTransform}
- * Constructor
- */
-cc.TransformHelp.transformFromParent = function (bone, parentBone) {
- this.nodeToMatrix(bone, this.helpMatrix1);
- this.nodeToMatrix(parentBone, this.helpMatrix2);
-
- this.helpMatrix2 = cc.AffineTransformInvert(this.helpMatrix2);
- this.helpMatrix1 = cc.AffineTransformConcat(this.helpMatrix1, this.helpMatrix2);
-
- this.matrixToNode(this.helpMatrix1, bone);
-};
-
-/**
- * @function
- * @param {cc.BaseData} node
- * @param {cc.AffineTransform} matrix
- */
-cc.TransformHelp.nodeToMatrix = function (node, matrix) {
- matrix.a = node.scaleX * Math.cos(node.skewY);
- matrix.b = node.scaleX * Math.sin(node.skewY);
- matrix.c = node.scaleY * Math.sin(node.skewX);
- matrix.d = node.scaleY * Math.cos(node.skewY);
- matrix.tx = node.x;
- matrix.ty = node.y;
-};
-
-/**
- * @function
- * @param {cc.AffineTransform} matrix
- * @param {cc.BaseData} node
- */
-cc.TransformHelp.matrixToNode = function (matrix, node) {
- /*
- * In as3 language, there is a function called "deltaTransformPoint", it calculate a point used give Transform
- * but not used the tx, ty value. we simulate the function here
- */
- this.helpPoint1.x = 0;
- this.helpPoint1.y = 1;
- this.helpPoint1 = cc.PointApplyAffineTransform(this.helpPoint1, matrix);
- this.helpPoint1.x -= matrix.tx;
- this.helpPoint1.y -= matrix.ty;
-
- this.helpPoint2.x = 1;
- this.helpPoint2.y = 0;
- this.helpPoint2 = cc.PointApplyAffineTransform(this.helpPoint2, matrix);
- this.helpPoint2.x -= matrix.tx;
- this.helpPoint2.y -= matrix.ty;
-
- node.skewX = -(Math.atan2(this.helpPoint1.y, this.helpPoint1.x) - 1.5707964); //todo
- //node.skewX = -Math.atan2(this.helpPoint2.y, this.helpPoint2.x);
- node.skewY = Math.atan2(this.helpPoint2.y, this.helpPoint2.x);
- node.scaleX = Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b);
- node.scaleY = Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d);
- node.x = matrix.tx;
- node.y = matrix.ty;
-};
-
-/**
- * @function
- * @param {cc.BaseData} target
- * @param {cc.BaseData} source
- */
-cc.TransformHelp.nodeConcat = function (target, source) {
- target.x += source.x;
- target.y += source.y;
- target.skewX += source.skewX;
- target.skewY += source.skewY;
- target.scaleX += source.scaleX;
- target.scaleY += source.scaleY;
-};
-
-/**
- * @function
- * @param {cc.BaseData} target
- * @param {cc.BaseData} source
- */
-cc.TransformHelp.nodeSub = function (target, source) {
- target.x -= source.x;
- target.y -= source.y;
- target.skewX -= source.skewX;
- target.skewY -= source.skewY;
- target.scaleX -= source.scaleX;
- target.scaleY -= source.scaleY;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/utils/CCTweenFunction.js b/extensions/CocoStudio/Armature/utils/CCTweenFunction.js
deleted file mode 100644
index ecce67417e..0000000000
--- a/extensions/CocoStudio/Armature/utils/CCTweenFunction.js
+++ /dev/null
@@ -1,367 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.TweenType = {
- TWEEN_EASING_MIN:-1,
- Linear:0,
-
- Sine_EaseIn:1,
- Sine_EaseInOut:2,
- Sine_EaseOut:3,
-
-
- Quad_EaseIn:4,
- Quad_EaseOut:5,
- Quad_EaseInOut:6,
-
- Cubic_EaseIn:7,
- Cubic_EaseOut:8,
- Cubic_EaseInOut:9,
-
- Quart_EaseIn:10,
- Quart_EaseOut:11,
- Quart_EaseInOut:12,
-
- Quint_EaseIn:13,
- Quint_EaseOut:14,
- Quint_EaseInOut:15,
-
- Expo_EaseIn:16,
- Expo_EaseOut:17,
- Expo_EaseInOut:18,
-
- Circ_EaseIn:19,
- Circ_EaseOut:20,
- Circ_EaseInOut:21,
-
- Elastic_EaseIn:22,
- Elastic_EaseOut:23,
- Elastic_EaseInOut:24,
-
- Back_EaseIn:25,
- Back_EaseOut:26,
- Back_EaseInOut:27,
-
- Bounce_EaseIn:28,
- Bounce_EaseOut:29,
- Bounce_EaseInOut:30,
-
- TWEEN_EASING_MAX:10000
-};
-
-cc.TweenFunction = cc.TweenFunction || {};
-
-cc.TweenFunction.tweenTo = function (from, change, time, duration, tweenType) {
- var delta = 0;
-
- switch (tweenType) {
- case cc.TweenType.Linear:
- delta = this.linear(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Sine_EaseIn:
- delta = this.sineEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Sine_EaseOut:
- delta = this.sineEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Sine_EaseInOut:
- delta = this.sineEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Quad_EaseIn:
- delta = this.quadEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Quad_EaseOut:
- delta = this.quadEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Quad_EaseInOut:
- delta = this.quadEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Cubic_EaseIn:
- delta = this.cubicEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Cubic_EaseOut:
- delta = this.cubicEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Cubic_EaseInOut:
- delta = this.cubicEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Quart_EaseIn:
- delta = this.quartEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Quart_EaseOut:
- delta = this.quartEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Quart_EaseInOut:
- delta = this.quartEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Quint_EaseIn:
- delta = this.quintEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Quint_EaseOut:
- delta = this.quintEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Quint_EaseInOut:
- delta = this.quintEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Expo_EaseIn:
- delta = this.expoEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Expo_EaseOut:
- delta = this.expoEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Expo_EaseInOut:
- delta = this.expoEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Circ_EaseIn:
- delta = this.circEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Circ_EaseOut:
- delta = this.circEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Circ_EaseInOut:
- delta = this.circEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Elastic_EaseIn:
- delta = this.elasticEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Elastic_EaseOut:
- delta = this.elasticEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Elastic_EaseInOut:
- delta = this.elasticEaseInOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Back_EaseIn:
- delta = this.backEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Back_EaseOut:
- delta = this.backEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Back_EaseInOut:
- delta = this.backEaseInOut(time, 0, 1, duration);
- break;
-
- case cc.TweenType.Bounce_EaseIn:
- delta = this.bounceEaseIn(time, 0, 1, duration);
- break;
- case cc.TweenType.Bounce_EaseOut:
- delta = this.bounceEaseOut(time, 0, 1, duration);
- break;
- case cc.TweenType.Bounce_EaseInOut:
- delta = this.bounceEaseInOut(time, 0, 1, duration);
- break;
-
- default:
- delta = this.sineEaseInOut(time, 0, 1, duration);
- break;
- }
-
- return delta;
-};
-
-cc.TweenFunction.linear = function (t, b, c, d) {
- return c * t / d + b;
-};
-
-cc.TweenFunction.quadEaseIn = function (t, b, c, d) {
- return c * (t /= d) * t + b;
-};
-cc.TweenFunction.quadEaseOut = function (t, b, c, d) {
- return -c * (t /= d) * (t - 2) + b;
-};
-cc.TweenFunction.quadEaseInOut = function (t, b, c, d) {
- if ((t /= d / 2) < 1)
- return c / 2 * t * t + b;
- return -c / 2 * ((--t) * (t - 2) - 1) + b;
-};
-
-cc.TweenFunction.cubicEaseIn = function (t, b, c, d) {
- return c * (t /= d) * t * t + b;
-};
-cc.TweenFunction.cubicEaseOut = function (t, b, c, d) {
- return c * (( t = t / d - 1) * t * t + 1) + b;
-};
-cc.TweenFunction.cubicEaseInOut = function (t, b, c, d) {
- if ((t /= d / 2) < 1)
- return c / 2 * t * t * t + b;
- return c / 2 * ((t -= 2) * t * t + 2) + b;
-};
-
-cc.TweenFunction.quartEaseIn = function (t, b, c, d) {
- return c * (t /= d) * t * t * t + b;
-};
-cc.TweenFunction.quartEaseOut = function (t, b, c, d) {
- return -c * (( t = t / d - 1) * t * t * t - 1) + b;
-};
-cc.TweenFunction.quartEaseInOut = function (t, b, c, d) {
- if ((t /= d / 2) < 1)
- return c / 2 * t * t * t * t + b;
- return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
-};
-
-cc.TweenFunction.quintEaseIn = function (t, b, c, d) {
- return c * (t /= d) * t * t * t * t + b;
-};
-cc.TweenFunction.quintEaseOut = function (t, b, c, d) {
- return c * (( t = t / d - 1) * t * t * t * t + 1) + b;
-};
-cc.TweenFunction.quintEaseInOut = function (t, b, c, d) {
- if ((t /= d / 2) < 1)
- return c / 2 * t * t * t * t * t + b;
- return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
-};
-
-cc.TweenFunction.sineEaseIn = function (t, b, c, d) {
- return -c * Math.cos(t / d * (cc.PI / 2)) + c + b;
-};
-cc.TweenFunction.sineEaseOut = function (t, b, c, d) {
- return c * Math.sin(t / d * (cc.PI / 2)) + b;
-};
-cc.TweenFunction.sineEaseInOut = function (t, b, c, d) {
- return -c / 2 * (Math.cos(cc.PI * t / d) - 1) + b;
-};
-
-cc.TweenFunction.expoEaseIn = function (t, b, c, d) {
- return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
-};
-cc.TweenFunction.expoEaseOut = function (t, b, c, d) {
- return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
-};
-cc.TweenFunction.expoEaseInOut = function (t, b, c, d) {
- if (t == 0)
- return b;
- if (t == d)
- return b + c;
- if ((t /= d / 2) < 1)
- return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
- return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
-};
-
-cc.TweenFunction.circEaseIn = function (t, b, c, d) {
- return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
-};
-cc.TweenFunction.circEaseOut = function (t, b, c, d) {
- return c * Math.sqrt(1 - ( t = t / d - 1) * t) + b;
-};
-cc.TweenFunction.circEaseInOut = function (t, b, c, d) {
- if ((t /= d / 2) < 1)
- return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
- return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
-};
-
-cc.TweenFunction.elasticEaseIn = function (t, b, c, d, a, p) {
- var s = 0;
- if (t == 0)
- return b;
- if ((t /= d) == 1)
- return b + c;
- if (!p)
- p = d * .3;
- if (!a || a < Math.abs(c)) {
- a = c;
- s = p / 4;
- } else
- s = p / (2 * cc.PI) * Math.asin(c / a);
- return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * cc.PI) / p)) + b;
-};
-cc.TweenFunction.elasticEaseOut = function (t, b, c, d, a, p) {
- var s = 0;
- if (t == 0)
- return b;
- if ((t /= d) == 1)
- return b + c;
- if (!p)
- p = d * .3;
- if (!a || a < Math.abs(c)) {
- a = c;
- s = p / 4;
- } else
- s = p / (2 * cc.PI) * Math.asin(c / a);
- return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * cc.PI) / p) + c + b);
-};
-cc.TweenFunction.elasticEaseInOut = function (t, b, c, d, a, p) {
- var s = 0;
- if (t == 0)
- return b;
- if ((t /= d / 2) == 2)
- return b + c;
- if (!p)
- p = d * (.3 * 1.5);
- if (!a || a < Math.abs(c)) {
- a = c;
- s = p / 4;
- } else
- s = p / (2 * cc.PI) * Math.asin(c / a);
- if (t < 1)
- return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * cc.PI) / p)) + b;
- return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * cc.PI) / p) * .5 + c + b;
-};
-
-cc.TweenFunction.backEaseIn = function (t, b, c, d, s) {
- if (s == 0)
- s = 1.70158;
- return c * (t /= d) * t * ((s + 1) * t - s) + b;
-};
-cc.TweenFunction.backEaseOut = function (t, b, c, d, s) {
- if (s == 0)
- s = 1.70158;
- return c * (( t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
-};
-cc.TweenFunction.backEaseInOut = function (t, b, c, d, s) {
- if (s == 0)
- s = 1.70158;
- if ((t /= d / 2) < 1)
- return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
- return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
-};
-
-cc.TweenFunction.bounceEaseIn = function (t, b, c, d) {
- return c - this.bounceEaseOut(d - t, 0, c, d) + b;
-};
-
-cc.TweenFunction.bounceEaseOut = function (t, b, c, d) {
- if ((t /= d) < (1 / 2.75)) {
- return c * (7.5625 * t * t) + b;
- } else if (t < (2 / 2.75)) {
- return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
- } else if (t < (2.5 / 2.75)) {
- return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
- } else {
- return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
- }
-};
-
-cc.TweenFunction.bounceEaseInOut = function (t, b, c, d) {
- if (t < d / 2)
- return this.bounceEaseIn(t * 2, 0, c, d) * .5 + b;
- else
- return this.bounceEaseOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js b/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js
deleted file mode 100644
index 69406e93c0..0000000000
--- a/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js
+++ /dev/null
@@ -1,245 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * format and manage armature configuration and armature animation
- * @class
- * @extends cc.Class
- */
-cc.ArmatureDataManager = cc.Class.extend({
- _animationDatas:null,
- _armarureDatas:null,
- _textureDatas:null,
- ctor:function () {
- this._animationDatas = {};
- this._armarureDatas = {};
- this._textureDatas = {};
- },
- init:function () {
-
- },
-
- /**
- * Add armature data
- * @param {string} id The id of the armature data
- * @param {cc.ArmatureData} armatureData
- */
- addArmatureData:function (id, armatureData) {
- if (this._armarureDatas) {
- this._armarureDatas[id] = armatureData;
- }
- },
-
- /**
- * remove armature data
- * @param {string} id
- */
- removeArmatureData:function(id){
- if (this._armarureDatas.hasOwnProperty(id))
- delete this._armarureDatas[id];
- },
-
- /**
- * get armatureData by id
- * @param {String} id
- * @return {cc.ArmatureData}
- */
- getArmatureData:function (id) {
- var armatureData = null;
- if (this._armarureDatas) {
- armatureData = this._armarureDatas[id];
- }
- return armatureData;
- },
-
- /**
- * get armatureDatas
- * @return {Object}
- */
- getArmatureDatas:function () {
- return this._armarureDatas;
- },
-
- /**
- * add animation data
- * @param {String} id
- * @param {cc.AnimationData} animationData
- */
- addAnimationData:function (id, animationData) {
- if (this._animationDatas) {
- this._animationDatas[id] = animationData;
- }
- },
-
- /**
- * remove animation data
- * @param {string} id
- */
- removeAnimationData:function(id){
- if (this._animationDatas.hasOwnProperty(id))
- delete this._animationDatas[id];
- },
-
- /**
- * get animationData by id
- * @param {String} id
- * @return {cc.AnimationData}
- */
- getAnimationData:function (id) {
- var animationData = null;
- if (this._animationDatas[id]) {
- animationData = this._animationDatas[id];
- }
- return animationData;
- },
-
- /**
- * get animationDatas
- * @return {Object}
- */
- getAnimationDatas:function () {
- return this._animationDatas;
- },
-
- /**
- * add texture data
- * @param {String} id
- * @param {cc.TextureData} textureData
- */
- addTextureData:function (id, textureData) {
- if (this._textureDatas) {
- this._textureDatas[id] = textureData;
- }
- },
-
- /**
- * remove texture data
- * @param {string} id
- */
- removeTextureData:function(id){
- if (this._textureDatas.hasOwnProperty(id))
- delete this._textureDatas[id];
- },
-
- /**
- * get textureData by id
- * @param {String} id
- * @return {cc.TextureData}
- */
- getTextureData:function (id) {
- var textureData = null;
- if (this._textureDatas) {
- textureData = this._textureDatas[id];
- }
- return textureData;
- },
-
- /**
- * get textureDatas
- * @return {Object}
- */
- getTextureDatas:function () {
- return this._textureDatas;
- },
-
- /**
- * Add ArmatureFileInfo, it is managed by CCArmatureDataManager.
- * @param {String} imagePath
- * @param {String} plistPath
- * @param {String} configFilePath
- */
- addArmatureFileInfo:function (/*imagePath,plistPath,configFilePath*/) {
- var imagePath,plistPath,configFilePath;
- var isLoadSpriteFrame = false;
- if (arguments.length == 1) {
- configFilePath = arguments[0];
- isLoadSpriteFrame = true;
- } else if (arguments.length == 3){
- imagePath = arguments[0];
- plistPath = arguments[1];
- configFilePath = arguments[2];
- this.addSpriteFrameFromFile(plistPath, imagePath);
- }
- cc.DataReaderHelper.addDataFromFile(configFilePath,isLoadSpriteFrame);
- },
-
- /**
- * Add ArmatureFileInfo, it is managed by CCArmatureDataManager.
- * @param {String} imagePath
- * @param {String} plistPath
- * @param {String} configFilePath
- * @param {Object} target
- * @param {Function} configFilePath
- */
- addArmatureFileInfoAsync:function (/*imagePath, plistPath, configFilePath,target,selector*/) {
- var imagePath, plistPath, configFilePath,target,selector;
- var isLoadSpriteFrame = false;
- if (arguments.length == 3) {
- configFilePath = arguments[0];
- target = arguments[1];
- selector = arguments[2];
- isLoadSpriteFrame = true;
- } else if (arguments.length == 5){
- imagePath = arguments[0];
- plistPath = arguments[1];
- configFilePath = arguments[2];
- target = arguments[3];
- selector = arguments[4];
- this.addSpriteFrameFromFile(plistPath, imagePath);
- }
-
- cc.DataReaderHelper.addDataFromFileAsync(configFilePath,target,selector,isLoadSpriteFrame);
-
- },
-
- /**
- * Add sprite frame to CCSpriteFrameCache, it will save display name and it's relative image name
- * @param {String} plistPath
- * @param {String} imagePath
- */
- addSpriteFrameFromFile:function (plistPath, imagePath) {
- cc.SpriteFrameCacheHelper.getInstance().addSpriteFrameFromFile(plistPath, imagePath);
- },
-
- removeAll:function () {
- this._animationDatas = null;
- this._armarureDatas = null;
- this._textureDatas = null;
- cc.DataReaderHelper.clear();
- }
-});
-
-cc.ArmatureDataManager._instance = null;
-cc.ArmatureDataManager.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.ArmatureDataManager();
- this._instance.init();
- }
- return this._instance;
-};
-cc.ArmatureDataManager.purge = function () {
- cc.SpriteFrameCacheHelper.purge();
- cc.DataReaderHelper.clear();
- this._instance = null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Components/CCComAudio.js b/extensions/CocoStudio/Components/CCComAudio.js
deleted file mode 100644
index 21dfdb1d80..0000000000
--- a/extensions/CocoStudio/Components/CCComAudio.js
+++ /dev/null
@@ -1,167 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.ComAudio
- * @class
- * @extends cc.Component
- */
-cc.ComAudio = cc.Component.extend({
- _filePath: "",
- _loop: false,
- ctor: function () {
- cc.Component.prototype.ctor.call(this);
- this._name = "Audio";
- },
- init: function () {
- return true;
- },
-
- onEnter: function () {
- },
-
- onExit: function () {
- this.stopBackgroundMusic(true);
- this.stopAllEffects();
- },
-
- isEnabled: function () {
- return this._enabled;
- },
-
- setEnabled: function (bool) {
- this._enabled = bool;
- },
-
- end: function () {
- cc.AudioEngine.end();
- },
-
- preloadBackgroundMusic: function (pszFilePath) {
- cc.AudioEngine.getInstance().preloadMusic(pszFilePath);
- },
-
- playBackgroundMusic: function (pszFilePath, loop) {
- cc.AudioEngine.getInstance().playMusic(pszFilePath, loop);
- },
-
- stopBackgroundMusic: function (releaseData) {
- cc.AudioEngine.getInstance().stopMusic(releaseData);
- },
-
- pauseBackgroundMusic: function () {
- cc.AudioEngine.getInstance().pauseMusic();
- },
-
- resumeBackgroundMusic: function () {
- cc.AudioEngine.getInstance().resumeMusic();
- },
-
- rewindBackgroundMusic: function () {
- cc.AudioEngine.getInstance().rewindMusic();
- },
-
- willPlayBackgroundMusic: function () {
- return cc.AudioEngine.getInstance().willPlayMusic();
- },
-
- isBackgroundMusicPlaying: function () {
- return cc.AudioEngine.getInstance().isMusicPlaying();
- },
-
- getBackgroundMusicVolume: function () {
- return cc.AudioEngine.getInstance().getMusicVolume();
- },
-
- setBackgroundMusicVolume: function (volume) {
- cc.AudioEngine.getInstance().setMusicVolume(volume);
- },
-
- getEffectsVolume: function () {
- return cc.AudioEngine.getInstance().getEffectsVolume();
- },
-
- setEffectsVolume: function (volume) {
- cc.AudioEngine.getInstance().setEffectsVolume(volume);
- },
-
- playEffect: function (pszFilePath, loop) {
- return cc.AudioEngine.getInstance().playEffect(pszFilePath, loop);
- },
-
- pauseEffect: function (soundId) {
- cc.AudioEngine.getInstance().pauseEffect(soundId);
- },
-
- pauseAllEffects: function () {
- cc.AudioEngine.getInstance().pauseAllEffects();
- },
-
- resumeEffect: function (soundId) {
- cc.AudioEngine.getInstance().resumeEffect(soundId);
- },
-
- resumeAllEffects: function () {
- cc.AudioEngine.getInstance().resumeAllEffects();
- },
-
- stopEffect: function (soundId) {
- cc.AudioEngine.getInstance().stopEffect(soundId);
- },
-
- stopAllEffects: function () {
- cc.AudioEngine.getInstance().stopAllEffects();
- },
-
- preloadEffect: function (pszFilePath) {
- cc.AudioEngine.getInstance().preloadEffect(pszFilePath);
- },
-
- unloadEffect: function (pszFilePath) {
- cc.AudioEngine.getInstance().unloadEffect(pszFilePath);
- },
-
- setFile: function (pszFilePath) {
- this._filePath = pszFilePath;
- },
-
- setLoop: function (loop) {
- this._loop = loop;
- },
-
- getFile: function () {
- return this._filePath;
- },
-
- isLoop: function () {
- return this._loop;
- }
-});
-cc.ComAudio.create = function () {
- var com = new cc.ComAudio();
- if (com && com.init()) {
- return com;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Components/CCComController.js b/extensions/CocoStudio/Components/CCComController.js
deleted file mode 100644
index 975a3fbdba..0000000000
--- a/extensions/CocoStudio/Components/CCComController.js
+++ /dev/null
@@ -1,480 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.ComController
- * @class
- * @extends cc.Component
- */
-cc.ComController = cc.Component.extend({
- ctor: function () {
- cc.Component.prototype.ctor.call(this);
- this._name = "ComAttribute";
- },
- init: function () {
- return true;
- },
-
- onEnter: function () {
-
- },
-
- onExit: function () {
- var director = cc.Director.getInstance();
- if (this._isTouchEnabled)
- cc.unregisterTouchDelegate(this);
-
- // remove this layer from the delegates who concern Accelerometer Sensor
- if (this._isAccelerometerEnabled)
- director.getAccelerometer().setDelegate(null);
-
- // remove this layer from the delegates who concern the kaypad msg
- if (this._isKeyboardEnabled)
- director.getKeyboardDispatcher().removeDelegate(this);
-
- if (this._isMouseEnabled)
- director.getMouseDispatcher().removeMouseDelegate(this);
- },
-
- update: function (dt) {
- },
-
- isEnabled: function () {
- return this._enabled;
- },
-
- setEnabled: function (bool) {
- this._enabled = b;
- },
- /**
- * If isTouchEnabled, this method is called onEnter.
- */
- registerWithTouchDispatcher:function () {
- if (this._touchMode === cc.TOUCH_ALL_AT_ONCE)
- cc.registerStandardDelegate(this,this._touchPriority);
- else
- cc.registerTargetedDelegate(this._touchPriority, true, this);
- },
-
- isMouseEnabled:function () {
- return this._isMouseEnabled;
- },
-
- setMouseEnabled:function (enabled) {
- if (this._isMouseEnabled != enabled) {
- this._isMouseEnabled = enabled;
- if (this._running) {
- if (enabled)
- cc.Director.getInstance().getMouseDispatcher().addMouseDelegate(this, this._mousePriority);
- else
- cc.Director.getInstance().getMouseDispatcher().removeMouseDelegate(this);
- }
- }
- },
-
- setMousePriority:function (priority) {
- if (this._mousePriority !== priority) {
- this._mousePriority = priority;
- // Update touch priority with handler
- if (this._isMouseEnabled) {
- this.setMouseEnabled(false);
- this.setMouseEnabled(true);
- }
- }
- },
-
- getMousePriority:function () {
- return this._mousePriority;
- },
-
- /**
- * whether or not it will receive Touch events.
- * You can enable / disable touch events with this property.
- * Only the touches of this node will be affected. This "method" is not propagated to it's children.
- * @return {Boolean}
- */
- isTouchEnabled:function () {
- return this._isTouchEnabled;
- },
-
- /**
- * Enable touch events
- * @param {Boolean} enabled
- */
- setTouchEnabled:function (enabled) {
- if (this._isTouchEnabled !== enabled) {
- this._isTouchEnabled = enabled;
- if (enabled) {
- this.registerWithTouchDispatcher();
- } else {
- // have problems?
- cc.unregisterTouchDelegate(this);
- }
- }
- },
-
- /** returns the priority of the touch event handler
- * @return {Number}
- */
- getTouchPriority:function () {
- return this._touchPriority;
- },
-
- /** Sets the touch event handler priority. Default is 0.
- * @param {Number} priority
- */
- setTouchPriority:function (priority) {
- if (this._touchPriority !== priority) {
- this._touchPriority = priority;
- // Update touch priority with handler
- if (this._isTouchEnabled) {
- this.setTouchEnabled(false);
- this.setTouchEnabled(true);
- }
- }
- },
-
- /** returns the touch mode.
- * @return {Number}
- */
- getTouchMode:function () {
- return this._touchMode;
- },
-
- /** Sets the touch mode.
- * @param {Number} mode
- */
- setTouchMode:function (mode) {
- if (this._touchMode !== mode) {
- this._touchMode = mode;
- // update the mode with handler
- if (this._isTouchEnabled) {
- this.setTouchEnabled(false);
- this.setTouchEnabled(true);
- }
- }
- },
-
- /**
- * whether or not it will receive Accelerometer events
- * You can enable / disable accelerometer events with this property.
- * @return {Boolean}
- */
- isAccelerometerEnabled:function () {
- return this._isAccelerometerEnabled;
- },
-
- /**
- * isAccelerometerEnabled setter
- * @param {Boolean} enabled
- */
- setAccelerometerEnabled:function (enabled) {
- if (enabled !== this._isAccelerometerEnabled) {
- this._isAccelerometerEnabled = enabled;
-
- if (this._running) {
- var director = cc.Director.getInstance();
- if (enabled) {
- director.getAccelerometer().setDelegate(this);
- } else {
- director.getAccelerometer().setDelegate(null);
- }
- }
- }
- },
-
- /**
- * accelerometerInterval setter
- * @param {Number} interval
- */
- setAccelerometerInterval:function (interval) {
- if (this._isAccelerometerEnabled) {
- cc.Director.getInstance().getAccelerometer().setAccelerometerInterval(interval);
- }
- },
-
- onAccelerometer:function (accelerationValue) {
- cc.Assert(false, "Layer#onAccelerometer override me");
- },
-
- /**
- * whether or not it will receive keyboard events
- * You can enable / disable accelerometer events with this property.
- * it's new in cocos2d-x
- * @return {Boolean}
- */
- isKeyboardEnabled:function () {
- return this._isKeyboardEnabled;
- },
-
- /**
- * Enable Keyboard interaction
- * @param {Boolean} enabled
- */
- setKeyboardEnabled:function (enabled) {
- if (enabled !== this._isKeyboardEnabled) {
- this._isKeyboardEnabled = enabled;
- if (this._running) {
- var director = cc.Director.getInstance();
- if (enabled) {
- director.getKeyboardDispatcher().addDelegate(this);
- } else {
- director.getKeyboardDispatcher().removeDelegate(this);
- }
- }
- }
- },
-
- // ---------------------CCTouchDelegate interface------------------------------
-
- /**
- * default implements are used to call script callback if exist
- * you must override these touch functions if you wish to utilize them
- * @param {cc.Touch} touch
- * @param {event} event
- * @return {Boolean}
- */
- onTouchBegan:function (touch, event) {
- return true;
- },
-
- /**
- * callback when a touch event moved
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchMoved:function (touch, event) {
- },
-
- /**
- * callback when a touch event finished
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchEnded:function (touch, event) {
- },
-
- /**
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchCancelled:function (touch, event) {
- },
-
- /**
- * Touches is the same as Touch, except this one can handle multi-touch
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchesBegan:function (touch, event) {
- },
-
- /**
- * when a touch moved
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchesMoved:function (touch, event) {
- },
-
- /**
- * when a touch finished
- * @param {cc.Touch} touch
- * @param {event} event
- */
- onTouchesEnded:function (touch, event) {
- },
-
- /**
- * @param touch
- * @param event
- */
- onTouchesCancelled:function (touch, event) {
- },
-
- // ---------------------CCMouseEventDelegate interface------------------------------
-
- /**
- * called when the "mouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseMoved" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseMoved:function (event) {
- return false;
- },
-
- /**
- * called when the "mouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onMouseUp:function (event) {
- return false;
- },
-
- //right
- /**
- * called when the "rightMouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onRightMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "rightMouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onRightMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "rightMouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onRightMouseUp:function (event) {
- return false;
- },
-
- //other
- /**
- * called when the "otherMouseDown" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onOtherMouseDown:function (event) {
- return false;
- },
-
- /**
- * called when the "otherMouseDragged" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onOtherMouseDragged:function (event) {
- return false;
- },
-
- /**
- * called when the "otherMouseUp" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onOtherMouseUp:function (event) {
- return false;
- },
-
- //scroll wheel
- /**
- * called when the "scrollWheel" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param event
- * @return {Boolean}
- */
- onScrollWheel:function (event) {
- return false;
- },
-
- // enter / exit
- /**
- * called when the "mouseEntered" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param theEvent
- * @return {Boolean}
- */
- onMouseEntered:function (theEvent) {
- return false;
- },
-
- /**
- * called when the "mouseExited" event is received.
- * Return YES to avoid propagating the event to other delegates.
- * @param theEvent
- * @return {Boolean}
- */
- onMouseExited:function (theEvent) {
- return false;
- },
-
- // ---------------------CCKeyboardDelegate interface------------------------------
-
- /**
- * Call back when a key is pressed down
- * @param {Number} keyCode
- * @example
- * // example
- * if(keyCode == cc.KEY.w){}
- */
- onKeyDown:function (keyCode) {
- },
-
- /**
- * Call back when a key is released
- * @param {Number} keyCode
- * @example
- * // example
- * if(keyCode == cc.KEY.w){}
- */
- onKeyUp:function (keyCode) {
- }
-});
-cc.ComController.create = function () {
- var com = new cc.ComController();
- if (com && com.init()) {
- return com;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/BaseClasses/UIWidget.js b/extensions/CocoStudio/GUI/BaseClasses/UIWidget.js
deleted file mode 100644
index 13697f7701..0000000000
--- a/extensions/CocoStudio/GUI/BaseClasses/UIWidget.js
+++ /dev/null
@@ -1,1517 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.BrightStyle = {
- NONE: -1,
- NORMAL: 0,
- HIGHLIGHT: 1
-};
-
-cc.WidgetType = {
- Widget: 0, //control
- Container: 1 //container
-};
-
-cc.TextureResType = {
- LOCAL: 0,
- PLIST: 1
-};
-
-cc.TouchEventType = {
- BEGAN: 0,
- MOVED: 1,
- ENDED: 2,
- CANCELED: 3
-};
-
-cc.SizeType = {
- ABSOLUTE: 0,
- PERCENT: 1
-};
-
-cc.PositionType = {
- ABSOLUTE: 0,
- PERCENT: 1
-};
-
-/**
- * Base class for cc.UIWidget
- * @class
- * @extends cc.Class
- */
-cc.UIWidget = cc.Class.extend({
- _enabled: true, ///< Highest control of widget
- _visible: true, ///< is this widget visible
- _bright: true, ///< is this widget bright
- _touchEnabled: false, ///< is this widget touch endabled
- _touchPassedEnabled: false, ///< is the touch event should be passed
- _focus: false, ///< is the widget on focus
- _widgetZOrder: 0, ///< z-order value that affects the draw order and touch order
- _anchorPoint: null, ///< anchor point normalized
- _widgetParent: null, ///< parent of widget
- _brightStyle: null, ///< bright style
- _updateEnabled: false, ///< is "update" method scheduled
- _renderer: null, ///< base renderer
- _touchStartPos: null, ///< touch began point
- _touchMovePos: null, ///< touch moved point
- _touchEndPos: null, ///< touch ended point
-
- _touchEventListener: null,
- _touchEventSelector: null,
-
-
- _widgetTag: -1,
- _name: "default",
- _widgetType: null,
- _actionTag: 0,
- _size: null,
- _customSize: null,
- _layoutParameterDictionary: null,
- _ignoreSize: false,
- _children: null,
- _affectByClipping: false,
-
- _scheduler: null,
-
- _sizeType: null,
- _sizePercent: null,
- _positionType: null,
- _positionPercent: null,
- _isRunning: false,
-
- ctor: function () {
- this._enabled = true;
- this._visible = true;
- this._bright = true;
- this._touchEnabled = false;
- this._touchPassedEnabled = false;
- this._focus = false;
- this._widgetZOrder = 0;
- this._anchorPoint = cc.p(0.5, 0.5);
- this._widgetParent = null;
- this._brightStyle = cc.BrightStyle.NONE;
- this._updateEnabled = false;
- this._renderer = null;
- this._touchStartPos = cc.PointZero();
- this._touchMovePos = cc.PointZero();
- this._touchEndPos = cc.PointZero();
- this._touchEventListener = null;
- this._touchEventSelector = null;
- this._widgetTag = -1;
- this._name = "default";
- this._widgetType = cc.WidgetType.Widget;
- this._actionTag = 0;
- this._size = cc.SizeZero();
- this._customSize = cc.SizeZero();
- this._layoutParameterDictionary = {};
- this._ignoreSize = false;
- this._children = [];
- this._affectByClipping = false;
- this._scheduler = null;
- this._sizeType = cc.SizeType.ABSOLUTE;
- this._sizePercent = cc.PointZero();
- this._positionType = cc.PositionType.ABSOLUTE;
- this._positionPercent = cc.PointZero();
- this._isRunning = false;
- },
-
- /**
- * initializes state of widget.
- * @returns {boolean}
- */
- init: function () {
- this._layoutParameterDictionary = {};
- this._children = [];
- this.initRenderer();
- this._renderer.setZOrder(this._widgetZOrder);
- if (this._renderer.RGBAProtocol) {
- this._renderer.setCascadeColorEnabled(true);
- this._renderer.setCascadeOpacityEnabled(true);
- }
- this.setBright(true);
- this.ignoreContentAdaptWithSize(true);
- this._scheduler = cc.Director.getInstance().getScheduler();
- return true;
- },
- /**
- * Release texture resoures of widget.
- * Release renderer.
- * If you override releaseResoures, you shall call its parent's one, e.g. UIWidget::releaseResoures().
- */
- releaseResoures: function () {
- this.setUpdateEnabled(false);
- this.removeAllChildren();
- this._children.release();
- this._renderer.removeAllChildren(true);
- this._renderer.removeFromParent(true);
- this._renderer.release();
- },
-
- onEnter: function () {
- var locChild;
- for (var i = 0; i < this._children.length; i++) {
- locChild = this._children[i];
- if (locChild instanceof cc.UIWidget)
- locChild.onEnter();
- }
- this._isRunning = true;
- this.updateSizeAndPosition();
- },
-
- onExit: function () {
- this._isRunning = false;
- var locChild;
- for (var i = 0; i < this._children.length; i++) {
- locChild = this._children[i];
- if (locChild instanceof cc.UIWidget)
- locChild.onExit();
- }
- },
-
- /**
- * Adds a child to the container.
- * @param {cc.UIWidget}child
- * @returns {boolean}
- */
- addChild: function (child) {
- if (!child) {
- return false;
- }
- if (cc.ArrayContainsObject(this._children, child)) {
- return false;
- }
- child.setParent(this);
- var childrenCount = this._children.length;
- if (childrenCount <= 0) {
- this._children.push(child);
- }
- else {
- var seekSucceed = false;
- for (var i = childrenCount - 1; i >= 0; --i) {
- var widget = this._children[i];
- if (child.getZOrder() >= widget.getZOrder()) {
- if (i == childrenCount - 1) {
- this._children.push(child);
- seekSucceed = true;
- break;
- }
- else {
- cc.ArrayAppendObjectToIndex(this._children, child, i + 1);
- seekSucceed = true;
- break;
- }
- }
- }
- if (!seekSucceed) {
- cc.ArrayAppendObjectToIndex(this._children, child, 0);
- }
- }
- child.getRenderer().setZOrder(child.getZOrder());
- this._renderer.addChild(child.getRenderer());
- if (this._isRunning) {
- child.onEnter();
- }
- return true;
- },
-
- /**
- * Adds a child to the container.
- * @param {cc.UIWidget} child
- * @returns {boolean}
- */
- removeChild: function (child) {
- if (!child) {
- return false;
- }
- if (cc.ArrayContainsObject(this._children, child)) {
- if (this._isRunning) {
- child.onExit();
- }
- child.disableUpdate();
- child.setParent(null);
- this._renderer.removeChild(child.getRenderer());
- cc.ArrayRemoveObject(this._children, child);
- return true;
- }
- return false;
- },
-
- /**
- * Removes this widget itself from its parent widget.
- * If the widget orphan, then it will destroy itself.
- */
- removeFromParent: function () {
- if (this._widgetParent) {
- this._widgetParent.removeChild(this);
- }
- },
-
- /**
- * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter.
- */
- removeAllChildren: function () {
- if (this._children.length <= 0) {
- return;
- }
- var locChild;
- for (var i = 0; i < this._children.length; ++i) {
- locChild = this._children[i];
- this.removeChild(this._children[i]);
- }
- },
-
- /**
- * Reorders a child according to a new z value.
- * @param {cc.UIWidget} child
- */
- reorderChild: function (child) {
- cc.ArrayRemoveObject(this._children, child);
- var childrenCount = this._children.length;
- if (childrenCount <= 0) {
- this._children.push(child);
- }
- else {
- var seekSucceed = false;
- var arrayChildren = this._children;
- for (var i = childrenCount - 1; i >= 0; --i) {
- var widget = arrayChildren[i];
- if (child.getZOrder() >= widget.getZOrder()) {
- if (i == childrenCount - 1) {
- this._children.push(child);
- seekSucceed = true;
- break;
- }
- else {
- cc.ArrayAppendObjectToIndex(this._children, child, i + 1);
- seekSucceed = true;
- break;
- }
- }
- }
- if (!seekSucceed) {
- cc.ArrayAppendObjectToIndex(this._children, child, 0);
- }
- }
- },
-
- /**
- * Unschedules the "update" method.
- */
- disableUpdate: function () {
- if (this._scheduler) {
- this._scheduler.unscheduleUpdateForTarget(this);
- }
- var childrenCount = this._children.length;
- var arrayChildren = this._children;
- for (var i = 0; i < childrenCount; i++) {
- var child = arrayChildren[i];
- child.disableUpdate();
- }
- },
-
- /**
- * Set enabled renderer
- * @param {Boolean} enabled
- */
- setEnabled: function (enabled) {
- this._enabled = enabled;
- this._renderer.setEnabled(enabled);
- var arrayChildren = this._children;
- var childrenCount = arrayChildren.length;
- for (var i = 0; i < childrenCount; i++) {
- var child = arrayChildren[i];
- child.setEnabled(enabled);
- }
- },
-
- /**
- * Gets a child from the container with its name
- * @param {string} name
- * @returns {cc.UIWidget}
- */
- getChildByName: function (name) {
- return cc.UIHelper.getInstance().seekWidgetByName(this, name);
- },
-
- /**
- * Gets a child from the container with its tag
- * @param {number} tag
- * @returns {cc.UIWidget}
- */
- getChildByTag: function (tag) {
- return cc.UIHelper.getInstance().seekWidgetByTag(this, tag);
- },
-
- /**
- * Return an array of children
- * @returns {Array}
- */
- getChildren: function () {
- return this._children;
- },
-
- /**
- * initializes renderer of widget.
- */
- initRenderer: function () {
- this._renderer = cc.GUIRenderer.create();
- },
-
- /**
- * Changes the size that is widget's size
- * @param {cc.Size} size
- */
- setSize: function (size) {
- this._customSize = size;
- if (this._ignoreSize) {
- this._size = this.getContentSize();
- }
- else {
- this._size.width = size.width;
- this._size.height = size.height;
- }
- if (this._isRunning) {
- this._sizePercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(this._customSize.width / this._widgetParent.getSize().width, this._customSize.height / this._widgetParent.getSize().height);
- }
- this.onSizeChanged();
- },
-
- /**
- * Changes the percent that is widget's percent size
- * @param {cc.Point} percent
- */
- setSizePercent: function (percent) {
- this._sizePercent = percent;
- if (!this._isRunning) {
- return;
- }
- var size = (this._widgetParent == null) ? cc.SizeZero() : cc.size(this._widgetParent.getSize().width * percent.x, this._widgetParent.getSize().height * percent.y);
- if (this._ignoreSize) {
- this._size = this.getContentSize();
- }
- else {
- this._size.width = size.width;
- this._size.height = size.height;
- }
- this._customSize = size;
- this.onSizeChanged();
- },
-
- /**
- * update size and position
- */
- updateSizeAndPosition: function () {
- switch (this._sizeType) {
- case cc.SizeType.ABSOLUTE:
- if (this._ignoreSize) {
- this._size = this.getContentSize();
- }
- else {
- this._size = this._customSize;
- }
- this._sizePercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(this._customSize.width / this._widgetParent.getSize().width, this._customSize.height / this._widgetParent.getSize().height);
- break;
- case cc.SizeType.PERCENT:
- var cSize = (this._widgetParent == null) ? cc.SizeZero() : cc.size(this._widgetParent.getSize().width * this._sizePercent.x, this._widgetParent.getSize().height * this._sizePercent.y);
- if (this._ignoreSize) {
- this._size = this.getContentSize();
- }
- else {
- this._size = cSize;
- }
- this._customSize = cSize;
- break;
- default:
- break;
- }
- this.onSizeChanged();
- var absPos = this.getPosition();
- switch (this._positionType) {
- case cc.PositionType.ABSOLUTE:
- this._positionPercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(absPos.x / this._widgetParent.getSize().width, absPos.y / this._widgetParent.getSize().height);
- break;
- case cc.PositionType.PERCENT:
- var parentSize = this._widgetParent.getSize();
- absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y);
- break;
- default:
- break;
- }
- this._renderer.setPosition(absPos);
- },
-
- /**
- * Changes the size type of widget.
- * @param {cc.SizeType} type
- */
- setSizeType: function (type) {
- this._sizeType = type;
- },
-
- /**
- * Gets the size type of widget.
- * @returns {cc.SizeType}
- */
- getSizeType: function () {
- return this._sizeType;
- },
-
- /**
- * Ignore the widget size
- * @param {Boolean} ignore
- */
- ignoreContentAdaptWithSize: function (ignore) {
- this._ignoreSize = ignore;
- if (this._ignoreSize) {
- var s = this.getContentSize();
- this._size = s;
- }
- else {
- this._size = this._customSize;
- }
- this.onSizeChanged();
- },
-
- /**
- * Gets the widget if is ignore it's size.
- * @returns {boolean}
- */
- isIgnoreContentAdaptWithSize: function () {
- return this._ignoreSize;
- },
-
- /**
- * Returns size of widget
- * @returns {cc.Size}
- */
- getSize: function () {
- return this._size;
- },
-
- /**
- * Returns size percent of widget
- * @returns {cc.Point}
- */
- getSizePercent: function () {
- return this._sizePercent;
- },
-
- /**
- * Gets world position of widget.
- * @returns {cc.Point}
- */
- getWorldPosition: function () {
- return this._renderer.convertToWorldSpace(cc.PointZero());
- },
-
- /**
- * Converts a Point to world space coordinates. The result is in Points.
- * @param {cc.Point} pt
- * @returns {cc.Point}
- */
- convertToWorldSpace: function (pt) {
- return this._renderer.convertToWorldSpace(pt);
- },
-
- /**
- * Gets the Virtual Renderer of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._renderer;
- },
-
- /**
- * call back function called when size changed.
- */
- onSizeChanged: function () {
-
- },
-
- /**
- * Gets the content size of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._size;
- },
-
- /**
- * set zOrder of widget
- * @param {number} z
- */
- setZOrder: function (z) {
- this._widgetZOrder = z;
- this._renderer.setZOrder(z);
- if (this._widgetParent) {
- this._widgetParent.reorderChild(this);
- }
- },
-
- /**
- * get zOrder of widget
- * @returns {number}
- */
- getZOrder: function () {
- return this._widgetZOrder;
- },
-
- /**
- * Sets whether the widget is touch enabled
- * @param enable
- */
- setTouchEnabled: function (enable) {
- this._touchEnabled = enable;
- },
-
- /**
- * To set the bright style of widget.
- * @returns {boolean}
- */
- isTouchEnabled: function () {
- return this._touchEnabled;
- },
-
- /**
- * Schedules the "update" method.
- * @param enable
- */
- setUpdateEnabled: function (enable) {
- this._updateEnabled = enable;
- if (enable) {
- if (this._scheduler) {
- this._scheduler.scheduleUpdateForTarget(this, 0, false);
- }
- }
- else {
- if (this._scheduler) {
- this._scheduler.unscheduleUpdateForTarget(this);
- }
- }
- },
-
- /**
- * is the "update" method scheduled.
- * @returns {boolean}
- */
- isUpdateEnabled: function () {
- return this._updateEnabled;
- },
-
- /**
- * Determines if the widget is on focused
- * @returns {boolean}
- */
- isFocused: function () {
- return this._focus;
- },
-
- /**
- * Sets whether the widget is on focused
- * The default value is false, a widget is default to not on focused
- * @param {boolean} fucos
- */
- setFocused: function (fucos) {
- if (fucos == this._focus) {
- return;
- }
- this._focus = fucos;
- if (this._bright) {
- if (this._focus) {
- this.setBrightStyle(cc.BrightStyle.HIGHLIGHT);
- }
- else {
- this.setBrightStyle(cc.BrightStyle.NORMAL);
- }
- }
- else {
- this.onPressStateChangedToDisabled();
- }
- },
-
- /**
- * To set the bright style of widget.
- * @param {cc.BrightStyle} style
- */
- setBrightStyle: function (style) {
- if (this._brightStyle == style) {
- return;
- }
- style = style|| cc.BrightStyle.NORMAL;
- this._brightStyle = style;
- switch (this._brightStyle) {
- case cc.BrightStyle.NORMAL:
- this.onPressStateChangedToNormal();
- break;
- case cc.BrightStyle.HIGHLIGHT:
- this.onPressStateChangedToPressed();
- break;
- default:
- break;
- }
- },
-
- /**
- * call back function called widget's state changed to normal.
- */
- onPressStateChangedToNormal: function () {
-
- },
-
- /**
- * call back function called widget's state changed to selected.
- */
- onPressStateChangedToPressed: function () {
-
- },
-
- /**
- * call back function called widget's state changed to dark.
- */
- onPressStateChangedToDisabled: function () {
-
- },
-
- /**
- * A call back function when widget lost of focus.
- */
- didNotSelectSelf: function () {
-
- },
-
- /**
- * A call back function called when widget is selected, and on touch began.
- * @param {cc.Ponit} touchPoint
- * @returns {boolean}
- */
- onTouchBegan: function (touchPoint) {
- this.setFocused(true);
- this._touchStartPos.x = touchPoint.x;
- this._touchStartPos.y = touchPoint.y;
- if (this._widgetParent) {
- this._widgetParent.checkChildInfo(0, this, touchPoint);
- }
- this.pushDownEvent();
- return this._touchPassedEnabled;
- },
-
- /**
- * A call back function called when widget is selected, and on touch moved.
- * @param {cc.Point} touchPoint
- */
- onTouchMoved: function (touchPoint) {
- this._touchMovePos.x = touchPoint.x;
- this._touchMovePos.y = touchPoint.y;
- this.setFocused(this.hitTest(touchPoint));
- if (this._widgetParent) {
- this._widgetParent.checkChildInfo(1, this, touchPoint);
- }
- this.moveEvent();
- },
-
- /**
- * A call back function called when widget is selected, and on touch ended.
- * @param {cc.Point} touchPoint
- */
- onTouchEnded: function (touchPoint) {
- this._touchEndPos.x = touchPoint.x;
- this._touchEndPos.y = touchPoint.y;
- var focus = this._focus;
- this.setFocused(false);
- if (this._widgetParent) {
- this._widgetParent.checkChildInfo(2, this, touchPoint);
- }
- if (focus) {
- this.releaseUpEvent();
- }
- else {
- this.cancelUpEvent();
- }
- },
-
- /**
- * A call back function called when widget is selected, and on touch canceled.
- * @param {cc.Point} touchPoint
- */
- onTouchCancelled: function (touchPoint) {
- this.setFocused(false);
- this.cancelUpEvent();
- },
-
- /**
- * A call back function called when widget is selected, and on touch long clicked.
- * @param {cc.Point} touchPoint
- */
- onTouchLongClicked: function (touchPoint) {
- this.longClickEvent();
- },
-
- //call back function called widget's state changed to dark.
-
- pushDownEvent: function () {
- if (this._touchEventListener && this._touchEventSelector) {
- if (this._touchEventSelector) {
- this._touchEventSelector.call(this._touchEventListener, this, cc.TouchEventType.BEGAN);
- }
- }
- },
-
- moveEvent: function () {
- if (this._touchEventListener && this._touchEventSelector) {
- if (this._touchEventSelector) {
- this._touchEventSelector.call(this._touchEventListener, this, cc.TouchEventType.MOVED);
- }
- }
- },
-
- releaseUpEvent: function () {
- if (this._touchEventListener && this._touchEventSelector) {
- if (this._touchEventSelector) {
- this._touchEventSelector.call(this._touchEventListener, this, cc.TouchEventType.ENDED);
- }
- }
- },
-
- cancelUpEvent: function () {
- if (this._touchEventSelector) {
- this._touchEventSelector.call(this._touchEventListener, this, cc.TouchEventType.CANCELED);
- }
- },
-
- longClickEvent: function () {
-
- },
-
- /**
- * Sets the touch event target/selector of the menu item
- * @param {Object} target
- * @param {Function} selector
- */
- addTouchEventListener: function (target, selector) {
- this._touchEventListener = target;
- this._touchEventSelector = selector;
- },
-
- /**
- * Gets the renderer of widget
- * @returns {cc.Node}
- */
- getRenderer: function () {
- return this._renderer;
- },
-
- /**
- * Add a CCNode for rendering.
- * renderer is a CCNode, it's for drawing
- * @param {cc.Node} renderer
- * @param {number} zOrder
- */
- addRenderer: function (renderer, zOrder) {
- this._renderer.addChild(renderer, zOrder);
- },
-
- /**
- * Remove a CCNode from widget.
- * @param {cc.Node} renderer
- * @param {Boolean} cleanup
- */
- removeRenderer: function (renderer, cleanup) {
- this._renderer.removeChild(renderer, cleanup);
- },
-
- /**
- * Checks a point if is in widget's space
- * @param {cc.Point} pt
- * @returns {boolean}
- */
- hitTest: function (pt) {
- var nsp = this._renderer.convertToNodeSpace(pt);
- var bb = cc.rect(-this._size.width * this._anchorPoint.x, -this._size.height * this._anchorPoint.y, this._size.width, this._size.height);
- if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) {
- return true;
- }
- return false;
- },
-
- /**
- * Checks a point if in parent's area.
- * @param {cc.Point} pt
- * @returns {Boolean}
- */
- clippingParentAreaContainPoint: function (pt) {
- this._affectByClipping = false;
- var parent = this.getParent();
- var clippingParent = null;
- while (parent) {
- if (parent instanceof cc.Layout) {
- if (parent.isClippingEnabled()) {
- this._affectByClipping = true;
- clippingParent = parent;
- break;
- }
- }
- parent = parent.getParent();
- }
-
- if (!this._affectByClipping) {
- return true;
- }
-
-
- if (clippingParent) {
- var bRet = false;
- if (clippingParent.hitTest(pt)) {
- bRet = true;
- }
- if (bRet) {
- return clippingParent.clippingParentAreaContainPoint(pt);
- }
- return false;
- }
- return true;
- },
-
- /**
- * Sends the touch event to widget's parent
- * @param {number} handleState
- * @param {cc.UIWidget} sender
- * @param {cc.Point} touchPoint
- */
- checkChildInfo: function (handleState, sender, touchPoint) {
- if (this._widgetParent) {
- this._widgetParent.checkChildInfo(handleState, sender, touchPoint);
- }
- },
-
- /**
- * Changes the position (x,y) of the widget .
- * @param {cc.Point} pos
- */
- setPosition: function (pos) {
- if (this._isRunning) {
- this._positionPercent = (this._widgetParent == null) ? cc.PointZero() : cc.p(pos.x / this._widgetParent.getSize().width, pos.y / this._widgetParent.getSize().height);
- }
- this._renderer.setPosition(pos);
- },
-
- /**
- * Changes the position (x,y) of the widget
- * @param {cc.Point} percent
- */
- setPositionPercent: function (percent) {
- this._positionPercent = percent;
- if (this._isRunning) {
- var parentSize = this._widgetParent.getSize();
- var absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y);
- this._renderer.setPosition(absPos);
- }
- },
-
- /**
- * Sets the anchor point in percent.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- this._anchorPoint = pt;
- this._renderer.setAnchorPoint(pt);
- },
-
- updateAnchorPoint: function () {
- this.setAnchorPoint(this._anchorPoint);
- },
-
- /**
- * Gets the position (x,y) of the widget
- * @returns {cc.Point}
- */
- getPosition: function () {
- return this._renderer.getPosition();
- },
-
- /**
- * Gets the percent (x,y) of the widget
- * @returns {cc.Point}
- */
- getPositionPercent: function () {
- return this._positionPercent;
- },
-
- /**
- * Changes the position type of the widget
- * @param {cc.PositionType} type
- */
- setPositionType: function (type) {
- this._positionType = type;
- },
-
- /**
- * Gets the position type of the widget
- * @returns {cc.pPositionType}
- */
- getPositionType: function () {
- return this._positionType;
- },
-
- /**
- * Returns the anchor point in percent.
- * @returns {cc.Point}
- */
- getAnchorPoint: function () {
- return this._anchorPoint;
- },
-
- /**
- * Changes both X and Y scale factor of the widget.
- * 1.0 is the default scale factor. It modifies the X and Y scale at the same time.
- * @param {number} scale
- */
- setScale: function (scale) {
- this._renderer.setScale(scale);
- },
-
- /**
- * Gets the scale factor of the widget, when X and Y have the same scale factor.
- * @returns {number}
- */
- getScale: function () {
- return this._renderer.getScale();
- },
-
- /**
- * Changes the scale factor on X axis of this widget
- * @param {number} scaleX
- */
- setScaleX: function (scaleX) {
- this._renderer.setScaleX(scaleX);
- },
-
- /**
- * Returns the scale factor on X axis of this widget
- * @returns {number}
- */
- getScaleX: function () {
- return this._renderer.getScaleX();
- },
-
- /**
- * Changes the scale factor on Y axis of this widget
- * @param {number} scaleY
- */
- setScaleY: function (scaleY) {
- this._renderer.setScaleY(scaleY);
- },
-
- /**
- * Returns the scale factor on Y axis of this widget
- * @returns {number}
- */
- getScaleY: function () {
- return this._renderer.getScaleY();
- },
-
- /**
- * Sets the rotation (angle) of the widget in degrees.
- * @param {number} rotation
- */
- setRotation: function (rotation) {
- this._renderer.setRotation(rotation);
- },
-
- /**
- * Returns the rotation of the widget in degrees.
- * @returns {number}
- */
- getRotation: function () {
- return this._renderer.getRotation();
- },
-
- /**
- * Sets the X rotation (angle) of the widget in degrees which performs a horizontal rotational skew.
- * @param {number} rotationX
- */
- setRotationX: function (rotationX) {
- this._renderer.setRotationX(rotationX);
- },
-
- /**
- * Gets the X rotation (angle) of the widget in degrees which performs a horizontal rotation skew.
- * @returns {number}
- */
- getRotationX: function () {
- return this._renderer.getRotationX();
- },
-
- /**
- * Sets the Y rotation (angle) of the widget in degrees which performs a vertical rotational skew.
- * @param {number} rotationY
- */
- setRotationY: function (rotationY) {
- this._renderer.setRotationY(rotationY);
- },
-
- /**
- * Gets the Y rotation (angle) of the widget in degrees which performs a vertical rotational skew.
- * @returns {number}
- */
- getRotationY: function () {
- return this._renderer.getRotationY();
- },
-
- /**
- * Sets whether the widget is visible
- * The default value is true, a widget is default to visible
- * @param {Boolean} visible
- */
- setVisible: function (visible) {
- this._visible = visible;
- this._renderer.setVisible(visible);
- },
-
- /**
- * Sets whether the widget should be flipped horizontally or not.
- * @param {Boolean} flipX
- */
- setFlippedX:function(flipX){
-
- },
-
- /**
- * Returns the flag which indicates whether the widget is flipped horizontally or not.
- * It only flips the texture of the widget, and not the texture of the widget's children.
- * Also, flipping the texture doesn't alter the anchorPoint.
- * If you want to flip the anchorPoint too, and/or to flip the children too use:
- * widget.setScaleX(sprite.getScaleX() * -1);
- * @return {Boolean} true if the widget is flipped horizaontally, false otherwise.
- */
- isFlippedX:function(){
- false;
- },
-
- /**
- * Sets whether the widget should be flipped vertically or not.
- * @param {Boolean} flipY
- */
- setFlippedY:function(flipY){
-
- },
-
- /**
- * Return the flag which indicates whether the widget is flipped vertically or not.
- * It only flips the texture of the widget, and not the texture of the widget's children.
- * Also, flipping the texture doesn't alter the anchorPoint.
- * If you want to flip the anchorPoint too, and/or to flip the children too use:
- * widget.setScaleY(widget.getScaleY() * -1);
- * @return {Boolean} true if the widget is flipped vertically, flase otherwise.
- */
- isFlippedY:function(){
- false;
- },
-
- /**
- * Determines if the widget is visible
- * @returns {boolean}
- */
- isVisible: function () {
- return this._visible;
- },
-
- /**
- * Determines if the widget is bright
- * @returns {boolean}
- */
- isBright: function () {
- return this._bright;
- },
-
- /**
- * Determines if the widget is enabled
- * @returns {boolean}
- */
- isEnabled: function () {
- return this._enabled;
- },
-
- /**
- * Gets the left boundary position of this widget.
- * @returns {number}
- */
- getLeftInParent: function () {
- return this.getPosition().x - this.getAnchorPoint().x * this._size.width;
- },
-
- /**
- * Gets the bottom boundary position of this widget.
- * @returns {number}
- */
- getBottomInParent: function () {
- return this.getPosition().y - this.getAnchorPoint().y * this._size.height;;
- },
-
- /**
- * Gets the right boundary position of this widget.
- * @returns {number}
- */
- getRightInParent: function () {
- return this.getLeftInParent() + this._size.width;
- },
-
- /**
- * Gets the top boundary position of this widget.
- * @returns {number}
- */
- getTopInParent: function () {
- return this.getBottomInParent() + this._size.height;
- },
-
- /**
- * Returns a pointer to the parent widget
- * @returns {cc.UIWidget}
- */
- getParent: function () {
- return this._widgetParent;
- },
-
- /**
- * Sets the parent widget
- * @param {cc.UIWidget} parent
- */
- setParent: function (parent) {
- this._widgetParent = parent;
- },
-
- /**
- * run action
- * @param {cc.Action} action
- * @returns {*}
- */
- runAction: function (action) {
- this._renderer.runAction(action);
- },
-
- /**
- * Sets the CCActionManager object that is used by all actions.
- * @param {cc.ActionManager} actionManager
- */
- setActionManager: function (actionManager) {
- this._renderer.setActionManager(actionManager);
- },
-
- /**
- * Gets the CCActionManager object that is used by all actions.
- * @returns {cc.ActionManager}
- */
- getActionManager: function () {
- return this._renderer.getActionManager();
- },
-
- /**
- * Stops and removes all actions from the running action list .
- */
- stopAllActions: function () {
- this._renderer.stopAllActions();
- },
-
- /**
- * Stops and removes an action from the running action list.
- * @param {cc.Action} action
- */
- stopAction: function (action) {
- this._renderer.stopAction(action);
- },
-
- /**
- * Removes an action from the running action list by its tag.
- * @param {number} tag
- */
- stopActionByTag: function (tag) {
- this._renderer.stopActionByTag(tag);
- },
-
- /**
- * Removes an action from the running action list by its tag.
- * @param {number} tag
- * @returns {cc.Action}
- */
- getActionByTag: function (tag) {
- return this._renderer.getActionByTag(tag);
- },
-
- /**
- * Sets color to widget
- * @param {cc.c3b} color
- */
- setColor: function (color) {
- if (this._renderer.RGBAProtocol) {
- this._renderer.setColor(color);
- }
- },
-
- /**
- * Gets color of widget
- * @returns {cc.c3b}
- */
- getColor: function () {
- if (this._renderer.RGBAProtocol) {
- return this._renderer.getColor();
- }
- return cc.WHITE;
- },
-
- /**
- * Sets opacity to widget
- * @param {number} opacity
- */
- setOpacity: function (opacity) {
- if (this._renderer.RGBAProtocol) {
- this._renderer.setOpacity(opacity);
- }
- },
-
- /**
- * Gets opacity of widget
- * @returns {number}
- */
- getOpacity: function () {
- if (this._renderer.RGBAProtocol) {
- return this._renderer.getOpacity();
- }
- return 255;
- },
-
- isCascadeOpacityEnabled: function () {
- if (this._renderer.RGBAProtocol) {
- return this._renderer.isCascadeOpacityEnabled();
- }
- return false;
- },
-
- setCascadeOpacityEnabled: function (cascadeOpacityEnabled) {
- if (this._renderer.RGBAProtocol) {
- this._renderer.setCascadeOpacityEnabled(cascadeOpacityEnabled);
- }
- },
-
- isCascadeColorEnabled: function () {
- if (this._renderer.RGBAProtocol) {
- return this._renderer.isCascadeColorEnabled();
- }
- return false;
- },
-
- setCascadeColorEnabled: function (cascadeColorEnabled) {
- if (this._renderer.RGBAProtocol) {
- this._renderer.setCascadeColorEnabled(cascadeColorEnabled);
- }
- },
-
- setBlendFunc: function (blendFunc) {
- if (this._renderer.setBlendFunc) {
- this._renderer.setBlendFunc(blendFunc);
- }
- },
-
- getTouchStartPos: function () {
- return this._touchStartPos;
- },
-
- getTouchMovePos: function () {
- return this._touchMovePos;
- },
-
- getTouchEndPos: function () {
- return this._touchEndPos;
- },
-
- setTag: function (tag) {
- this._widgetTag = tag;
- },
-
- getTag: function () {
- return this._widgetTag;
- },
-
- setName: function (name) {
- this._name = name;
- },
-
- getName: function () {
- return this._name;
- },
-
- getWidgetType: function () {
- return this._widgetType;
- },
-
- setLayoutParameter: function (parameter) {
- this._layoutParameterDictionary[parameter.getLayoutType()] = parameter;
- },
-
- getLayoutParameter: function (type) {
- return this._layoutParameterDictionary[type];
- },
-
- getDescription: function () {
- return "Widget";
- },
-
- /*temp action*/
- setActionTag: function (tag) {
- this._actionTag = tag;
- },
-
- getActionTag: function () {
- return this._actionTag;
- },
- setTouchEnable: function (enabled, containChildren) {
- containChildren = containChildren || false;
- this.setTouchEnabled(enabled);
- if (containChildren) {
- var childrenArray = this.getChildren();
- var length = childrenArray.length;
- var child;
- for (var i = 0; i < length; ++i) {
- child = childrenArray[i];
- child.setTouchEnable(enabled, true);
- }
- }
- },
- disable: function (containChildren) {
- containChildren = containChildren || false;
- this.setBright(false, containChildren);
- this.setTouchEnable(false, containChildren);
- },
- active: function (containChildren) {
- containChildren = containChildren || false;
- this.setBright(true, containChildren);
- this.setTouchEnable(true, containChildren);
- },
- isActive: function () {
- return this.isBright();
- },
- setBright: function (bright, containChild) {
- this._bright = bright;
- if (this._bright) {
- this._brightStyle = cc.BrightStyle.NONE;
- this.setBrightStyle(cc.BrightStyle.NORMAL);
- }
- else {
- this.onPressStateChangedToDisabled();
- }
-
- if (containChild) {
- var childrenArray = this.getChildren();
- var length = childrenArray.length;
- var child;
- for (var i = 0; i < length; ++i) {
- child = childrenArray[i];
- child.setBright(bright, containChild);
- }
- }
- },
-
- getRect: function () {
- var wPos = this.getWorldPosition();
- var width = this._size.width;
- var height = this._size.height;
- var offset_width = this._anchorPoint.x * width;
- var offset_height = this._anchorPoint.y * height;
- return cc.rect(wPos.x - offset_width, wPos.y - offset_height, width, height);
- },
- getValidNode: function () {
- return this.getVirtualRenderer();
- },
- setWidgetZOrder: function (z) {
- this.setZOrder(z);
- },
- getWidgetZOrder: function () {
- return this.getZOrder();
- },
- getRelativeLeftPos: function () {
- return this.getLeftInParent();
- },
- getRelativeBottomPos: function () {
- return this.getBottomInParent();
- },
- getRelativeRightPos: function () {
- return this.getRightInParent();
- },
- getRelativeTopPos: function () {
- return this.getTopInParent();
- },
- getContainerNode: function () {
- return this.getRenderer();
- },
- setWidgetParent: function (parent) {
- this.setParent(parent);
- },
- getWidgetParent: function () {
- return this.getParent();
- },
- setWidgetTag: function (tag) {
- this.setTag(tag);
- },
- getWidgetTag: function () {
- return this.getTag();
- },
- addCCNode: function (node) {
- this.addRenderer(node, 0);
- },
- removeCCNode: function (cleanup) {
- this.removeCCNode(cleanup);
- }
-});
-
-cc.UIWidget.create = function () {
- var widget = new cc.UIWidget();
- if (widget && widget.init()) {
- return widget;
- }
- return null;
-};
-
-cc.GUIRenderer = cc.NodeRGBA.extend({
- _enabled: true,
- setEnabled: function (enabled) {
- this._enabled = enabled;
- },
-
- isEnabled: function () {
- return this._enabled;
- },
-
- visit: function (ctx) {
- if (!this._enabled) {
- return;
- }
- cc.NodeRGBA.prototype.visit.call(this, ctx);
- }
-});
-
-cc.GUIRenderer.create = function () {
- var widget = new cc.GUIRenderer();
- if (widget && widget.init()) {
- return widget;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/Layouts/Layout.js b/extensions/CocoStudio/GUI/Layouts/Layout.js
deleted file mode 100644
index d46f4c752d..0000000000
--- a/extensions/CocoStudio/GUI/Layouts/Layout.js
+++ /dev/null
@@ -1,991 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-cc.LayoutBackGroundColorType = {
- NONE: 0,
- SOLID: 1,
- GRADIENT: 2
-};
-
-cc.LayoutType = {
- ABSOLUTE: 0,
- LINEAR_VERTICAL: 1,
- LINEAR_HORIZONTAL: 2,
- RELATIVE: 3
-};
-
-/**
- * Base class for cc.Layout
- * @class
- * @extends cc.UIWidget
- */
-cc.Layout = cc.UIWidget.extend({
- _clippingEnabled: null,
- _backGroundScale9Enable: null,
- _backGroundImage: null,
- _backGroundImageFileName: null,
- _backGroundImageCapInsets: null,
- _colorType: null,
- _bgImageTexType: null,
- _colorRender: null,
- _gradientRender: null,
- _color: null,
- _startColor: null,
- _endColor: null,
- _alongVector: null,
- _opacity: null,
- _backGroundImageTextureSize: null,
- _layoutType: null,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._clippingEnabled = false;
- this._backGroundScale9Enable = false;
- this._backGroundImage = null;
- this._backGroundImageFileName = "";
- this._backGroundImageCapInsets = cc.RectZero();
- this._colorType = cc.LayoutBackGroundColorType.NONE;
- this._bgImageTexType = cc.TextureResType.LOCAL;
- this._colorRender = null;
- this._gradientRender = null;
- this._color = cc.WHITE;
- this._startColor = cc.WHITE;
- this._endColor = cc.WHITE;
- this._alongVector = cc.p(0, -1);
- this._opacity = 255;
- this._backGroundImageTextureSize = cc.SizeZero();
- this._layoutType = cc.LayoutType.ABSOLUTE;
- this._widgetType = cc.WidgetType.Container;
- },
- init: function () {
- this._layoutParameterDictionary = {};
- this._children = [];
- this.initRenderer();
- this._renderer.setZOrder(this._widgetZOrder);
- if (this._renderer.RGBAProtocol) {
- this._renderer.setCascadeColorEnabled(false);
- this._renderer.setCascadeOpacityEnabled(false);
- }
- this.ignoreContentAdaptWithSize(false);
- this.setSize(cc.SizeZero());
- this.setBright(true);
- this.setAnchorPoint(cc.p(0, 0));
- this._scheduler = cc.Director.getInstance().getScheduler();
- return true;
- },
-
- initRenderer: function () {
- this._renderer = cc.RectClippingNode.create();
- },
-
- /**
- * Adds a locChild to the container.
- * @param {cc.UIWidget} locChild
- * @returns {boolean}
- */
- addChild: function (locChild) {
- this.supplyTheLayoutParameterLackToChild(locChild);
- return cc.UIWidget.prototype.addChild.call(this, locChild);
- },
-
- /**
- * Gets if layout is clipping enabled.
- * @returns {Boolean}
- */
- isClippingEnabled: function () {
- return this._clippingEnabled;
- },
-
- hitTest: function (pt) {
- var nsp = this._renderer.convertToNodeSpace(pt);
- var bb = cc.rect(0.0, 0, this._size.width, this._size.height);
- if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) {
- return true;
- }
- return false;
- },
-
- /**
- * Changes if layout can clip it's content and locChild.
- * @param {Boolean} able
- */
- setClippingEnabled: function (able) {
- this._clippingEnabled = able;
- if (this._renderer instanceof cc.RectClippingNode)
- this._renderer.setClippingEnabled(able);
- },
-
- onSizeChanged: function () {
- if (this._renderer instanceof cc.RectClippingNode)
- this._renderer.setClippingSize(this._size);
- this.doLayout();
- if (this._backGroundImage) {
- this._backGroundImage.setPosition(cc.p(this._size.width / 2.0, this._size.height / 2.0));
- if (this._backGroundScale9Enable) {
- if (this._backGroundImage instanceof cc.Scale9Sprite) {
- this._backGroundImage.setPreferredSize(this._size);
- }
- }
- }
- if (this._colorRender) {
- this._colorRender.setContentSize(this._size);
- }
- if (this._gradientRender) {
- this._gradientRender.setContentSize(this._size);
- }
- },
-
- /**
- * Sets background iamge use scale9 renderer.
- * @param {Boolean} able
- */
- setBackGroundImageScale9Enabled: function (able) {
- if (this._backGroundScale9Enable == able) {
- return;
- }
- this._renderer.removeChild(this._backGroundImage, true);
- this._backGroundImage = null;
- this._backGroundScale9Enable = able;
- if (this._backGroundScale9Enable) {
- this._backGroundImage = cc.Scale9Sprite.create();
- }
- else {
- this._backGroundImage = cc.Sprite.create();
- }
- this._renderer.addChild(this._backGroundImage);
- this._backGroundImage.setZOrder(-1);
- this.setBackGroundImage(this._backGroundImageFileName, this._bgImageTexType);
- this.setBackGroundImageCapInsets(this._backGroundImageCapInsets);
- },
-
- /**
- * Sets a background image for layout
- * @param {String} fileName
- * @param {cc.TextureResType} texType
- */
- setBackGroundImage: function (fileName, texType) {
- if (!fileName) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- if (this._backGroundImage == null) {
- this.addBackGroundImage();
- }
- this._backGroundImageFileName = fileName;
- this._bgImageTexType = texType;
- if (this._backGroundScale9Enable) {
- switch (this._bgImageTexType) {
- case cc.TextureResType.LOCAL:
- this._backGroundImage.initWithFile(fileName);
- break;
- case cc.TextureResType.PLIST:
- this._backGroundImage.initWithSpriteFrameName(fileName);
- break;
- default:
- break;
- }
- this._backGroundImage.setPreferredSize(this._size);
- }
- else {
- switch (this._bgImageTexType) {
- case cc.TextureResType.LOCAL:
- this._backGroundImage.initWithFile(fileName);
- break;
- case cc.TextureResType.PLIST:
- this._backGroundImage.initWithSpriteFrameName(fileName);
- break;
- default:
- break;
- }
- }
- if (this._backGroundScale9Enable) {
- this._backGroundImage.setColor(this.getColor());
- this._backGroundImage.setOpacity(this.getOpacity());
- }
- else {
- this._backGroundImage.setColor(this.getColor());
- this._backGroundImage.setOpacity(this.getOpacity());
- }
- this._backGroundImageTextureSize = this._backGroundImage.getContentSize();
- this._backGroundImage.setPosition(cc.p(this._size.width / 2.0, this._size.height / 2.0));
- },
-
- /**
- * Sets a background image capinsets for layout, if the background image is a scale9 render.
- * @param {cc.Rect} capInsets
- */
- setBackGroundImageCapInsets: function (capInsets) {
- this._backGroundImageCapInsets = capInsets;
- if (this._backGroundScale9Enable) {
- this._backGroundImage.setCapInsets(capInsets);
- }
- },
-
- supplyTheLayoutParameterLackToChild: function (locChild) {
- if (!locChild) {
- return;
- }
- switch (this._layoutType) {
- case cc.LayoutType.ABSOLUTE:
- break;
- case cc.LayoutType.LINEAR_HORIZONTAL:
- case cc.LayoutType.LINEAR_VERTICAL:
- var layoutParameter = locChild.getLayoutParameter(cc.LayoutParameterType.LINEAR);
- if (!layoutParameter) {
- locChild.setLayoutParameter(cc.LinearLayoutParameter.create());
- }
- break;
- case cc.LayoutType.RELATIVE:
- var layoutParameter = locChild.getLayoutParameter(cc.LayoutParameterType.RELATIVE);
- if (!layoutParameter) {
- locChild.setLayoutParameter(cc.RelativeLayoutParameter.create());
- }
- break;
- default:
- break;
- }
- },
-
- /**
- * init background image renderer.
- */
- addBackGroundImage: function () {
- if (this._backGroundScale9Enable) {
- this._backGroundImage = cc.Scale9Sprite.create();
- this._backGroundImage.setZOrder(-1);
- this._renderer.addChild(this._backGroundImage);
- this._backGroundImage.setPreferredSize(this._size);
- }
- else {
- this._backGroundImage = cc.Sprite.create();
- this._backGroundImage.setZOrder(-1);
- this._renderer.addChild(this._backGroundImage);
- }
- this._backGroundImage.setPosition(cc.p(this._size.width / 2.0, this._size.height / 2.0));
- },
-
- /**
- * Remove the background image of layout.
- */
- removeBackGroundImage: function () {
- if (!this._backGroundImage) {
- return;
- }
- this._renderer.removeChild(this._backGroundImage, true);
- this._backGroundImage = null;
- this._backGroundImageFileName = "";
- this._backGroundImageTextureSize = cc.SizeZero();
- },
-
- /**
- * Sets Color Type for layout.
- * @param {cc.LayoutBackGroundColorType} type
- */
- setBackGroundColorType: function (type) {
- if (this._colorType == type) {
- return;
- }
- switch (this._colorType) {
- case cc.LayoutBackGroundColorType.NONE:
- if (this._colorRender) {
- this._renderer.removeChild(this._colorRender, true);
- this._colorRender = null;
- }
- if (this._gradientRender) {
- this._renderer.removeChild(this._gradientRender, true);
- this._gradientRender = null;
- }
- break;
- case cc.LayoutBackGroundColorType.SOLID:
- if (this._colorRender) {
- this._renderer.removeChild(this._colorRender, true);
- this._colorRender = null;
- }
- break;
- case cc.LayoutBackGroundColorType.GRADIENT:
- if (this._gradientRender) {
- this._renderer.removeChild(this._gradientRender, true);
- this._gradientRender = null;
- }
- break;
- default:
- break;
- }
- this._colorType = type;
- switch (this._colorType) {
- case cc.LayoutBackGroundColorType.NONE:
- break;
- case cc.LayoutBackGroundColorType.SOLID:
- this._colorRender = cc.LayerColor.create();
- this._colorRender.setContentSize(this._size);
- this._colorRender.setOpacity(this._opacity);
- this._colorRender.setColor(this._color);
- this._renderer.addChild(this._colorRender, -2);
- break;
- case cc.LayoutBackGroundColorType.GRADIENT:
- this._gradientRender = cc.LayerGradient.create(cc.c4b(255, 0, 0, 255), cc.c4b(0, 255, 0, 255));
- this._gradientRender.setContentSize(this._size);
- this._gradientRender.setOpacity(this._opacity);
- this._gradientRender.setStartColor(this._startColor);
- this._gradientRender.setEndColor(this._endColor);
- this._gradientRender.setVector(this._alongVector);
- this._renderer.addChild(this._gradientRender, -2);
- break;
- default:
- break;
- }
- },
-
- /**
- * Sets background color for layout, if color type is LAYOUT_COLOR_SOLID
- * @param {cc.c3b} color
- * @param {cc.c3b} endColor
- */
- setBackGroundColor: function (color, endColor) {
- if (!endColor) {
- this._color = color;
- if (this._colorRender) {
- this._colorRender.setColor(color);
- }
- } else {
- this._startColor = color;
- if (this._gradientRender) {
- this._gradientRender.setStartColor(color);
- }
- this._endColor = endColor;
- if (this._gradientRender) {
- this._gradientRender.setEndColor(endColor);
- }
- }
- },
-
- /**
- * Sets background opacity layout.
- * @param {number} opacity
- */
- setBackGroundColorOpacity: function (opacity) {
- this._opacity = opacity;
- switch (this._colorType) {
- case cc.LayoutBackGroundColorType.NONE:
- break;
- case cc.LayoutBackGroundColorType.SOLID:
- this._colorRender.setOpacity(opacity);
- break;
- case cc.LayoutBackGroundColorType.GRADIENT:
- this._gradientRender.setOpacity(opacity);
- break;
- default:
- break;
- }
- },
-
- /**
- * Sets background color vector for layout, if color type is LAYOUT_COLOR_GRADIENT
- * @param {cc.Point} vector
- */
- setBackGroundColorVector: function (vector) {
- this._alongVector = vector;
- if (this._gradientRender) {
- this._gradientRender.setVector(vector);
- }
- },
-
- /**
- * Sets background color
- * @param {cc.c3b} color
- */
- setColor: function (color) {
- cc.UIWidget.prototype.setColor.call(this, color);
- if (this._backGroundImage) {
- if (this._backGroundImage.RGBAProtocol) {
- this._backGroundImage.setColor(color);
- }
- }
- },
-
- /**
- * Sets background opacity
- * @param {number} opacity
- */
- setOpacity: function (opacity) {
- cc.UIWidget.prototype.setOpacity.call(this, opacity);
- if (this._backGroundImage) {
- if (this._backGroundImage.RGBAProtocol) {
- this._backGroundImage.setOpacity(opacity);
- }
- }
- },
-
- /**
- * Gets background image texture size.
- * @returns {cc.Size}
- */
- getBackGroundImageTextureSize: function () {
- return this._backGroundImageTextureSize;
- },
-
- /**
- * Gets the content size of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._renderer.getContentSize();
- },
-
- /**
- * Sets LayoutType.
- * @param {cc.LayoutType} type
- */
- setLayoutType: function (type) {
- this._layoutType = type;
- var layoutChildrenArray = this.getChildren();
- var locChild = null;
- for (var i = 0; i < layoutChildrenArray.length; i++) {
- locChild = layoutChildrenArray[i];
- this.supplyTheLayoutParameterLackToChild(locChild);
- }
- },
-
- /**
- * Gets LayoutType.
- * @returns {null}
- */
- getLayoutType: function () {
- return this._layoutType;
- },
-
- doLayout_LINEAR_VERTICAL: function () {
- var layoutChildrenArray = this.getChildren();
- var layoutSize = this.getSize();
- var topBoundary = layoutSize.height;
- for (var i = 0; i < layoutChildrenArray.length; ++i) {
- var locChild = layoutChildrenArray[i];
- var locLayoutParameter = locChild.getLayoutParameter(cc.LayoutParameterType.LINEAR);
-
- if (locLayoutParameter) {
- var locChildGravity = locLayoutParameter.getGravity();
- var locAP = locChild.getAnchorPoint();
- var locSize = locChild.getSize();
- var locFinalPosX = locAP.x * locSize.width;
- var locFinalPosY = topBoundary - ((1 - locAP.y) * locSize.height);
- switch (locChildGravity) {
- case cc.UILinearGravity.NONE:
- case cc.UILinearGravity.LEFT:
- break;
- case cc.UILinearGravity.RIGHT:
- locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
- break;
- case cc.UILinearGravity.CENTER_HORIZONTAL:
- locFinalPosX = layoutSize.width / 2 - locSize.width * (0.5 - locAP.x);
- break;
- default:
- break;
- }
- var locMargin = locLayoutParameter.getMargin();
- locFinalPosX += locMargin.left;
- locFinalPosY -= locMargin.top;
- locChild.setPosition(cc.p(locFinalPosX, locFinalPosY));
- topBoundary = locChild.getBottomInParent() - locMargin.bottom;
- }
- }
- },
- doLayout_LINEAR_HORIZONTAL: function () {
- var layoutChildrenArray = this.getChildren();
- var layoutSize = this.getSize();
- var leftBoundary = 0;
- for (var i = 0; i < layoutChildrenArray.length; ++i) {
- var locChild = layoutChildrenArray[i];
- var locLayoutParameter = locChild.getLayoutParameter(cc.LayoutParameterType.LINEAR);
-
- if (locLayoutParameter) {
- var locChildGravity = locLayoutParameter.getGravity();
- var locAP = locChild.getAnchorPoint();
- var locSize = locChild.getSize();
- var locFinalPosX = leftBoundary + (locAP.x * locSize.width);
- var locFinalPosY = layoutSize.height - (1 - locAP.y) * locSize.height;
- switch (locChildGravity) {
- case cc.UILinearGravity.NONE:
- case cc.UILinearGravity.TOP:
- break;
- case cc.UILinearGravity.BOTTOM:
- locFinalPosY = locAP.y * locSize.height;
- break;
- case cc.UILinearGravity.CENTER_VERTICAL:
- locFinalPosY = layoutSize.height / 2 - locSize.height * (0.5 - locAP.y);
- break;
- default:
- break;
- }
- var locMargin = locLayoutParameter.getMargin();
- locFinalPosX += locMargin.left;
- locFinalPosY -= locMargin.top;
- locChild.setPosition(cc.p(locFinalPosX, locFinalPosY));
- leftBoundary = locChild.getRightInParent() + locMargin.right;
- }
- }
- },
- doLayout_RELATIVE: function () {
- var layoutChildrenArray = this.getChildren();
- var length = layoutChildrenArray.length;
- var unlayoutChildCount = length;
- var layoutSize = this.getSize();
-
- for (var i = 0; i < length; i++) {
- var locChild = layoutChildrenArray[i];
- var locLayoutParameter = locChild.getLayoutParameter(cc.LayoutParameterType.RELATIVE);
- locLayoutParameter._put = false;
- }
-
- while (unlayoutChildCount > 0) {
- for (var i = 0; i < length; i++) {
- var locChild = layoutChildrenArray[i];
- var locLayoutParameter = locChild.getLayoutParameter(cc.LayoutParameterType.RELATIVE);
-
- if (locLayoutParameter) {
- if (locLayoutParameter._put) {
- continue;
- }
- var locAP = locChild.getAnchorPoint();
- var locSize = locChild.getSize();
- var locAlign = locLayoutParameter.getAlign();
- var locRelativeName = locLayoutParameter.getRelativeToWidgetName();
- var locRelativeWidget = null;
- var locRelativeWidgetLP = null;
- var locFinalPosX = 0;
- var locFinalPosY = 0;
- if (locRelativeName) {
- locRelativeWidget = cc.UIHelper.getInstance().seekWidgetByRelativeName(this, locRelativeName);
- if (locRelativeWidget) {
- locRelativeWidgetLP = locRelativeWidget.getLayoutParameter(cc.LayoutParameterType.RELATIVE);
- }
- }
- switch (locAlign) {
- case cc.UIRelativeAlign.ALIGN_NONE:
- case cc.UIRelativeAlign.ALIGN_PARENT_TOP_LEFT:
- locFinalPosX = locAP.x * locSize.width;
- locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height);
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_TOP_CENTER_HORIZONTAL:
- locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x);
- locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height);
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_TOP_RIGHT:
- locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
- locFinalPosY = layoutSize.height - ((1 - locAP.y) * locSize.height);
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_LEFT_CENTER_VERTICAL:
- locFinalPosX = locAP.x * locSize.width;
- locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y);
- break;
- case cc.UIRelativeAlign.CENTER_IN_PARENT:
- locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x);
- locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y);
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_RIGHT_CENTER_VERTICAL:
- locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
- locFinalPosY = layoutSize.height * 0.5 - locSize.height * (0.5 - locAP.y);
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_LEFT_BOTTOM:
- locFinalPosX = locAP.x * locSize.width;
- locFinalPosY = locAP.y * locSize.height;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL:
- locFinalPosX = layoutSize.width * 0.5 - locSize.width * (0.5 - locAP.x);
- locFinalPosY = locAP.y * locSize.height;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_RIGHT_BOTTOM:
- locFinalPosX = layoutSize.width - ((1 - locAP.x) * locSize.width);
- locFinalPosY = locAP.y * locSize.height;
- break;
-
- case cc.UIRelativeAlign.LOCATION_ABOVE_LEFTALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationBottom = locRelativeWidget.getTopInParent();
- var locationLeft = locRelativeWidget.getLeftInParent();
- locFinalPosY = locationBottom + locAP.y * locSize.height;
- locFinalPosX = locationLeft + locAP.x * locSize.width;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_ABOVE_CENTER:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var rbs = locRelativeWidget.getSize();
- var locationBottom = locRelativeWidget.getTopInParent();
-
- locFinalPosY = locationBottom + locAP.y * locSize.height;
- locFinalPosX = locRelativeWidget.getLeftInParent() + rbs.width * 0.5 + locAP.x * locSize.width - locSize.width * 0.5;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_ABOVE_RIGHTALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationBottom = locRelativeWidget.getTopInParent();
- var locationRight = locRelativeWidget.getRightInParent();
- locFinalPosY = locationBottom + locAP.y * locSize.height;
- locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_LEFT_OF_TOPALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationTop = locRelativeWidget.getTopInParent();
- var locationRight = locRelativeWidget.getLeftInParent();
- locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
- locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_LEFT_OF_CENTER:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var rbs = locRelativeWidget.getSize();
- var locationRight = locRelativeWidget.getLeftInParent();
- locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
-
- locFinalPosY = locRelativeWidget.getBottomInParent() + rbs.height * 0.5 + locAP.y * locSize.height - locSize.height * 0.5;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_LEFT_OF_BOTTOMALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationBottom = locRelativeWidget.getBottomInParent();
- var locationRight = locRelativeWidget.getLeftInParent();
- locFinalPosY = locationBottom + locAP.y * locSize.height;
- locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_RIGHT_OF_TOPALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationTop = locRelativeWidget.getTopInParent();
- var locationLeft = locRelativeWidget.getRightInParent();
- locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
- locFinalPosX = locationLeft + locAP.x * locSize.width;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_RIGHT_OF_CENTER:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var rbs = locRelativeWidget.getSize();
- var locationLeft = locRelativeWidget.getRightInParent();
- locFinalPosX = locFinalPosX = locationLeft + locAP.x * locSize.width;
-
- locFinalPosY = locRelativeWidget.getBottomInParent() + rbs.height * 0.5 + locAP.y * locSize.height - locSize.height * 0.5;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_RIGHT_OF_BOTTOMALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationBottom = locRelativeWidget.getBottomInParent();
- var locationLeft = locRelativeWidget.getRightInParent();
- locFinalPosY = locationBottom + locAP.y * locSize.height;
- locFinalPosX = locationLeft + locAP.x * locSize.width;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_BELOW_LEFTALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationTop = locRelativeWidget.getBottomInParent();
- var locationLeft = locRelativeWidget.getLeftInParent();
- locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
- locFinalPosX = locationLeft + locAP.x * locSize.width;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_BELOW_CENTER:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var rbs = locRelativeWidget.getSize();
- var locationTop = locRelativeWidget.getBottomInParent();
-
- locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
- locFinalPosX = locRelativeWidget.getLeftInParent() + rbs.width * 0.5 + locAP.x * locSize.width - locSize.width * 0.5;
- }
- break;
- case cc.UIRelativeAlign.LOCATION_BELOW_RIGHTALIGN:
- if (locRelativeWidget) {
- if (locRelativeWidgetLP && !locRelativeWidgetLP._put) {
- continue;
- }
- var locationTop = locRelativeWidget.getBottomInParent();
- var locationRight = locRelativeWidget.getRightInParent();
- locFinalPosY = locationTop - (1 - locAP.y) * locSize.height;
- locFinalPosX = locationRight - (1 - locAP.x) * locSize.width;
- }
- break;
- default:
- break;
- }
- var locRelativeWidgetMargin;
- var locMargin = locLayoutParameter.getMargin();
- if (locRelativeWidget) {
- locRelativeWidgetMargin = locRelativeWidget.getLayoutParameter(cc.LayoutParameterType.RELATIVE).getMargin();
- }
- //handle margin
- switch (locAlign) {
- case cc.UIRelativeAlign.ALIGN_NONE:
- case cc.UIRelativeAlign.ALIGN_PARENT_TOP_LEFT:
- locFinalPosX += locMargin.left;
- locFinalPosY -= locMargin.top;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_TOP_CENTER_HORIZONTAL:
- locFinalPosY -= locMargin.top;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_TOP_RIGHT:
- locFinalPosX -= locMargin.right;
- locFinalPosY -= locMargin.top;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_LEFT_CENTER_VERTICAL:
- locFinalPosX += locMargin.left;
- break;
- case cc.UIRelativeAlign.CENTER_IN_PARENT:
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_RIGHT_CENTER_VERTICAL:
- locFinalPosX -= locMargin.right;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_LEFT_BOTTOM:
- locFinalPosX += locMargin.left;
- locFinalPosY += locMargin.bottom;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL:
- locFinalPosY += locMargin.bottom;
- break;
- case cc.UIRelativeAlign.ALIGN_PARENT_RIGHT_BOTTOM:
- locFinalPosX -= locMargin.right;
- locFinalPosY += locMargin.bottom;
- break;
-
- case cc.UIRelativeAlign.LOCATION_ABOVE_LEFTALIGN:
- case cc.UIRelativeAlign.LOCATION_ABOVE_CENTER:
- case cc.UIRelativeAlign.LOCATION_ABOVE_RIGHTALIGN:
- locFinalPosY += locMargin.bottom;
- locFinalPosY += locRelativeWidgetMargin.top;
- break;
- case cc.UIRelativeAlign.LOCATION_LEFT_OF_TOPALIGN:
- case cc.UIRelativeAlign.LOCATION_LEFT_OF_CENTER:
- case cc.UIRelativeAlign.LOCATION_LEFT_OF_BOTTOMALIGN:
- locFinalPosX -= locMargin.right;
- locFinalPosX -= locRelativeWidgetMargin.left;
- break;
- case cc.UIRelativeAlign.LOCATION_RIGHT_OF_TOPALIGN:
- case cc.UIRelativeAlign.LOCATION_RIGHT_OF_CENTER:
- case cc.UIRelativeAlign.LOCATION_RIGHT_OF_BOTTOMALIGN:
- locFinalPosX += locMargin.left;
- locFinalPosX += locRelativeWidgetMargin.right;
- break;
- case cc.UIRelativeAlign.LOCATION_BELOW_LEFTALIGN:
- case cc.UIRelativeAlign.LOCATION_BELOW_CENTER:
- case cc.UIRelativeAlign.LOCATION_BELOW_RIGHTALIGN:
- locFinalPosY -= locMargin.top;
- locFinalPosY -= locRelativeWidgetMargin.bottom;
- break;
- default:
- break;
- }
- locChild.setPosition(cc.p(locFinalPosX, locFinalPosY));
- locLayoutParameter._put = true;
- unlayoutChildCount--;
- }
- }
- }
- },
- doLayout: function () {
- switch (this._layoutType) {
- case cc.LayoutType.ABSOLUTE:
- break;
- case cc.LayoutType.LINEAR_VERTICAL:
- this.doLayout_LINEAR_VERTICAL();
- break;
- case cc.LayoutType.LINEAR_HORIZONTAL:
- this.doLayout_LINEAR_HORIZONTAL();
- break;
- case cc.LayoutType.RELATIVE:
- this.doLayout_RELATIVE();
- break;
- default:
- break;
- }
- },
-
- /**
- * Returns the "class name" of widget.
- * @returns {string}
- */
- getDescription: function () {
- return "Layout";
- }
-});
-
-cc.Layout.create = function () {
- var layout = new cc.Layout();
- if (layout && layout.init()) {
- return layout;
- }
- return null;
-};
-
-cc.RectClippingNode = cc.ClippingNode.extend({
- _innerStencil: null,
- _enabled: null,
- _arrRect: null,
- _clippingSize: null,
- _clippingEnabled: null,
- ctor: function () {
- cc.ClippingNode.prototype.ctor.call(this);
- this._innerStencil = null;
- this._enabled = true;
- this._arrRect = [];
- this._clippingSize = cc.size(50, 50);
- this._clippingEnabled = false;
- },
-
- init: function () {
- this._innerStencil = cc.DrawNode.create();
- this._arrRect[0] = cc.p(0, 0);
- this._arrRect[1] = cc.p(this._clippingSize.width, 0);
- this._arrRect[2] = cc.p(this._clippingSize.width, this._clippingSize.height);
- this._arrRect[3] = cc.p(0, this._clippingSize.height);
-
- var green = cc.c4f(0, 1, 0, 1);
- this._innerStencil.drawPoly(this._arrRect, 4, green, 0, green);
- if (cc.Browser.supportWebGL) {
- if (cc.ClippingNode.prototype.init.call(this, this._innerStencil)) {
- return true;
- }
- } else {
- this._stencil = this._innerStencil;
- this._alphaThreshold = 1;
- this._inverted = false;
- return true;
- }
-
- return false;
- },
-
- setClippingSize: function (size) {
- this.setContentSize(size);
- this._clippingSize = cc.size(size.width, size.height);
- this._arrRect[0] = cc.p(0, 0);
- this._arrRect[1] = cc.p(this._clippingSize.width, 0);
- this._arrRect[2] = cc.p(this._clippingSize.width, this._clippingSize.height);
- this._arrRect[3] = cc.p(0, this._clippingSize.height);
- var green = cc.c4f(0, 1, 0, 1);
- this._innerStencil.clear();
- this._innerStencil.drawPoly(this._arrRect, 4, green, 0, green);
- },
-
- setClippingEnabled: function (enabled) {
- this._clippingEnabled = enabled;
- },
-
- visit: function (ctx) {
- if (!this._enabled) {
- return;
- }
- if (this._clippingEnabled) {
- if (cc.Browser.supportWebGL) {
- cc.ClippingNode.prototype.visit.call(this, ctx);
- } else {
- this.visitCanvas(ctx);
- }
- }
- else {
- cc.Node.prototype.visit.call(this, ctx);
- }
- },
-
- visitCanvas: function (ctx) {
- // quick return if not visible
- if (!this._visible)
- return;
-
- //visit for canvas
- var context = ctx || cc.renderContext, i;
- var children = this._children, locChild;
- context.save();
- this.transform(context);
- context.beginPath();
- var locContentSize = this.getContentSize();
- var locRect = cc.rect(0, 0, locContentSize.width, locContentSize.height);
- var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY();
-
- context.rect(locRect.x * locEGL_ScaleX, locRect.y * locEGL_ScaleY, locRect.width * locEGL_ScaleX, -locRect.height * locEGL_ScaleY);
- context.clip();
- context.closePath();
- var len = children.length;
- if (len > 0) {
- this.sortAllChildren();
- // draw children zOrder < 0
- for (i = 0; i < len; i++) {
- locChild = children[i];
- if (locChild._zOrder < 0)
- locChild.visit(context);
- else
- break;
- }
- this.draw(context);
- for (; i < len; i++) {
- children[i].visit(context);
- }
- } else
- this.draw(context);
-
- this._orderOfArrival = 0;
- context.restore();
- },
-
- setEnabled: function (enabled) {
- this._enabled = enabled;
- },
-
- isEnabled: function () {
- return this._enabled;
- }
-});
-cc.RectClippingNode.create = function () {
- var node = new cc.RectClippingNode();
- if (node && node.init()) {
- return node;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/Layouts/LayoutParameter.js b/extensions/CocoStudio/GUI/Layouts/LayoutParameter.js
deleted file mode 100644
index 18284e4ad3..0000000000
--- a/extensions/CocoStudio/GUI/Layouts/LayoutParameter.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.LayoutParameterType = {
- NONE: 0,
- LINEAR: 1,
- RELATIVE: 2
-};
-
-/**
- * Base class for cc.LayoutParameter
- * @class
- * @extends cc.Class
- */
-cc.LayoutParameter = cc.Class.extend({
- _margin: null,
- _layoutParameterType: null,
- ctor: function () {
- this._margin = new cc.UIMargin();
- this._layoutParameterType = cc.LayoutParameterType.NONE;
- },
-
- /**
- * Sets Margin parameter for LayoutParameter.
- * @param {cc.UIMargin} margin
- */
- setMargin: function (margin) {
- this._margin = margin;
- },
-
- /**
- * Gets Margin parameter of LayoutParameter.
- * @returns {cc.UIMargin}
- */
- getMargin: function () {
- return this._margin;
- },
-
- /**
- * Gets LayoutParameterType of LayoutParameter.
- * @returns {cc.LayoutParameterType}
- */
- getLayoutType: function () {
- return this._layoutParameterType;
- }
-});
-
-
-cc.LayoutParameter.create = function () {
- var parameter = new cc.LayoutParameter();
- return parameter;
-};
-
-/**
- * Base class for cc.LinearLayoutParameter
- * @class
- * @extends cc.LayoutParameter
- */
-cc.LinearLayoutParameter = cc.LayoutParameter.extend({
- _linearGravity: null,
- ctor: function () {
- cc.LayoutParameter.prototype.ctor.call(this);
- this._linearGravity = cc.UILinearGravity.NONE;
- this._layoutParameterType = cc.LayoutParameterType.LINEAR;
- },
-
- /**
- * Sets UILinearGravity parameter for LayoutParameter.
- * @param {cc.UILinearGravity} gravity
- */
- setGravity: function (gravity) {
- this._linearGravity = gravity;
- },
-
- /**
- * Gets UILinearGravity parameter for LayoutParameter.
- * @returns {cc.UILinearGravity}
- */
- getGravity: function () {
- return this._linearGravity;
- }
-});
-
-cc.LinearLayoutParameter.create = function () {
- var parameter = new cc.LinearLayoutParameter();
- return parameter;
-};
-
-/**
- * Base class for cc.RelativeLayoutParameter
- * @class
- * @extends cc.LayoutParameter
- */
-cc.RelativeLayoutParameter = cc.LayoutParameter.extend({
- _relativeAlign: null,
- _relativeWidgetName: "",
- _relativeLayoutName: "",
- _put:false,
- ctor: function () {
- cc.LayoutParameter.prototype.ctor.call(this);
- this._relativeAlign = cc.UIRelativeAlign.ALIGN_NONE;
- this._relativeWidgetName = "";
- this._relativeLayoutName = "";
- this._put = false;
- },
-
- /**
- * Sets UIRelativeAlign parameter for LayoutParameter.
- * @param {cc.UIRelativeAlign} align
- */
- setAlign: function (align) {
- this._relativeAlign = align;
- },
-
- /**
- * Gets UIRelativeAlign parameter for LayoutParameter.
- * @returns {cc.UIRelativeAlign}
- */
- getAlign: function () {
- return this._relativeAlign;
- },
-
- /**
- * Sets a key for LayoutParameter. Witch widget named this is relative to.
- * @param {String} name
- */
- setRelativeToWidgetName: function (name) {
- this._relativeWidgetName = name;
- },
-
- /**
- * Gets the key of LayoutParameter. Witch widget named this is relative to.
- * @returns {string}
- */
- getRelativeToWidgetName: function () {
- return this._relativeWidgetName;
- },
-
- /**
- * Sets a name in Relative Layout for LayoutParameter.
- * @param {String} name
- */
- setRelativeName: function (name) {
- this._relativeLayoutName = name;
- },
-
- /**
- * Gets a name in Relative Layout of LayoutParameter.
- * @returns {string}
- */
- getRelativeName: function () {
- return this._relativeLayoutName;
- }
-});
-
-cc.RelativeLayoutParameter.create = function () {
- var parameter = new cc.RelativeLayoutParameter();
- return parameter;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/Layouts/UILayoutDefine.js b/extensions/CocoStudio/GUI/Layouts/UILayoutDefine.js
deleted file mode 100644
index 6889bea2f4..0000000000
--- a/extensions/CocoStudio/GUI/Layouts/UILayoutDefine.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.UILinearGravity = {
- NONE: 0,
- LEFT: 1,
- TOP: 2,
- RIGHT: 3,
- BOTTOM: 4,
- CENTER_VERTICAL: 5,
- CENTER_HORIZONTAL: 6
-};
-
-cc.UIRelativeAlign = {
- ALIGN_NONE: 0,
- ALIGN_PARENT_TOP_LEFT: 1,
- ALIGN_PARENT_TOP_CENTER_HORIZONTAL: 2,
- ALIGN_PARENT_TOP_RIGHT: 3,
- ALIGN_PARENT_LEFT_CENTER_VERTICAL: 4,
- CENTER_IN_PARENT: 5,
- ALIGN_PARENT_RIGHT_CENTER_VERTICAL: 6,
- ALIGN_PARENT_LEFT_BOTTOM: 7,
- ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL: 8,
- ALIGN_PARENT_RIGHT_BOTTOM: 9,
- LOCATION_ABOVE_LEFTALIGN: 10,
- LOCATION_ABOVE_CENTER: 11,
- LOCATION_ABOVE_RIGHTALIGN: 12,
- LOCATION_LEFT_OF_TOPALIGN: 13,
- LOCATION_LEFT_OF_CENTER: 14,
- LOCATION_LEFT_OF_BOTTOMALIGN: 15,
- LOCATION_RIGHT_OF_TOPALIGN: 16,
- LOCATION_RIGHT_OF_CENTER: 17,
- LOCATION_RIGHT_OF_BOTTOMALIGN: 18,
- LOCATION_BELOW_LEFTALIGN: 19,
- LOCATION_BELOW_CENTER: 20,
- LOCATION_BELOW_RIGHTALIGN: 21
-};
-
-/**
- * Base class for cc.UIMargin
- * @class
- * @extends cc.Class
- */
-cc.UIMargin = cc.Class.extend({
- left: 0,
- top: 0,
- right: 0,
- bottom: 0,
- ctor: function () {
- if (arguments.length == 1) {
- var uiMargin = arguments[0];
- this.left = uiMargin.left;
- this.top = uiMargin.top;
- this.right = uiMargin.right;
- this.bottom = uiMargin.bottom;
- }
- if (arguments.length == 4) {
- this.left = arguments[0];
- this.top = arguments[1];
- this.right = arguments[2];
- this.bottom = arguments[3];
- }
- },
- setMargin: function (l, t, r, b) {
- this.left = l;
- this.top = t;
- this.right = r;
- this.bottom = b;
- },
- equals: function (target) {
- return (this.left == target.left && this.top == target.top && this.right == target.right && this.bottom == target.bottom);
- }
-});
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/System/UIHelper.js b/extensions/CocoStudio/GUI/System/UIHelper.js
deleted file mode 100644
index 64376ed99c..0000000000
--- a/extensions/CocoStudio/GUI/System/UIHelper.js
+++ /dev/null
@@ -1,215 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.UIHelper
- * @class
- * @extends cc.Class
- */
-cc.UIHelper = cc.Class.extend({
- _fileDesignWidth: 0,
- _fileDesignHeight: 0,
-//texture
- _textureFiles: [],
- ctor: function () {
- var winSize = cc.Director.getInstance().getWinSize();
- this._fileDesignWidth = winSize.width;
- this._fileDesignHeight = winSize.height;
- this.init();
- },
- init: function () {
- this._textureFiles = [];
- },
-
- /**
- * Load a widget with json file.
- * @param {String} fileName
- * @returns {String}
- */
- createWidgetFromJsonFile: function (fileName) {
- return cc.CCSGUIReader.getInstance().widgetFromJsonFile(fileName);
- },
-
- /**
- * add a plist file for loading widget's texture.
- * @param {String} fileName
- */
- addSpriteFrame: function (fileName) {
- if (!fileName) {
- return;
- }
- for (var i = 0; i < this._textureFiles.length; i++) {
- var file = this._textureFiles[i];
- if (file == fileName) {
- return;
- }
- }
- this._textureFiles.push(fileName);
- cc.SpriteFrameCache.getInstance().addSpriteFrames(fileName);
- },
-
- /**
- * remove a plist file for loading widget's texture.
- * @param fileName
- */
- removeSpriteFrame: function (fileName) {
- if (!fileName) {
- return;
- }
- for (var i = 0; i < this._textureFiles.length; i++) {
- var file = this._textureFiles[i];
- if (file == fileName) {
- cc.SpriteFrameCache.getInstance().removeSpriteFrameByName(fileName);
- cc.ArrayRemoveObject(this._textureFiles, file);
- return;
- }
- }
- },
-
- /**
- * remove all plist files for loading widget's texture.
- */
- removeAllSpriteFrame: function () {
- for (var i = 0; i < this._textureFiles.length; i++) {
- var file = this._textureFiles[i];
- cc.SpriteFrameCache.getInstance().removeSpriteFrameByName(file);
- }
- this._textureFiles = [];
- },
-
- /**
- * Finds a widget whose tag equals to param tag from root widget.
- * @param {cc.UIWidget} root
- * @param {number} tag
- * @returns {cc.UIWidget}
- */
- seekWidgetByTag: function (root, tag) {
- if (!root) {
- return null;
- }
- if (root.getTag() == tag) {
- return root;
- }
- var arrayRootChildren = root.getChildren();
- var length = arrayRootChildren.length;
- for (var i = 0; i < length; i++) {
- var child = arrayRootChildren[i];
- var res = this.seekWidgetByTag(child, tag);
- if (res != null) {
- return res;
- }
- }
- return null;
- },
-
- /**
- * Finds a widget whose name equals to param name from root widget.
- * @param {cc.UIWidget} root
- * @param {String} name
- * @returns {cc.UIWidget}
- */
- seekWidgetByName: function (root, name) {
- if (!root) {
- return null;
- }
- if (root.getName() == name) {
- return root;
- }
- var arrayRootChildren = root.getChildren();
- var length = arrayRootChildren.length;
- for (var i = 0; i < length; i++) {
- var child = arrayRootChildren[i];
- var res = this.seekWidgetByName(child, name);
- if (res != null) {
- return res;
- }
- }
- return null;
- },
-
- /**
- * Finds a widget whose name equals to param name from root widget.
- * RelativeLayout will call this method to find the widget witch is needed.
- * @param {cc.UIWidget} root
- * @param {String} name
- * @returns {cc.UIWidget}
- */
- seekWidgetByRelativeName: function (root, name) {
- if (!root) {
- return null;
- }
- var arrayRootChildren = root.getChildren();
- var length = arrayRootChildren.length;
- for (var i = 0; i < length; i++) {
- var child = arrayRootChildren[i];
- var layoutParameter = child.getLayoutParameter(cc.LayoutParameterType.RELATIVE);
- if (layoutParameter && layoutParameter.getRelativeName() == name) {
- return child;
- }
- }
- return null;
- },
-
- /**
- * Set file design width
- * @param {number} width
- */
- setFileDesignWidth: function (width) {
- this._fileDesignWidth = width;
- },
-
- /**
- * Get file design width
- * @returns {number}
- */
- getFileDesignWidth: function () {
- return this._fileDesignWidth;
- },
-
- /**
- * Set file design height
- * @param {number} height
- */
- setFileDesignHeight: function (height) {
- this._fileDesignHeight = height;
- },
-
- /**
- * Get file design height
- * @returns {number}
- */
- getFileDesignHeight: function () {
- return this._fileDesignHeight;
- }
-});
-cc.UIHelper._instance = null;
-cc.UIHelper.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.UIHelper();
- }
- return this._instance;
-};
-cc.UIHelper.purge = function(){
- this._instance=null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/System/UIInputManager.js b/extensions/CocoStudio/GUI/System/UIInputManager.js
deleted file mode 100644
index eeeb41b9d4..0000000000
--- a/extensions/CocoStudio/GUI/System/UIInputManager.js
+++ /dev/null
@@ -1,207 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.UIHelper
- * @class
- * @extends cc.Class
- */
-cc.UIInputManager = cc.Class.extend({
- _manageredWidget: null,
- _selectedWidgets: null,
- _touchBeganedPoint: null,
- _touchMovedPoint: null,
- _touchEndedPoint: null,
- _touchCanceledPoint: null,
- _widgetBeSorted: false,
- _touchDown: false,
- _longClickTime: 0,
- _longClickRecordTime: 0,
- _checkedDoubleClickWidget: null,
- _rootWidget: null,
- ctor: function () {
- this._manageredWidget = null;
- this._selectedWidgets = [];
- this._touchBeganedPoint = cc.p(0, 0);
- this._touchMovedPoint = cc.p(0, 0);
- this._touchEndedPoint = cc.p(0, 0);
- this._touchCanceledPoint = cc.p(0, 0);
- this._widgetBeSorted = false;
- this._touchDown = false;
- this._longClickTime = 0;
- this._longClickRecordTime = 0;
- this._checkedDoubleClickWidget = [];
- this._rootWidget = null;
- },
-
- /**
- * Regist a widget to input manager.
- * @param {cc.UIWidget} widget
- */
- registWidget: function (widget) {
- if (!widget) {
- return;
- }
- if (cc.ArrayContainsObject(this._manageredWidget, widget)) {
- return;
- }
- this._manageredWidget.push(widget);
- },
-
- /**
- * A call back function called when widget tree struct has changed.
- * If widget tree struct has changed, uiinputmanager will resort registed widgets.
- */
- uiSceneHasChanged: function () {
- this._widgetBeSorted = false;
- },
-
- /**
- * Check touch event
- * @param {cc.UIWidget} root
- * @param {cc.Point} touchPoint
- * @returns {boolean}
- */
- checkTouchEvent: function (root, touchPoint) {
- var arrayRootChildren = root.getChildren();
- var length = arrayRootChildren.length;
- for (var i = length - 1; i >= 0; i--) {
- var widget = arrayRootChildren[i];
- if (this.checkTouchEvent(widget, touchPoint)) {
- return true;
- }
- }
- if (root.isEnabled() && root.isTouchEnabled() && root.hitTest(touchPoint) && root.clippingParentAreaContainPoint(touchPoint)) {
- this._selectedWidgets.push(root);
- root.onTouchBegan(touchPoint);
- return true;
- }
- return false;
- },
-
- /**
- * Remove a registed widget from input manager.
- * @param {cc.UIWidget} widget
- */
- removeManageredWidget: function (widget) {
- if (!widget) {
- return;
- }
- if (!cc.ArrayContainsObject(this._manageredWidget, widget)) {
- return;
- }
- cc.ArrayRemoveObject(this._manageredWidget, widget);
- },
-
- /**
- * Finds a widget which is selected and call it's "onTouchBegan" method.
- * @param {cc.Point} touchPoint
- * @returns {boolean}
- */
- checkEventWidget: function (touchPoint) {
- this.checkTouchEvent(this._rootWidget, touchPoint);
- return (this._selectedWidgets.length > 0);
- },
-
- /**
- * Add doubleClick widget
- * @param {UIWidget} widget
- */
- addCheckedDoubleClickWidget: function (widget) {
- if (cc.ArrayContainsObject(this._checkedDoubleClickWidget, widget)) {
- return;
- }
- this._checkedDoubleClickWidget.push(widget);
- },
-
- update: function (dt) {
- if (this._touchDown) {
- this._longClickRecordTime += dt;
- if (this._longClickRecordTime >= this._longClickTime) {
- this._longClickRecordTime = 0;
- this._touchDown = false;
- }
- }
- var arrayWidget = this._checkedDoubleClickWidget;
- for (var i = 0; i < arrayWidget.length; i++) {
- var widget = arrayWidget[i];
- if (!widget.isVisible()) {
- continue;
- }
- }
- },
-
- onTouchBegan: function (touch) {
- this._touchBeganedPoint.x = touch.getLocation().x;
- this._touchBeganedPoint.y = touch.getLocation().y;
- this._touchDown = true;
- return this.checkEventWidget(this._touchBeganedPoint);
- },
-
- onTouchMoved: function (touch) {
- this._touchMovedPoint.x = touch.getLocation().x;
- this._touchMovedPoint.y = touch.getLocation().y;
- var selectedWidgetArray = this._selectedWidgets;
- for (var i = 0; i < selectedWidgetArray.length; ++i) {
- var hitWidget = selectedWidgetArray[i];
- hitWidget.onTouchMoved(this._touchMovedPoint);
- }
- if (this._touchDown) {
- this._longClickRecordTime = 0;
- this._touchDown = false;
- }
- },
-
- onTouchEnded: function (touch) {
- this._touchDown = false;
- this._touchEndedPoint.x = touch.getLocation().x;
- this._touchEndedPoint.y = touch.getLocation().y;
- var selectedWidgetArray = this._selectedWidgets;
- for (var i = 0; i < selectedWidgetArray.length; ++i) {
- var hitWidget = selectedWidgetArray[i];
- hitWidget.onTouchEnded(this._touchEndedPoint);
- }
- this._selectedWidgets = [];
- },
-
- onTouchCancelled: function (touch) {
- this._touchDown = false;
- this._touchEndedPoint.x = touch.getLocation().x;
- this._touchEndedPoint.y = touch.getLocation().y;
- var selectedWidgetArray = this._selectedWidgets;
- for (var i = 0; i < selectedWidgetArray.length; ++i) {
- var hitWidget = selectedWidgetArray[i];
- hitWidget.onTouchCancelled(this._touchEndedPoint);
- }
- this._selectedWidgets = [];
- },
-
- setRootWidget: function (root) {
- this._rootWidget = root;
- },
-
- getRootWidget: function () {
- return this._rootWidget;
- }
-});
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/System/UILayer.js b/extensions/CocoStudio/GUI/System/UILayer.js
deleted file mode 100644
index d929bbda3b..0000000000
--- a/extensions/CocoStudio/GUI/System/UILayer.js
+++ /dev/null
@@ -1,133 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.UILayer
- * @class
- * @extends cc.Layer
- */
-cc.UILayer = cc.Layer.extend({
- _rootWidget: null,
- _inputManager: null,
- init: function () {
- if (cc.Layer.prototype.init.call(this)) {
- this._rootWidget = cc.UIRootWidget.create();
- this._rootWidget.onEnter();
- this.addChild(this._rootWidget.getRenderer());
- this._inputManager = new cc.UIInputManager();
- this._inputManager.setRootWidget(this._rootWidget);
- return true;
- }
- return false;
- },
-
- onEnter: function () {
- this.setTouchMode(cc.TOUCH_ONE_BY_ONE);
- this.setTouchEnabled(true);
- cc.Layer.prototype.onEnter.call(this);
-
- },
-
- onExit: function () {
- this.setTouchEnabled(false);
- cc.Layer.prototype.onExit.call(this);
- },
-
- onEnterTransitionDidFinish: function () {
- cc.Layer.prototype.onEnterTransitionDidFinish.call(this);
- },
-
- addWidget: function (widget) {
- this._rootWidget.addChild(widget);
- },
-
- removeWidget: function (widget) {
- this._rootWidget.removeChild(widget);
- },
-
- setVisible: function (visible) {
- cc.Layer.prototype.setVisible.call(this,visible);
- this._rootWidget.setVisible(visible);
- },
-
- getWidgetByTag: function (tag) {
- if (!this._rootWidget) {
- return null;
- }
- return cc.UIHelper.getInstance().seekWidgetByTag(this._rootWidget, tag);
- },
-
- getWidgetByName: function (name) {
- if (!this._rootWidget) {
- return null;
- }
- return cc.UIHelper.getInstance().seekWidgetByName(this._rootWidget, name);
- },
-
- getRootWidget: function () {
- return this._rootWidget;
- },
-
- getInputManager: function () {
- return this._inputManager;
- },
-
- clear: function () {
- this._rootWidget.removeAllChildren();
- },
-
- onTouchBegan: function (touch, event) {
- if (this._inputManager && this._inputManager.onTouchBegan(touch)) {
- return true;
- }
- return false;
- },
-
- onTouchMoved: function (touch, event) {
- this._inputManager.onTouchMoved(touch);
- },
-
- onTouchEnded: function (touch, event) {
- this._inputManager.onTouchEnded(touch);
- },
-
- onTouchCancelled: function (touch, event) {
- this._inputManager.onTouchCancelled(touch);
- },
-
- dispose: function () {
- this.removeFromParent(true);
- },
-
- removeWidgetAndCleanUp: function (widget, cleanup) {
- this.removeWidget(widget);
- }
-});
-cc.UILayer.create = function () {
- var uiLayer = new cc.UILayer();
- if (uiLayer && uiLayer.init()) {
- return uiLayer;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIDragPanel.js b/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIDragPanel.js
deleted file mode 100644
index 3b70d5946c..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIDragPanel.js
+++ /dev/null
@@ -1,1258 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-/**
- * drag panel move type
- */
-cc.DRAGPANEL_MOVE_TYPE = {
- NONE: 0,
- AUTOMOVE: 1,
- BOUNCE: 2
-};
-
-/**
- * dragpanel berth direction
- */
-cc.DRAGPANEL_BERTH_DIR = {
- NONE: 0,
- LEFTBOTTOM: 1,
- LFETTOP: 2,
- RIGHTBOTTOM: 3,
- RIGHTTOP: 4,
- LEFT: 5,
- TOP: 6,
- RIGHT: 7,
- BOTTOM: 8
-};
-
-/**
- * dragpanel bounce direction
- */
-cc.DRAGPANEL_BOUNCE_DIR = {
- NONE: 0,
- LEFTBOTTOM: 1,
- LEFTTOP: 2,
- RIGHTBOTTOM: 3,
- RIGHTTOP: 4,
- LEFT: 5,
- TOP: 6,
- RIGHT: 7,
- BOTTOM: 8
-};
-
-cc.DragPanelEventType = {
- BERTH_LEFTBOTTOM: 0,
- BERTH_LFETTOP: 1,
- BERTH_RIGHTBOTTOM: 2,
- BERTH_RIGHTTOP: 3,
- BERTH_LEFT: 4,
- BERTH_TOP: 5,
- BERTH_RIGHT: 6,
- BERTH_BOTTOM: 7,
- BOUNCE_LEFTBOTTOM: 8,
- BOUNCE_LEFTTOP: 9,
- BOUNCE_RIGHTBOTTOM: 10,
- BOUNCE_RIGHTTOP: 11,
- BOUNCE_LEFT: 12,
- BOUNCE_TOP: 13,
- BOUNCE_RIGHT: 14,
- BOUNCE_BOTTOM: 15
-};
-
-/**
- * Base class for cc.UIDragPanel
- * @class
- * @extends cc.Layout
- */
-cc.UIDragPanel = cc.Layout.extend({
- _innerContainer: null,
- _touchPressed: false,
- _touchMoved: false,
- _touchReleased: false,
- _touchCanceld: false,
- _touchStartNodeSpace: null,
- _touchStartWorldSpace: null,
- _touchEndWorldSpace: null,
- _slidTime: 0,
- _moveType: null,
- _autoMoveDuration: 0,
- _autoMoveEaseRate: 0,
- _berthDirection: null,
- _bounceEnable: 0,
- _bounceDirection: null,
- _bounceDuration: 0,
- _bounceEaseRate: 0,
- _eventLister: null,
- _eventSelector: null,
- _runningAction: 0,
- _actionType: null,
- _actionWidget: null,
- _duration: 0,
- _elapsed: 0,
- _firstTick: false,
- _positionDelta: null,
- _startPosition: null,
- _previousPosition: null,
- _endPosition: null,
-
- ctor: function () {
- cc.Layout.prototype.ctor.call(this);
- this._innerContainer = null;
- this._touchPressed = false;
- this._touchMoved = false;
- this._touchReleased = false;
- this._touchCanceld = false; // check touch out of drag panel boundary
- this._touchStartNodeSpace = cc.p(0, 0);
- this._touchStartWorldSpace = cc.p(0, 0);
- this._touchEndWorldSpace = cc.p(0, 0);
- this._slidTime = 0;
- this._moveType = cc.DRAGPANEL_MOVE_TYPE.AUTOMOVE;
- this._autoMoveDuration = 0.5;
- this._autoMoveEaseRate = 2.0;
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.NONE;
- this._bounceEnable = 0;
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.NONE;
- this._bounceDuration = 0;
- this._eventLister = null;
- this._eventSelector = null;
- this._runningAction = 0;
- this._actionType = null;
- this._actionWidget = null;
- this._duration = 0;
- this._elapsed = 0;
- this._firstTick = false;
- this._positionDelta = cc.p(0, 0);
- this._startPosition = cc.p(0, 0);
- this._previousPosition = cc.p(0, 0);
- this._endPosition = cc.p(0, 0);
- },
-
- init: function () {
- if (cc.Layout.prototype.init.call(this)) {
- this.setUpdateEnabled(true);
- this.setTouchEnabled(true);
- this.setClippingEnabled(true);
- return true;
- }
- return false;
- },
-
- initRenderer: function () {
- cc.Layout.prototype.initRenderer.call(this);
- this._innerContainer = cc.Layout.create();
- cc.Layout.prototype.addChild.call(this, this._innerContainer);
-
- },
-
- releaseResoures: function () {
- this.setUpdateEnabled(false);
- this.removeAllChildren();
- this._renderer.removeAllChildren(true);
- this._renderer.removeFromParent(true);
- cc.Layout.prototype.removeChild.call(this, this._innerContainer);
- this._children = [];
- },
-
- onTouchBegan: function (touchPoint) {
- var pass = cc.Layout.prototype.onTouchBegan.call(this, touchPoint);
- this.handlePressLogic(touchPoint);
- return pass;
- },
-
- onTouchMoved: function (touchPoint) {
- cc.Layout.prototype.onTouchMoved.call(this,touchPoint);
- this.handleMoveLogic(touchPoint);
- },
-
- onTouchEnded: function (touchPoint) {
- cc.Layout.prototype.onTouchEnded.call(this,touchPoint);
- this.handleReleaseLogic(touchPoint);
- },
-
- onTouchCancelled: function (touchPoint) {
- cc.Layout.prototype.onTouchCancelled.call(this,touchPoint);
- },
-
- onTouchLongClicked: function (touchPoint) {
-
- },
-
- update: function (dt) {
- // widget action
- if (this._runningAction) {
- if (this.actionIsDone()) {
- this.actionDone();
- this.actionStop();
- }
- else {
- this.actionStep(dt);
- }
- }
-
- this.recordSlidTime(dt);
- },
-
- /**
- * add widget child override
- * @param {cc.UIWidget} widget
- * @returns {boolean}
- */
- addChild: function (widget) {
- this._innerContainer.addChild(widget);
- return true;
- },
-
- /**
- * remove widget child override
- * @param {cc.UIWidget} child
- * @returns {boolean}
- */
- removeChild: function (child) {
- var value = false;
- if (this._innerContainer.removeChild(child)) {
- value = true;
- }
-
- return value;
- },
-
- /**
- * remove all widget children override
- */
- removeAllChildren: function () {
- this._innerContainer.removeAllChildren();
- },
-
- /**
- * get widget children of inner container
- * @returns {Array}
- */
- getChildren: function () {
- return this._innerContainer.getChildren();
- },
-
- onSizeChanged: function () {
- cc.Layout.prototype.onSizeChanged.call(this);
- var innerSize = this._innerContainer.getSize();
- var orginInnerSizeWidth = innerSize.width;
- var orginInnerSizeHeight = innerSize.height;
- var innerSizeWidth = Math.max(orginInnerSizeWidth, this._size.width);
- var innerSizeHeight = Math.max(orginInnerSizeHeight, this._size.height);
- this._innerContainer.setSize(cc.size(innerSizeWidth, innerSizeHeight));
- },
-
- /**
- * get and set inner container size
- * @returns {cc.Size}
- */
- getInnerContainerSize: function () {
- return this._innerContainer.getContentSize();
- },
-
- /**
- * set inner container size
- * @returns {cc.Size}
- */
- setInnerContainerSize: function (size) {
- var innerSizeWidth = this._size.width;
- var innerSizeHeight = this._size.height;
- if (size.width < this._size.width) {
- cc.log("Inner width <= scrollview width, it will be force sized!");
- }
- else {
- innerSizeWidth = size.width;
- }
- if (size.height < this._size.height) {
- cc.log("Inner height <= scrollview height, it will be force sized!");
- }
- else {
- innerSizeHeight = size.height;
- }
- this._innerContainer.setSize(cc.size(innerSizeWidth, innerSizeHeight));
- this._innerContainer.setPosition(cc.p(0, this._size.height - this._innerContainer.getSize().height));
- },
-
- getInnerContainerPosition: function () {
- return this._innerContainer.getPosition();
- },
-
- setInnerContainerPosition: function (point, animated) {
- var delta = cc.pSub(point, this._innerContainer.getPosition());
- this.setInnerContainerOffset(delta, animated);
- },
-
- /**
- * Set inner container offset
- * @param {cc.Point} offset
- * @param {Boolean} animated
- */
- setInnerContainerOffset: function (offset, animated) {
- if (animated) {
- var delta = offset;
-
- if (this.checkToBoundaryWithDeltaPosition(delta)) {
- delta = this.calculateToBoundaryDeltaPosition(delta);
- }
- this.actionStartWithWidget(this._innerContainer);
- this.moveByWithDuration(this._autoMoveDuration, delta);
- }
- else {
- var delta = offset;
-
- if (this.checkToBoundaryWithDeltaPosition(delta)) {
- delta = this.calculateToBoundaryDeltaPosition(delta);
- }
- this.moveWithDelta(delta);
- if (this.checkBerth()) {
- this.berthEvent();
- }
- }
- },
-
- handlePressLogic: function (touchPoint) {
- // check inner rect < drag panel rect
- if (this.checkContainInnerRect()) {
- this._touchPressed = false;
- return;
- }
-
- this._touchPressed = true;
- this._touchMoved = false;
- this._touchReleased = false;
- this._touchCanceld = false;
-
- if (this._runningAction) {
- switch (this._moveType) {
- case cc.DRAGPANEL_MOVE_TYPE.AUTOMOVE:
- this.stopAutoMove();
- this.actionStop();
- break;
-
- case cc.DRAGPANEL_MOVE_TYPE.BOUNCE:
- this._touchPressed = false;
- break;
-
- default:
- break;
- }
- }
-
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- this._touchStartNodeSpace = nsp;
-
- this._touchStartWorldSpace = touchPoint;
- },
-
- handleMoveLogic: function (touchPoint) {
- if (!this._touchPressed) {
- return;
- }
-
- // check touch out of drag panel boundary
- if (this._touchCanceld) {
- return;
- }
-
- this._touchMoved = true;
-
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- var delta = cc.pSub(nsp, this._touchStartNodeSpace);
- this._touchStartNodeSpace = nsp;
-
- // reset berth dir to none
- if (!this._bounceEnable) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.NONE;
- }
-
- // check will berth (bounce disable)
- if (!this._bounceEnable) {
- if (this.checkToBoundaryWithDeltaPosition(delta)) {
- delta = this.calculateToBoundaryDeltaPosition(delta);
- }
- }
- // move
- this.moveWithDelta(delta);
- // check bounce or berth
- if (this._bounceEnable) {
- // bounce
- if (!this.hitTest(touchPoint)) {
- this._touchMoved = false;
-
- if (this.checkNeedBounce()) {
- this._touchCanceld = true;
- this.startBounce();
- }
- }
- }
- else {
- // berth
- if (this.checkBerth()) {
- this.berthEvent();
- }
- }
- },
-
- handleReleaseLogic: function (touchPoint) {
- if (!this._touchPressed) {
- return;
- }
-
- this._touchPressed = false;
- this._touchMoved = false;
- this._touchReleased = true;
- this._touchCanceld = false;
-
- // check touch out of drag panel boundary
- if (this._touchCanceld) {
- return;
- }
-
- if (this.hitTest(touchPoint)) {
- this._touchEndWorldSpace = touchPoint;
- this.startAutoMove();
- }
- },
-
- /**
- *
- * @param {number} handleState
- * @param {cc.UIWidget} sender
- * @param {cc.Point} touchPoint
- */
- checkChildInfo: function (handleState, sender, touchPoint) {
- this.interceptTouchEvent(handleState, sender, touchPoint);
- },
-
- /**
- *
- * @param {number} handleState
- * @param {cc.UIWidget} sender
- * @param {cc.Point} touchPoint
- */
- interceptTouchEvent: function (handleState, sender, touchPoint) {
- switch (handleState) {
- case 0:
- this.handlePressLogic(touchPoint);
- break;
- case 1:
- var offset = cc.pDistance(sender.getTouchStartPos(), touchPoint);
- if (offset > 5.0) {
- sender.setFocused(false);
- this.handleMoveLogic(touchPoint);
- }
- break;
- case 2:
- this.handleReleaseLogic(touchPoint);
- break;
- case 3:
- break;
- }
- },
-
- recordSlidTime: function (dt) {
- if (this._touchPressed) {
- this._slidTime += dt;
- }
- },
-
- /**
- * check if dragpanel rect contain inner rect
- * @returns {boolean}
- */
- checkContainInnerRect: function () {
- var width = this._size.width;
- var height = this._size.height;
- var innerWidth = this._innerContainer.getSize().width;
- var innerHeight = this._innerContainer.getSize().height;
-
- if (innerWidth <= width && innerHeight <= height) {
- return true;
- }
- return false;
- },
-
- /**
- * move
- * @param delta
- */
- moveWithDelta: function (delta) {
- var newPos = cc.pAdd(this._innerContainer.getPosition(), delta);
- this._innerContainer.setPosition(newPos);
- },
-
- /**
- * auto move
- */
- autoMove: function () {
- if (this._bounceEnable) {
- if (this.checkNeedBounce()) {
- this.stopAutoMove();
- this.startBounce();
- }
- }
- },
-
- autoMoveOver: function () {
- this.stopAutoMove();
-
- if (this.checkBerth()) {
- this.berthEvent();
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.NONE;
- }
- },
-
- startAutoMove: function () {
- this._moveType = cc.DRAGPANEL_MOVE_TYPE.AUTOMOVE;
-
- this.actionStop();
-
- var delta = cc.pSub(this._touchEndWorldSpace, this._touchStartWorldSpace);
- delta.x /= this._slidTime * 60;
- delta.y /= this._slidTime * 60;
- this._slidTime = 0.0;
-
- // bounceEnable is disable
- if (!this._bounceEnable) {
- if (this.checkToBoundaryWithDeltaPosition(delta)) {
- delta = this.calculateToBoundaryDeltaPosition(delta);
- }
- }
- this.actionStartWithWidget(this._innerContainer);
- this.moveByWithDuration(this._autoMoveDuration, delta);
- },
-
- stopAutoMove: function () {
- this._moveType = cc.DRAGPANEL_MOVE_TYPE.NONE;
- },
-
- /**
- * Set auto move duration
- * @param {Number} duration
- */
- setAutoMoveDuration: function (duration) {
- this._autoMoveDuration = duration;
- },
-
- /**
- * Set auto move ease rate
- * @param {Number} rate
- */
- setAutoMoveEaseRate: function (rate) {
- this._autoMoveEaseRate = rate;
- },
-
- /**
- * check if move to boundary with update
- * @param {number} delta
- * @returns {boolean}
- */
- checkToBoundaryWithDeltaPosition: function (delta) {
- var innerLeft = this._innerContainer.getLeftInParent();
- var innerTop = this._innerContainer.getTopInParent();
- var innerRight = this._innerContainer.getRightInParent();
- var innerBottom = this._innerContainer.getBottomInParent();
-
- var left = 0;
- var top = this._size.height;
- var right = this._size.width;
- var bottom = 0;
-
- var toLeftBottom = false;
- var toLeftTop = false;
- var toRightBottom = false;
- var toRightTop = false;
- var toLeft = false;
- var toRight = false;
- var toTop = false;
- var toBottom = false;
-
- // left bottom
- if (innerLeft + delta.x > left && innerBottom + delta.y > bottom) {
- toLeftBottom = true;
- }
- // left top
- else if (innerLeft + delta.x > left && innerTop + delta.y < top) {
- toLeftTop = true;
- }
- // right bottom
- else if (innerRight + delta.x < right && innerBottom + delta.y > bottom) {
- toRightBottom = true;
- }
- // right top
- else if (innerRight + delta.x < right && innerTop + delta.y < top) {
- toRightTop = true;
- }
- // left
- else if (innerLeft + delta.x > left) {
- toLeft = true;
- }
- // right
- else if (innerRight + delta.x < right) {
- toRight = true;
- }
- // top
- else if (innerTop + delta.y < top) {
- toTop = true;
- }
- // bottom
- else if (innerBottom + delta.y > bottom) {
- toBottom = true;
- }
-
- if (toLeft || toTop || toRight || toBottom
- || toLeftBottom || toLeftTop || toRightBottom || toRightTop) {
- return true;
- }
-
- return false;
- },
-
- /**
- * calculate to boundary delta
- * @param {cc.Point} paramDelta
- * @returns {cc.Point}
- */
- calculateToBoundaryDeltaPosition: function (paramDelta) {
- var innerLeft = this._innerContainer.getLeftInParent();
- var innerTop = this._innerContainer.getTopInParent();
- var innerRight = this._innerContainer.getRightInParent();
- var innerBottom = this._innerContainer.getBottomInParent();
-
- var left = 0;
- var top = this._size.height;
- var right = this._size.width;
- var bottom = 0;
-
- var delta = paramDelta;
-
- // left bottom
- if (innerLeft + delta.x > left && innerBottom + delta.y > bottom) {
- delta.x = left - innerLeft;
- delta.y = bottom - innerBottom;
- }
- // left top
- else if (innerLeft + delta.x > left && innerTop + delta.y < top) {
- delta.x = left - innerLeft;
- delta.y = top - innerTop;
- }
- // right bottom
- else if (innerRight + delta.x < right && innerBottom + delta.y > bottom) {
- delta.x = right - innerRight;
- delta.y = bottom - innerBottom;
- }
- // right bottom
- else if (innerRight + delta.x < right && innerTop + delta.y < top) {
- delta.x = right - innerRight;
- delta.y = top - innerTop;
- }
- // left
- else if (innerLeft + delta.x > left) {
- delta.x = left - innerLeft;
- }
- // right
- else if (innerRight + delta.x < right) {
- delta.x = right - innerRight;
- }
- // top
- else if (innerTop + delta.y < top) {
- delta.y = top - innerTop;
- }
- // bottom
- else if (innerBottom + delta.y > bottom) {
- delta.y = bottom - innerBottom;
- }
-
- return delta;
- },
-
- /**
- * get berth or not
- * @returns {boolean}
- */
- isBerth: function () {
- return this._berthDirection != cc.DRAGPANEL_BERTH_DIR.NONE;
- },
-
- /**
- * Check berth
- * @returns {boolean}
- */
- checkBerth: function () {
- var innerLeft = this._innerContainer.getLeftInParent();
- var innerTop = this._innerContainer.getTopInParent();
- var innerRight = this._innerContainer.getRightInParent();
- var innerBottom = this._innerContainer.getBottomInParent();
-
- var left = 0;
- var top = this._size.height;
- var right = this._size.width;
- var bottom = 0;
-
- // left bottom
- if (innerLeft == left && innerBottom == bottom) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.LEFTBOTTOM;
- }
- // left top
- else if (innerLeft == left && innerTop == top) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.LFETTOP;
- }
- // right bottom
- else if (innerRight == right && innerBottom == bottom) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.RIGHTBOTTOM;
- }
- // right top
- else if (innerRight == right && innerTop == top) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.RIGHTTOP;
- }
- // left
- else if (innerLeft == left) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.LEFT;
- }
- // right
- else if (innerRight == right) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.RIGHT;
- }
- // top
- else if (innerTop == top) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.TOP;
- }
- // bottom
- else if (innerBottom == bottom) {
- this._berthDirection = cc.DRAGPANEL_BERTH_DIR.BOTTOM;
- }
-
- if (this._berthDirection != cc.DRAGPANEL_BERTH_DIR.NONE) {
- return true;
- }
-
- return false;
- },
-
- /**
- * Berth event
- */
- berthEvent: function () {
- switch (this._berthDirection) {
- case cc.DRAGPANEL_BERTH_DIR.LEFTBOTTOM:
- this.berthToLeftBottomEvent();
- break;
-
- case cc.DRAGPANEL_BERTH_DIR.LFETTOP:
- this.berthToLeftTopEvent();
- break;
-
- case cc.DRAGPANEL_BERTH_DIR.RIGHTBOTTOM:
- this.berthToRightBottomEvent();
- break;
-
- case cc.DRAGPANEL_BERTH_DIR.RIGHTTOP:
- this.berthToRightTopEvent();
- break;
-
- case cc.DRAGPANEL_BERTH_DIR.LEFT:
- this.berthToLeftEvent();
- break;
-
- case cc.DRAGPANEL_BERTH_DIR.TOP:
- this.berthToTopEvent();
- break;
-
- case cc.DRAGPANEL_BERTH_DIR.RIGHT:
- this.berthToRightEvent();
- break;
-
- case cc.DRAGPANEL_BERTH_DIR.BOTTOM:
- this.berthToBottomEvent();
- break;
-
- default:
- break;
- }
- },
-
- berthToLeftBottomEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_LEFTBOTTOM);
- }
- },
-
- berthToLeftTopEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_LFETTOP);
- }
- },
-
- berthToRightBottomEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_RIGHTBOTTOM);
- }
- },
-
- berthToRightTopEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_RIGHTTOP);
- }
- },
-
- berthToLeftEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_LEFT);
- }
- },
-
- berthToTopEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_TOP);
- }
- },
-
- berthToRightEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_RIGHT);
- }
- },
-
- berthToBottomEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BERTH_BOTTOM)
- }
- },
-
- /**
- *
- * @param {Object} target
- * @param {Function} selector
- */
- addEventListener: function (target, selector) {
- this._eventLister = target;
- this._eventSelector = selector;
- },
-
- /**
- * Get and set bounce enable
- * @returns {number}
- */
- isBounceEnabled: function () {
- return this._bounceEnable;
- },
-
- /**
- * Set and set bounce enable
- * @param {Boolean} bounce
- */
- setBounceEnabled: function (bounce) {
- this._bounceEnable = bounce;
- },
-
- /**
- * Check is need bounce
- * @returns {boolean}
- */
- checkNeedBounce: function () {
- var innerLeft = this._innerContainer.getLeftInParent();
- var innerTop = this._innerContainer.getTopInParent();
- var innerRight = this._innerContainer.getRightInParent();
- var innerBottom = this._innerContainer.getBottomInParent();
-
- var left = 0;
- var top = this._size.height;
- var right = this._size.width;
- var bottom = 0;
-
- var need = ((innerLeft > left && innerBottom > bottom)
- || (innerLeft > left && innerTop < top)
- || (innerRight < right && innerBottom > bottom)
- || (innerRight < right && innerTop < top)
- || (innerLeft > left)
- || (innerTop < top)
- || (innerRight < right)
- || (innerBottom > bottom));
- return need;
- },
-
- startBounce: function () {
- if (this._moveType == cc.DRAGPANEL_MOVE_TYPE.BOUNCE) {
- return;
- }
-
- this.actionStop();
- this._moveType = cc.DRAGPANEL_MOVE_TYPE.BOUNCE;
- this.bounceToCorner();
- },
-
- stopBounce: function () {
- this._moveType = cc.DRAGPANEL_MOVE_TYPE.NONE;
- },
-
- bounceToCorner: function () {
- var innerLeft = this._innerContainer.getLeftInParent();
- var innerTop = this._innerContainer.getTopInParent();
- var innerRight = this._innerContainer.getRightInParent();
- var innerBottom = this._innerContainer.getBottomInParent();
-
- var width = this._size.width;
- var height = this._size.height;
- var left = 0;
- var top = height;
- var right = width;
- var bottom = 0;
-
- var from_x = 0;
- var from_y = 0;
- var to_x = 0;
- var to_y = 0;
- var delta = cc.p(0, 0);
-
- // left bottom
- if (innerLeft > left && innerBottom > bottom) {
- from_x = innerLeft;
- from_y = innerBottom;
- to_x = left;
- to_y = bottom;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.LEFTBOTTOM;
- }
- // left top
- else if (innerLeft > left && innerTop < top) {
- from_x = innerLeft;
- from_y = innerTop;
- to_x = left;
- to_y = top;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.LEFTTOP;
- }
- // right bottom
- else if (innerRight < right && innerBottom > bottom) {
- from_x = innerRight;
- from_y = innerBottom;
- to_x = right;
- to_y = bottom;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.RIGHTBOTTOM;
- }
- // right top
- else if (innerRight < right && innerTop < top) {
- from_x = innerRight;
- from_y = innerTop;
- to_x = right;
- to_y = top;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.RIGHTTOP;
- }
- // left
- else if (innerLeft > left) {
- from_x = innerLeft;
- from_y = innerBottom;
- to_x = left;
- to_y = from_y;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.LEFT;
- }
- // top
- else if (innerTop < top) {
- from_x = innerLeft;
- from_y = innerTop;
- to_x = from_x;
- to_y = top;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.TOP;
- }
- // right
- else if (innerRight < right) {
- from_x = innerRight;
- from_y = innerBottom;
- to_x = right;
- to_y = from_y;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.RIGHT;
- }
- // bottom
- else if (innerBottom > bottom) {
- from_x = innerLeft;
- from_y = innerBottom;
- to_x = from_x;
- to_y = bottom;
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.BOTTOM;
- }
- delta = cc.pSub(cc.p(to_x, to_y), cc.p(from_x, from_y));
-
- this.actionStartWithWidget(this._innerContainer);
- this.moveByWithDuration(this._bounceDuration, delta);
- },
-
- bounceOver: function () {
- this.stopBounce();
-
- switch (this._bounceDirection) {
- case cc.DRAGPANEL_BOUNCE_DIR.LEFTBOTTOM:
- this.bounceToLeftBottomEvent();
- break;
-
- case cc.DRAGPANEL_BOUNCE_DIR.LEFTTOP:
- this.bounceToLeftTopEvent();
- break;
-
- case cc.DRAGPANEL_BOUNCE_DIR.RIGHTBOTTOM:
- this.bounceToRightBottomEvent();
- break;
-
- case cc.DRAGPANEL_BOUNCE_DIR.RIGHTTOP:
- this.bounceToRightTopEvent();
- break;
-
- case cc.DRAGPANEL_BOUNCE_DIR.LEFT:
- this.bounceToLeftEvent();
- break;
-
- case cc.DRAGPANEL_BOUNCE_DIR.TOP:
- this.bounceToTopEvent();
- break;
-
- case cc.DRAGPANEL_BOUNCE_DIR.RIGHT:
- this.bounceToRightEvent();
- break;
-
- case cc.DRAGPANEL_BOUNCE_DIR.BOTTOM:
- this.bounceToBottomEvent();
- break;
-
- default:
- break;
- }
-
- this._bounceDirection = cc.DRAGPANEL_BOUNCE_DIR.NONE;
- },
-
- bounceToLeftBottomEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_LEFTBOTTOM);
- }
-
- },
-
- bounceToLeftTopEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_LEFTTOP);
- }
- },
-
- bounceToRightBottomEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_RIGHTBOTTOM);
- }
- },
-
- bounceToRightTopEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_RIGHTTOP);
- }
- },
-
- bounceToLeftEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_LEFT);
- }
- },
-
- bounceToTopEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_TOP);
- }
-
- },
-
- bounceToRightEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_RIGHT);
- }
-
- },
-
- bounceToBottomEvent: function () {
- if (this._eventLister && this._eventSelector) {
- this._eventSelector.call(this._eventLister, this, cc.DragPanelEventType.BOUNCE_BOTTOM);
- }
- },
-
- /**
- * Set duration
- * @param {number} duration
- */
- actionWithDuration: function (duration) {
- this._duration = duration;
-
- if (this._duration == 0) {
- this._duration = 0.0000001192092896;
- }
-
- this._elapsed = 0;
- this._firstTick = true;
- },
-
- actionIsDone: function () {
- var value = (this._elapsed >= this._duration);
- return value;
- },
-
- actionStartWithWidget: function (widget) {
- this._runningAction = true;
- this._actionWidget = widget;
- },
-
- actionStep: function (dt) {
- if (this._firstTick) {
- this._firstTick = false;
- this._elapsed = 0;
- }
- else {
- this._elapsed += dt;
- }
-
- this.actionUpdate(Math.max(0, Math.min(1, this._elapsed / Math.max(this._duration, 0.0000001192092896))));
- },
-
- actionUpdate: function (dt) {
- switch (this._actionType) {
- case 1: // move by
- this.moveByUpdate(dt);
- break;
-
- case 2: // move to
- this.moveToUpdate(dt);
- break;
-
- default:
- break;
- }
- },
-
- actionStop: function () {
- this._runningAction = false;
- },
-
- actionDone: function () {
- switch (this._moveType) {
- case cc.DRAGPANEL_MOVE_TYPE.AUTOMOVE:
- this.autoMoveOver();
- break;
-
- case cc.DRAGPANEL_MOVE_TYPE.BOUNCE:
- this.bounceOver();
- break;
-
- default:
- break;
- }
- },
-
- moveByWithDuration: function (duration, deltaPosition) {
- this.actionWithDuration(duration);
- this._positionDelta = deltaPosition;
- this.moveByInit();
- this._actionType = 1;
- },
-
- moveByInit: function () {
- this._previousPosition = this._startPosition = this._actionWidget.getPosition();
- },
-
- moveByUpdate: function (t) {
- var easeRate = 0.0;
- switch (this._moveType) {
- case cc.DRAGPANEL_MOVE_TYPE.AUTOMOVE:
- easeRate = this._autoMoveEaseRate;
- break;
-
- case cc.DRAGPANEL_MOVE_TYPE.BOUNCE:
- easeRate = this._bounceEaseRate;
- break;
-
- default:
- break;
- }
- t = Math.pow(t, 1 / easeRate);
-
- var currentPos = this._actionWidget.getPosition();
- var diff = cc.pSub(currentPos, this._previousPosition);
- this._startPosition = cc.pAdd(this._startPosition, diff);
-
- var newPos = cc.pAdd(this._startPosition, cc.pMult(this._positionDelta, t));
- this._actionWidget.setPosition(newPos);
- this._previousPosition = newPos;
-
- switch (this._moveType) {
- case cc.DRAGPANEL_MOVE_TYPE.AUTOMOVE:
- this.autoMove();
- break;
-
- default:
- break;
- }
- },
-
- moveToWithDuration: function (duration, position) {
- this.actionWithDuration(duration);
- this._endPosition = position;
- this.moveToInit();
- this._actionType = 2;
- },
-
- moveToInit: function () {
- this.moveByInit();
- this._positionDelta = cc.pSub(this._endPosition, this._actionWidget.getPosition());
- },
-
- moveToUpdate: function (t) {
- this.moveByUpdate(t);
- },
-
- getInnerContainer: function () {
- return this._innerContainer;
- },
-
- setLayoutType: function (type) {
- this._innerContainer.setLayoutType(type);
- },
-
- getLayoutType: function () {
- return this._innerContainer.getLayoutType();
- },
-
- doLayout: function () {
- this._innerContainer.doLayout();
- },
-
- getDescription: function () {
- return "DragPanel";
- }
-});
-cc.UIDragPanel.create = function () {
- var uiDragPanel = new cc.UIDragPanel();
- if (uiDragPanel && uiDragPanel.init()) {
- return uiDragPanel;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIListView.js b/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIListView.js
deleted file mode 100644
index abf812e6c3..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIListView.js
+++ /dev/null
@@ -1,1275 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * list view direction
- */
-cc.ListViewDirection = {
- NONE: 0,
- VERTICAL: 1,
- HORIZONTAL: 2
-};
-
-/**
- * list view scroll direction
- */
-cc.ListViewMoveDirection = {
- NONE: 0,
- UP: 1,
- DOWN: 2,
- LEFT: 3,
- RIGHT: 4
-};
-
-cc.ListViewEventType = {
- INIT_CHILD: 0,
- UPDATE_CHILD: 1
-};
-
-/**
- * Base class for cc.UIListView
- * @class
- * @extends cc.Layout
- */
-cc.UIListView = cc.Layout.extend({
- _direction: null,
- _moveDirection: null,
- _touchStartLocation: 0,
- _touchEndLocation: 0,
- _touchMoveStartLocation: 0,
- _topBoundary: 0,//test
- _bottomBoundary: 0,//test
- _leftBoundary: 0,
- _rightBoundary: 0,
- _autoScroll: false,
- _autoScrollOriginalSpeed: 0,
- _autoScrollAcceleration: 0,
- _bePressed: false,
- _slidTime: 0,
- _moveChildPoint: null,
- _childFocusCancelOffset: 0,
- _childPool: null,
- _updatePool: null,
- _dataLength: 0,
- _begin: 0,
- _end: 0,
- _updateChild: null,
- _updateDataIndex: 0,
- _updateSuccess: false,
- _overTopArray: null,
- _overBottomArray: null,
- _overLeftArray: null,
- _overRightArray: null,
- _disBoundaryToChild_0: 0,
- _disBetweenChild: 0,
-
- _eventListener: null,
- _eventSelector: null,
- ctor: function () {
- cc.Layout.prototype.ctor.call(this);
-
- this._direction = cc.ListViewDirection.VERTICAL;
- this._moveDirection = cc.ListViewMoveDirection.NONE;
- this._touchStartLocation = 0;
- this._touchEndLocation = 0;
- this._touchMoveStartLocation = 0;
- this._topBoundary = 0;//test
- this._bottomBoundary = 0;//test
- this._leftBoundary = 0;
- this._rightBoundary = 0;
- this._autoScroll = false;
- this._autoScrollOriginalSpeed = 0;
- this._autoScrollAcceleration = 600;
- this._bePressed = false;
- this._slidTime = 0;
- this._moveChildPoint = null;
- this._childFocusCancelOffset = 50;
- this._childPool = [];
- this._updatePool = [];
- this._dataLength = 0;
- this._begin = 0;
- this._end = 0;
- this._updateChild = null;
- this._updateDataIndex = -1;
- this._updateSuccess = false;
- this._overTopArray = [];
- this._overBottomArray = [];
- this._overLeftArray = [];
- this._overRightArray = [];
- this._disBoundaryToChild_0 = 0;
- this._disBetweenChild = 0;
- this._eventListener = null;
- this._eventSelector = null;
- },
- init: function () {
- if (cc.Layout.prototype.init.call(this)) {
- this.setUpdateEnabled(true);
- this.setTouchEnabled(true);
- this.setClippingEnabled(true);
- this._childPool = [];
- this._updatePool = [];
- this._overTopArray = [];
- this._overBottomArray = [];
- this._overLeftArray = [];
- this._overRightArray = [];
- return true;
- }
- return false;
- },
-
- onSizeChanged: function () {
- cc.Layout.prototype.onSizeChanged.call(this);
- this._topBoundary = this._size.height;
- this._rightBoundary = this._size.width;
- },
-
- /**
- * Add widget child override
- * @param {cc.UIWidget} widget
- * @returns {boolean}
- */
- addChild: function (widget) {
- cc.Layout.prototype.addChild.call(this,widget);
- this.resetProperty();
- return true;
- },
-
- /**
- * remove all widget children override
- */
- removeAllChildren: function () {
- this._updatePool = [];
- this._childPool = [];
- cc.Layout.prototype.removeAllChildren.call(this);
- },
-
- /**
- * remove widget child override
- * @param {cc.UIWidget} child
- * @returns {boolean}
- */
- removeChild: function (child) {
- var value = false;
-
- if (cc.Layout.prototype.removeChild.call(this,child)) {
- value = true;
- this.resetProperty();
- }
-
- return value;
- },
-
- onTouchBegan: function (touchPoint) {
- var pass = cc.Layout.prototype.onTouchBegan.call(this,touchPoint);
- this.handlePressLogic(touchPoint);
- return pass;
- },
-
- onTouchMoved: function (touchPoint) {
- cc.Layout.prototype.onTouchMoved.call(this,touchPoint);
- this.handleMoveLogic(touchPoint);
- },
-
- onTouchEnded: function (touchPoint) {
- cc.Layout.prototype.onTouchEnded.call(this,touchPoint);
- this.handleReleaseLogic(touchPoint);
- },
-
- onTouchCancelled: function (touchPoint) {
- cc.Layout.prototype.onTouchCancelled.call(this,touchPoint);
- },
-
- onTouchLongClicked: function (touchPoint) {
-
- },
-
- update: function (dt) {
- if (this._autoScroll) {
- this.autoScrollChildren(dt);
- }
- this.recordSlidTime(dt);
- },
-
- /**
- * direction setter
- * @param {cc.ListViewDirection} dir
- */
- setDirection: function (dir) {
- this._direction = dir;
- },
-
- /**
- * direction getter
- * @param {cc.ListViewDirection} dir
- */
- getDirection: function () {
- return this._direction;
- },
-
- resetProperty: function () {
- var arrayChildren = this._children;
-
- if (arrayChildren.length <= 0) {
- return;
- }
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- if (this._topBoundary == 0) {
- return;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- if (this._rightBoundary == 0) {
- return;
- }
- break;
-
- default:
- break;
- }
-
- var scroll_top = this._topBoundary;
- var scroll_left = this._leftBoundary;
-
- switch (this._children.length) {
- case 1:
- {
- var child_0 = arrayChildren[0];
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- {
- var child_0_top = child_0.getTopInParent();
- this._disBoundaryToChild_0 = scroll_top - child_0_top;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- {
- var child_0_left = child_0.getLeftInParent();
- this._disBoundaryToChild_0 = child_0_left - scroll_left;
- }
- break;
-
- default:
- break;
- }
- }
- break;
-
- default:
- {
- var child_0 = arrayChildren[0];
- var child_1 = arrayChildren[1];
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- {
- var child_0_top = child_0.getTopInParent();
- this._disBoundaryToChild_0 = scroll_top - child_0_top;
- this._disBetweenChild = child_0.getPosition().y - child_1.getPosition().y;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- {
- var child_0_left = child_0.getLeftInParent();
- this._disBoundaryToChild_0 = child_0_left - scroll_left;
- this._disBetweenChild = child_1.getPosition().x - child_0.getPosition().x;
- }
- break;
-
- default:
- break;
- }
- }
- break;
- }
- },
-
- handlePressLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- this._touchMoveStartLocation = nsp.y;
- this._touchStartLocation = nsp.y;
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- this._touchMoveStartLocation = nsp.x;
- this._touchStartLocation = nsp.x;
- break;
-
- default:
- break;
- }
- this.startRecordSlidAction();
- this.clearCollectOverArray();
- },
-
- handleMoveLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- var offset = 0;
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- {
- var moveY = nsp.y;
- offset = moveY - this._touchMoveStartLocation;
- this._touchMoveStartLocation = moveY;
-
- if (offset < 0) {
- this._moveDirection = cc.ListViewMoveDirection.DOWN; // down
- }
- else if (offset > 0) {
- this._moveDirection = cc.ListViewMoveDirection.UP; // up
- }
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- {
- var moveX = nsp.x;
- offset = moveX - this._touchMoveStartLocation;
- this._touchMoveStartLocation = moveX;
-
- if (offset < 0) {
- this._moveDirection = cc.ListViewMoveDirection.LEFT; // left
- }
- else if (offset > 0) {
- this._moveDirection = cc.ListViewMoveDirection.RIGHT; // right
- }
- }
- break;
-
- default:
- break;
- }
- this.scrollChildren(offset);
- },
-
- handleReleaseLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- this._touchEndLocation = nsp.y;
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- this._touchEndLocation = nsp.x;
- break;
-
- default:
- break;
- }
- this.endRecordSlidAction();
- },
-
- /**
- * Intercept touch event
- * @param {number} handleState
- * @param {cc.UIWidget} sender
- * @param {cc.Point} touchPoint
- */
- interceptTouchEvent: function (handleState, sender, touchPoint) {
- switch (handleState) {
- case 0:
- this.handlePressLogic(touchPoint);
- break;
- case 1:
- var offset = 0;
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- offset = Math.abs(sender.getTouchStartPos().y - touchPoint.y);
- break;
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- offset = Math.abs(sender.getTouchStartPos().x - touchPoint.x);
- break;
- default:
- break;
- }
- if (offset > this._childFocusCancelOffset) {
- sender.setFocused(false);
- this.handleMoveLogic(touchPoint);
- }
- break;
- case 2:
- this.handleReleaseLogic(touchPoint);
- break;
-
- case 3:
- break;
- }
- },
-
- /**
- *
- * @param {number} handleState
- * @param {cc.UIWidget} sender
- * @param {cc.Point} touchPoint
- */
- checkChildInfo: function (handleState, sender, touchPoint) {
- this.interceptTouchEvent(handleState, sender, touchPoint);
- },
-
- moveChildren: function (offset) {
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; i++) {
- var child = arrayChildren[i];
- var pos = child.getPosition();
- child.setPosition(cc.p(pos.x, pos.y + offset));
- }
- break;
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; i++) {
- var child = arrayChildren[i];
- var pos = child.getPosition();
- child.setPosition(cc.p(pos.x + offset, pos.y));
- }
- break;
- default:
- break;
- }
- },
-
- scroll_VERTICAL_UP:function(realOffset){
- realOffset = Math.min(realOffset, this._disBetweenChild);
-
- var child_last = this._childPool[this._childPool.length - 1];
- var child_last_bottom = child_last.getBottomInParent();
- var scroll_bottom = this._bottomBoundary;
-
- if (this._end == this._dataLength - 1) {
- if (realOffset > scroll_bottom + this._disBoundaryToChild_0 - child_last_bottom) {
- realOffset = scroll_bottom + this._disBoundaryToChild_0 - child_last_bottom;
- }
- this.moveChildren(realOffset);
- return false;
- }
- this.moveChildren(realOffset);
-
- if (this._end < this._dataLength - 1) {
- this.collectOverTopChild();
- var count = this._overTopArray.length;
- if (count > 0) {
- this.updateChild();
- this.setLoopPosition();
- this._overTopArray = [];
- }
- }
- },
- scroll_VERTICAL_DOWN:function(realOffset){
- realOffset = Math.max(realOffset, -this._disBetweenChild);
-
- var child_0 = this._childPool[0];
- var child_0_top = child_0.getTopInParent();
- var scroll_top = this._topBoundary;
-
- if (this._begin == 0) {
- if (realOffset < scroll_top - this._disBoundaryToChild_0 - child_0_top) {
- realOffset = scroll_top - this._disBoundaryToChild_0 - child_0_top;
- }
- this.moveChildren(realOffset);
- return false;
- }
- this.moveChildren(realOffset);
-
- if (this._begin > 0) {
- this.collectOverBottomChild();
- var count = this._overBottomArray.length;
- if (count > 0) {
- this.updateChild();
- this.setLoopPosition();
- this._overBottomArray = [];
- }
- }
- },
- scroll_HORIZONTAL_LEFT:function(realOffset){
- realOffset = Math.max(realOffset, -this._disBetweenChild);
-
- var child_last = this._childPool[this._childPool.length - 1];
- var child_last_right = child_last.getRightInParent();
- var scroll_right = this._rightBoundary;
-
- if (this._end == this._dataLength - 1) {
- if (realOffset < scroll_right - this._disBoundaryToChild_0 - child_last_right) {
- realOffset = scroll_right - this._disBoundaryToChild_0 - child_last_right;
- }
- this.moveChildren(realOffset);
- return false;
- }
- this.moveChildren(realOffset);
-
- if (this._end < this._dataLength - 1) {
- this.collectOverLeftChild();
- var count = this._overLeftArray.length;
- if (count > 0) {
- this.updateChild();
- this.setLoopPosition();
- this._overLeftArray = [];
- }
- }
- },
- scroll_HORIZONTAL_RIGHT:function(realOffset){
- realOffset = Math.min(realOffset, this._disBetweenChild);
-
- var child_0 = this._childPool[0];
- var child_0_left = child_0.getLeftInParent();
- var scroll_left = this._leftBoundary;
-
- if (this._begin == 0) {
- if (realOffset > scroll_left + this._disBoundaryToChild_0 - child_0_left) {
- realOffset = scroll_left + this._disBoundaryToChild_0 - child_0_left;
- }
- this.moveChildren(realOffset);
- return false;
- }
- this.moveChildren(realOffset);
-
- this.collectOverRightChild();
- var count = this._overRightArray.length;
- if (count > 0) {
- this.updateChild();
- this.setLoopPosition();
- this._overRightArray = [];
- }
- },
- scrollChildren: function (touchOffset) {
- var realOffset = touchOffset;
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- this.scroll_VERTICAL_UP(realOffset);
- break;
- case cc.ListViewMoveDirection.DOWN: // down
- this.scroll_VERTICAL_DOWN(realOffset);
- break;
- default:
- break;
- }
- return true;
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- this.scroll_HORIZONTAL_LEFT(realOffset);
- break;
- case cc.ListViewMoveDirection.RIGHT: // right
- this.scroll_HORIZONTAL_RIGHT(realOffset);
- break;
- default:
- break;
- }
- return true;
- break;
- default:
- break;
- }
- return false;
- },
-
- autoScrollChildren: function (dt) {
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
-
- case cc.ListViewMoveDirection.DOWN: // down
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(-curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
-
- default:
- break;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(-curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
-
- case cc.ListViewMoveDirection.RIGHT: // right
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
- },
-
- getCurAutoScrollDistance: function (dt) {
- this._autoScrollOriginalSpeed -= this._autoScrollAcceleration * dt;
- return this._autoScrollOriginalSpeed * dt;
- },
-
- startAutoScrollChildren: function (v) {
- this._autoScrollOriginalSpeed = v;
- this._autoScroll = true;
- },
-
- stopAutoScrollChildren: function () {
- this._autoScroll = false;
- this._autoScrollOriginalSpeed = 0;
- },
-
- recordSlidTime: function (dt) {
- if (this._bePressed) {
- this._slidTime += dt;
- }
- },
-
- startRecordSlidAction: function () {
- if (this._children.length <= 0) {
- return;
- }
- if (this._autoScroll) {
- this.stopAutoScrollChildren();
- }
- this._bePressed = true;
- this._slidTime = 0.0;
- },
-
- endRecordSlidAction: function () {
- if (this._children.length <= 0) {
- return;
- }
- if (this._slidTime <= 0.016) {
- return;
- }
- var totalDis = 0;
- totalDis = this._touchEndLocation - this._touchStartLocation;
- var orSpeed = Math.abs(totalDis) / (this._slidTime);
- this.startAutoScrollChildren(orSpeed / 4);
-
- this._bePressed = false;
- this._slidTime = 0.0;
- },
-
- getCheckPositionChild: function () {
- var child = null;
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- child = this._childPool[this._childPool.length];
- break;
-
- case cc.ListViewMoveDirection.DOWN: // down
- child = this._childPool[0];
- break;
-
- default:
- break;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- child = this._childPool[this._childPool.length];
- break;
-
- case cc.ListViewMoveDirection.RIGHT: // right
- child = this._childPool[0];
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- return child;
- },
-
- initChildWithDataLength: function (length) {
- this._dataLength = length;
- this._begin = 0;
- this._end = 0;
-
- // init child pool
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; ++i) {
- var child = arrayChildren[i];
- this.setUpdateChild(child);
- this.setUpdateDataIndex(i);
- this.initChildEvent();
- this._childPool.push(child);
- this._end = i;
- }
- },
-
- getChildFromUpdatePool: function () {
- var child = this._updatePool.pop();
- return child;
- },
-
- pushChildToPool: function () {
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- var child = this._childPool.shift();
- cc.ArrayAppendObjectToIndex(this._updatePool,child,0);
- break;
- case cc.ListViewMoveDirection.DOWN: // down
- var child = this._childPool.pop();
- cc.ArrayAppendObjectToIndex(this._updatePool,child,0);
- break;
- default:
- break;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- var child = this._childPool.shift();
- cc.ArrayAppendObjectToIndex(this._updatePool,child,0);
- break;
-
- case cc.ListViewMoveDirection.RIGHT: // right
- var child = this._childPool.pop();
- cc.ArrayAppendObjectToIndex(this._updatePool,child,0);
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
- },
-
- getAndCallback: function () {
- var child = this.getChildFromUpdatePool();
-
- if (child == null) {
- return;
- }
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- ++this._end;
- this.setUpdateChild(child);
- this.setUpdateDataIndex(this._end);
- this.updateChildEvent();
-
- if (this._updateSuccess == false) {
- --this._end;
- cc.ArrayAppendObjectToIndex(this._childPool, child, 0);
- return;
- }
- ++this._begin;
- break;
-
- case cc.ListViewMoveDirection.DOWN: // down
- --this._begin;
- this.setUpdateChild(child);
- this.setUpdateDataIndex(this._begin);
- this.updateChildEvent();
-
- if (this._updateSuccess == false) {
- ++this._begin;
- this._childPool.push(child);
- return;
- }
- --this._end;
- break;
-
- default:
- break;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- ++this._end;
- this.setUpdateChild(child);
- this.setUpdateDataIndex(this._end);
- this.updateChildEvent();
-
- if (this._updateSuccess == false) {
- --this._end;
- cc.ArrayAppendObjectToIndex(this._childPool, child, 0);
- return;
- }
- ++this._begin;
- break;
-
- case cc.ListViewMoveDirection.RIGHT: // right
- --this._begin;
- this.setUpdateChild(child);
- this.setUpdateDataIndex(this._begin);
- this.updateChildEvent();
-
- if (this._updateSuccess == false) {
- ++this._begin;
- this._childPool.push(child);
- return;
- }
- --this._end;
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- this._childPool.push(child);
- break;
-
- case cc.ListViewMoveDirection.DOWN: // down
- cc.ArrayAppendObjectToIndex(this._childPool, child, 0);
- break;
-
- default:
- break;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- this._childPool.push(child);
- break;
- case cc.ListViewMoveDirection.RIGHT: // right
- cc.ArrayAppendObjectToIndex(this._childPool, child, 0);
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
- },
-
- getDataLength: function () {
- return this._dataLength;
- },
-
- getUpdateChild: function () {
- return this._updateChild;
- },
-
- setUpdateChild: function (child) {
- this._updateChild = child;
- },
-
- getUpdateDataIndex: function () {
- return this._updateDataIndex;
- },
-
- setUpdateDataIndex: function (index) {
- this._updateDataIndex = index;
- },
-
- getUpdateSuccess: function () {
- return this._updateSuccess;
- },
-
- setUpdateSuccess: function (sucess) {
- this._updateSuccess = sucess;
- },
-
- clearCollectOverArray: function () {
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL:
- this._overTopArray = [];
- this._overBottomArray = [];
- break;
-
- case cc.ListViewDirection.HORIZONTAL:
- this._overLeftArray = [];
- this._overRightArray = [];
- break;
-
- default:
- break;
- }
- },
-
- collectOverTopChild: function () {
- var scroll_top = this._topBoundary;
-
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; ++i) {
- var child = arrayChildren[i];
- var child_bottom = child.getBottomInParent();
-
- if (child_bottom >= scroll_top)
- this._overTopArray.push(child);
- }
- },
-
- collectOverBottomChild: function () {
- var scroll_bottom = this._bottomBoundary;
-
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; ++i) {
- var child = arrayChildren[i];
- var child_top = child.getTopInParent();
-
- if (child_top <= scroll_bottom)
- this._overBottomArray.push(child);
- }
- },
-
- collectOverLeftChild: function () {
- var scroll_left = this._leftBoundary;
-
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; ++i) {
- var child = arrayChildren[i];
- var child_right = child.getRightInParent();
- if (child_right <= scroll_left)
- this._overLeftArray.push(child);
- }
- },
-
- collectOverRightChild: function () {
- var scroll_right = this._rightBoundary;
-
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; ++i) {
- var child = arrayChildren[i];
- var child_left = child.getLeftInParent();
- if (child_left >= scroll_right)
- this._overRightArray.push(child);
- }
- },
-
- setLoopPosition: function () {
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- var arrayChildren = this._children;
- if (this._overTopArray.length == arrayChildren.length) {
- var count = arrayChildren.length;
- for (var i = 0; i < count; ++i) {
- var child = this._overTopArray[i];
-
- if (i == 0) {
- var height = child.getSize().height;
- var offset = (child.getWidgetType() == cc.WidgetType.Widget) ? height / 2 : height;
- var y = this._topBoundary - this._disBoundaryToChild_0 - offset;
- child.setPosition(cc.p(child.getPosition().x, y));
- }
- else {
- var prev_child = this._overTopArray[i - 1];
- child.setPosition(cc.p(child.getPosition().x, prev_child.getPosition().y - this._disBetweenChild));
- }
- }
- }
- else {
- var scroll_top = this._topBoundary;
-
- var arrayChildren = this._children;
- for (var i = 0; i < arrayChildren.length; ++i) {
- var child = arrayChildren[i];
- var child_bottom = child.getBottomInParent();
-
- if (child_bottom >= scroll_top) {
- var index = (i == 0) ? (arrayChildren.length - 1) : (i - 1);
- var prev_child = arrayChildren[index];
- child.setPosition(cc.p(child.getPosition().x, prev_child.getPosition().y - this._disBetweenChild));
- }
- }
- }
- break;
-
- case cc.ListViewMoveDirection.DOWN: // down
- var arrayChildren = this._children;
- var childrenCount = arrayChildren.length;
- if (this._overBottomArray.length == childrenCount) {
- var count = childrenCount;
- for (var i = 0; i < count; ++i) {
- var child = this._overBottomArray[i];
-
- if (i == 0) {
- var y = this._bottomBoundary + this._disBoundaryToChild_0 - this._disBetweenChild;
- child.setPosition(cc.p(child.getPosition().x, y));
- }
- else {
- var prev_child = this._overBottomArray[i - 1];
- child.setPosition(cc.p(child.getPosition().x, prev_child.getPosition().y + this._disBetweenChild));
- }
- }
- }
- else {
- var scroll_bottom = this._bottomBoundary;
-
- var arrayChildren = this._children;
- var count = arrayChildren.length;
- for (var i = count - 1; i >= 0; --i) {
- var child = arrayChildren[i];
- var child_top = child.getTopInParent();
-
- if (child_top <= scroll_bottom) {
- var index = (i == count - 1) ? 0 : (i + 1);
- var next_child = arrayChildren[index];
- child.setPosition(cc.p(child.getPosition().x, next_child.getPosition().y + this._disBetweenChild));
- }
- }
- }
- break;
-
- default:
- break;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- var arrayChildren = this._children;
- var childrenCount = arrayChildren.length;
-
- if (this._overLeftArray.length == childrenCount) {
- var count = childrenCount;
- for (var i = 0; i < count; ++i) {
- var child = this._overLeftArray[i];
-
- if (i == 0) {
- var width = child.getSize().width;
- var offset = (child.getWidgetType() == cc.WidgetType.Widget) ? (width / 2) : 0;
- var x = this._leftBoundary + this._disBoundaryToChild_0 + width + offset;
- child.setPosition(cc.p(x, child.getPosition().y));
- }
- else {
- var prev_child = this._overLeftArray[i - 1];
- child.setPosition(cc.p(prev_child.getPosition().x + this._disBetweenChild, child.getPosition().y));
- }
- }
- }
- else {
- var scroll_left = this._leftBoundary;
-
- var arrayChildren = this._children;
- var count = arrayChildren.length;
- for (var i = 0; i < count; ++i) {
- var child = arrayChildren[i];
- var child_right = child.getRightInParent();
-
- if (child_right <= scroll_left) {
- var index = (i == 0) ? (count - 1) : (i - 1);
- var prev_child = arrayChildren[index];
- child.setPosition(cc.p(prev_child.getPosition().x + this._disBetweenChild, child.getPosition().y));
- }
- }
- }
- break;
-
- case cc.ListViewMoveDirection.RIGHT: // right
- var arrayChildren = this._children;
- var childrenCount = arrayChildren.length;
-
- if (this._overRightArray.length == childrenCount) {
- var count = childrenCount;
- for (var i = 0; i < count; ++i) {
- var child = this._overRightArray[i];
-
- if (i == 0) {
- var x = this._rightBoundary - this._disBoundaryToChild_0 + this._disBetweenChild;
- child.setPosition(cc.p(x, child.getPosition().y));
- }
- else {
- var prev_child = this._overRightArray[i - 1];
- child.setPosition(cc.p(prev_child.getPosition().x - this._disBetweenChild, child.getPosition().y));
- }
- }
- }
- else {
- var scroll_right = this._rightBoundary;
-
- var arrayChildren = this._children;
- var count = arrayChildren.length;
- for (var i = count - 1; i >= 0; --i) {
- var child = arrayChildren[i];
- var child_left = child.getLeftInParent();
-
- if (child_left >= scroll_right) {
- var index = (i == count - 1) ? 0 : (i + 1);
- var next_child = arrayChildren[index];
- child.setPosition(cc.p(next_child.getPosition().x - this._disBetweenChild, child.getPosition().y));
- }
- }
- }
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
- },
-
- updateChild: function () {
- switch (this._direction) {
- case cc.ListViewDirection.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.UP: // up
- var count = this._overTopArray.length;
- for (var i = 0; i < count; ++i) {
- this.pushChildToPool();
- this.getAndCallback();
- }
- break;
-
- case cc.ListViewMoveDirection.DOWN: // down
- var count = this._overBottomArray.length;
- for (var i = 0; i < count; ++i) {
- this.pushChildToPool();
- this.getAndCallback();
- }
- break;
- default:
- break;
- }
- break;
-
- case cc.ListViewDirection.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.ListViewMoveDirection.LEFT: // left
- var count = this._overLeftArray.length;
- for (var i = 0; i < count; ++i) {
- this.pushChildToPool();
- this.getAndCallback();
- }
- break;
- case cc.ListViewMoveDirection.RIGHT: // right
- var count = this._overRightArray.length;
- for (var i = 0; i < count; ++i) {
- this.pushChildToPool();
- this.getAndCallback();
- }
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- },
-
- initChildEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.ListViewEventType.INIT_CHILD);
- }
- },
-
- updateChildEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.ListViewEventType.UPDATE_CHILD);
- }
- },
-
- addEventListenter: function (target, selector) {
- this._eventListener = target;
- this._eventSelector = selector;
- },
-
- getDescription: function () {
- return "ListView";
- }
-});
-
-cc.UIListView.create = function () {
- var uiListView = new cc.UIListView();
- if (uiListView && uiListView.init()) {
- return uiListView;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIPageView.js b/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIPageView.js
deleted file mode 100644
index 4080e277cb..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIPageView.js
+++ /dev/null
@@ -1,537 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.PageViewEventType = {
- TURNING: 0
-};
-
-cc.PVTouchDir = {
- TOUCHLEFT: 0,
- TOUCHRIGHT: 1
-};
-
-/**
- * Base class for cc.UIPageView
- * @class
- * @extends cc.Layout
- */
-cc.UIPageView = cc.Layout.extend({
- _curPageIdx: 0,
- _pages: null,
- _touchMoveDir: null,
- _touchStartLocation: 0,
- _touchEndLocation: 0,
- _touchMoveStartLocation: 0,
- _movePagePoint: null,
- _leftChild: null,
- _rightChild: null,
- _leftBoundary: 0,
- _rightBoundary: 0,
- _isAutoScrolling: false,
- _autoScrollDistance: 0,
- _autoScrollSpeed: 0,
- _autoScrollDir: 0,
- _childFocusCancelOffset: 0,
- _eventListener: null,
- _eventSelector: null,
- ctor: function () {
- cc.Layout.prototype.ctor.call(this);
- this._curPageIdx = 0;
- this._pages = [];
- this._touchMoveDir = cc.PVTouchDir.TOUCHLEFT;
- this._touchStartLocation = 0;
- this._touchEndLocation = 0;
- this._touchMoveStartLocation = 0;
- this._movePagePoint = null;
- this._leftChild = null;
- this._rightChild = null;
- this._leftBoundary = 0;
- this._rightBoundary = 0;
- this._isAutoScrolling = false;
- this._autoScrollDistance = 0;
- this._autoScrollSpeed = 0;
- this._autoScrollDir = 0;
- this._childFocusCancelOffset = 5;
- this._eventListener = null;
- this._eventSelector = null;
- },
-
- init: function () {
- if (cc.Layout.prototype.init.call(this)) {
- this._pages = [];
- this.setClippingEnabled(true);
- this.setUpdateEnabled(true);
- return true;
- }
- return false;
- },
-
- /**
- * Add a widget to a page of pageview.
- * @param {cc.UIWidget} widget
- * @param {number} pageIdx
- * @param {Boolean} forceCreate
- */
- addWidgetToPage: function (widget, pageIdx, forceCreate) {
- if (!widget) {
- return;
- }
- var pageCount = this._pages.length;
- if (pageIdx < 0 || pageIdx >= pageCount) {
- if (forceCreate) {
- if (pageIdx > pageCount) {
- cc.log("pageIdx is %d, it will be added as page id [%d]", pageIdx, pageCount);
- }
- var newPage = this.createPage();
- newPage.addChild(widget);
- this.addPage(newPage);
- }
- }
- else {
- var page = this._pages[pageIdx];
- if (page) {
- page.addChild(widget);
- }
- }
- },
-
- /**
- * create page
- * @returns {cc.Layout}
- */
- createPage: function () {
- var newPage = cc.Layout.create();
- newPage.setSize(this.getSize());
- return newPage;
- },
-
- /**
- * Push back a page to pageview.
- * @param {cc.Layout} page
- */
- addPage: function (page) {
- if (!page) {
- return;
- }
- if (page.getWidgetType() != cc.WidgetType.Container) {
- return;
- }
- if (cc.ArrayContainsObject(this._pages, page)) {
- return;
- }
- var pSize = page.getSize();
- var pvSize = this.getSize();
- if (!(pSize.width==pvSize.width&&pSize.height==pvSize.height)) {
- cc.log("page size does not match pageview size, it will be force sized!");
- page.setSize(pvSize);
- }
- page.setPosition(cc.p(this.getPositionXByIndex(this._pages.length), 0));
- this._pages.push(page);
- this.addChild(page);
- this.updateBoundaryPages();
- },
-
- /**
- * Inert a page to pageview.
- * @param {cc.Layout} page
- * @param {Number} idx
- */
- insertPage: function (page, idx) {
- if (idx < 0) {
- return;
- }
- if (!page) {
- return;
- }
- if (page.getWidgetType() != cc.WidgetType.Container) {
- return;
- }
- if (cc.ArrayContainsObject(this._pages, page)) {
- return;
- }
-
- var pageCount = this._pages.length;
- if (idx >= pageCount) {
- this.addPage(page);
- }
- else {
- cc.ArrayAppendObjectToIndex(this._pages, page, idx);
- page.setPosition(cc.p(this.getPositionXByIndex(idx), 0));
- this.addChild(page);
- var pSize = page.getSize();
- var pvSize = this.getSize();
- if (!pSize.equals(pvSize)) {
- cc.log("page size does not match pageview size, it will be force sized!");
- page.setSize(pvSize);
- }
- var arrayPages = this._pages;
- var length = arrayPages.length;
- for (var i = (idx + 1); i < length; i++) {
- var behindPage = arrayPages[i];
- var formerPos = behindPage.getPosition();
- behindPage.setPosition(cc.p(formerPos.x + this.getSize().width, 0));
- }
- this.updateBoundaryPages();
- }
- },
-
- /**
- * Remove a page of pageview.
- * @param {cc.Layout} page
- */
- removePage: function (page) {
- if (!page) {
- return;
- }
- this.removeChild(page);
- this.updateChildrenPosition();
- this.updateBoundaryPages();
- },
-
- /**
- * Remove a page at index of pageview.
- * @param {number} index
- */
- removePageAtIndex: function (index) {
- if (index < 0 || index >= this._pages.length) {
- return;
- }
- var page = this._pages[index];
- if (page) {
- this.removePage(page);
- }
- },
-
- updateBoundaryPages: function () {
- if (this._pages.length <= 0) {
- this._leftChild = null;
- this._rightChild = null;
- return;
- }
- this._leftChild = this._pages[0];
- this._rightChild = this._pages[this._pages.length-1];
- },
-
- /**
- * Get x position by index
- * @param {number} idx
- * @returns {number}
- */
- getPositionXByIndex: function (idx) {
- return (this.getSize().width * (idx - this._curPageIdx));
- },
-
- /**
- * Add widget
- * @param {cc.UIWidget} widget
- * @returns {boolean}
- */
- addChild: function (widget) {
- return cc.Layout.prototype.addChild.call(this, widget);
- },
-
- /**
- * remove widget child override
- * @param {cc.UIWidget} child
- * @returns {boolean}
- */
- removeChild: function (widget) {
- if (cc.ArrayContainsObject(this._pages, widget)) {
- cc.ArrayRemoveObject(this._pages, widget);
- return cc.Layout.prototype.removeChild.call(this, widget);
- }
- return false;
- },
-
- onSizeChanged: function () {
- cc.Layout.prototype.onSizeChanged.call(this);
- this._rightBoundary = this.getSize().width;
- this.updateChildrenSize();
- this.updateChildrenPosition();
- },
-
- updateChildrenSize: function () {
- if (!this._pages.length <= 0) {
- return;
- }
-
- var selfSize = this.getSize();
- for (var i = 0; i < this._pages.length; i++) {
- var page = this._pages[i];
- page.setSize(selfSize);
- }
- },
-
- updateChildrenPosition: function () {
- if (!this._pages) {
- return;
- }
-
- var pageCount = this._pages.length;
- if (pageCount <= 0) {
- this._curPageIdx = 0;
- return;
- }
- if (this._curPageIdx >= pageCount) {
- this._curPageIdx = pageCount - 1;
- }
- var pageWidth = this.getSize().width;
- var arrayPages = this._pages;
- for (var i = 0; i < pageCount; i++) {
- var page = arrayPages[i];
- page.setPosition(cc.p((i - this._curPageIdx) * pageWidth, 0));
- }
- },
-
- removeAllChildren: function () {
- this._pages = [];
- cc.Layout.prototype.removeAllChildren.call(this);
- },
-
- /**
- * scroll pageview to index.
- * @param {number} idx
- */
- scrollToPage: function (idx) {
- if (idx < 0 || idx >= this._pages.length) {
- return;
- }
- this._curPageIdx = idx;
- var curPage = this._pages[idx];
- this._autoScrollDistance = -(curPage.getPosition().x);
- this._autoScrollSpeed = Math.abs(this._autoScrollDistance) / 0.2;
- this._autoScrollDir = this._autoScrollDistance > 0 ? 1 : 0;
- this._isAutoScrolling = true;
- },
-
- update: function (dt) {
- if (this._isAutoScrolling) {
- switch (this._autoScrollDir) {
- case 0:
- var step = this._autoScrollSpeed * dt;
- if (this._autoScrollDistance + step >= 0.0) {
- step = -this._autoScrollDistance;
- this._autoScrollDistance = 0.0;
- this._isAutoScrolling = false;
- this.pageTurningEvent();
- }
- else {
- this._autoScrollDistance += step;
- }
- this.scrollPages(-step);
- break;
- break;
- case 1:
- var step = this._autoScrollSpeed * dt;
- if (this._autoScrollDistance - step <= 0.0) {
- step = this._autoScrollDistance;
- this._autoScrollDistance = 0.0;
- this._isAutoScrolling = false;
- this.pageTurningEvent();
- }
- else {
- this._autoScrollDistance -= step;
- }
- this.scrollPages(step);
- break;
- default:
- break;
- }
- }
- },
-
- onTouchBegan: function (touchPoint) {
- var pass = cc.Layout.prototype.onTouchBegan.call(this, touchPoint);
- this.handlePressLogic(touchPoint);
- return pass;
- },
-
- onTouchMoved: function (touchPoint) {
- this._touchMovePos.x = touchPoint.x;
- this._touchMovePos.y = touchPoint.y;
- this.handleMoveLogic(touchPoint);
- if (this._widgetParent) {
- this._widgetParent.checkChildInfo(1, this, touchPoint);
- }
- this.moveEvent();
- if (!this.hitTest(touchPoint)) {
- this.setFocused(false);
- this.onTouchEnded(touchPoint);
- }
- },
-
- onTouchEnded: function (touchPoint) {
- cc.Layout.prototype.onTouchEnded.call(this, touchPoint);
- this.handleReleaseLogic(touchPoint);
- },
-
- movePages: function (offset) {
- var arrayPages = this._pages;
- var length = arrayPages.length;
- for (var i = 0; i < length; i++) {
- var child = arrayPages[i];
- var pos = child.getPosition();
- child.setPosition(cc.p(pos.x + offset, pos.y));
- }
- },
-
- scrollPages: function (touchOffset) {
- if (this._pages.length <= 0) {
- return false;
- }
-
- if (!this._leftChild || !this._rightChild) {
- return false;
- }
-
- var realOffset = touchOffset;
-
- switch (this._touchMoveDir) {
- case cc.PVTouchDir.TOUCHLEFT: // left
- if (this._rightChild.getRightInParent() + touchOffset <= this._rightBoundary) {
- realOffset = this._rightBoundary - this._rightChild.getRightInParent();
- this.movePages(realOffset);
- return false;
- }
- break;
-
- case cc.PVTouchDir.TOUCHRIGHT: // right
- if (this._leftChild.getLeftInParent() + touchOffset >= this._leftBoundary) {
- realOffset = this._leftBoundary - this._leftChild.getLeftInParent();
- this.movePages(realOffset);
- return false;
- }
- break;
- default:
- break;
- }
-
- this.movePages(realOffset);
- return true;
- },
-
- onTouchCancelled: function (touchPoint) {
- cc.Layout.prototype.onTouchCancelled.call(this, touchPoint);
- },
-
- handlePressLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- this._touchMoveStartLocation = nsp.x;
- this._touchStartLocation = nsp.x;
- },
-
- handleMoveLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- var offset = 0.0;
- var moveX = nsp.x;
- offset = moveX - this._touchMoveStartLocation;
- this._touchMoveStartLocation = moveX;
- if (offset < 0) {
- this._touchMoveDir = cc.PVTouchDir.TOUCHLEFT;
- }
- else if (offset > 0) {
- this._touchMoveDir = cc.PVTouchDir.TOUCHRIGHT;
- }
- this.scrollPages(offset);
- },
-
- handleReleaseLogic: function (touchPoint) {
- var curPage = this._pages[this._curPageIdx];
- if (curPage) {
- var curPagePos = curPage.getPosition();
- var pageCount = this._pages.length;
- var curPageLocation = curPagePos.x;
- var pageWidth = this.getSize().width;
- var boundary = pageWidth / 2.0;
- if (curPageLocation <= -boundary) {
- if (this._curPageIdx >= pageCount - 1)
- this.scrollPages(-curPageLocation);
- else
- this.scrollToPage(this._curPageIdx + 1);
- }
- else if (curPageLocation >= boundary) {
- if (this._curPageIdx <= 0)
- this.scrollPages(-curPageLocation);
- else
- this.scrollToPage(this._curPageIdx - 1);
- }
- else {
- this.scrollToPage(this._curPageIdx);
- }
- }
- },
-
- checkChildInfo: function (handleState, sender, touchPoint) {
- this.interceptTouchEvent(handleState, sender, touchPoint);
- },
-
- interceptTouchEvent: function (handleState, sender, touchPoint) {
- switch (handleState) {
- case 0:
- this.handlePressLogic(touchPoint);
- break;
- case 1:
- var offset = 0;
- offset = Math.abs(sender.getTouchStartPos().x - touchPoint.x);
- if (offset > this._childFocusCancelOffset) {
- sender.setFocused(false);
- this.handleMoveLogic(touchPoint);
- }
- break;
- case 2:
- this.handleReleaseLogic(touchPoint);
- break;
-
- case 3:
- break;
- }
- },
-
- pageTurningEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.PageViewEventType.TURNING);
- }
- },
-
- addEventListener: function (target, selector) {
- this._eventListener = target;
- this._eventSelector = selector;
- },
-
- getCurPageIndex: function () {
- return this._curPageIdx;
- },
-
- getDescription: function () {
- return "PageView";
- }
-});
-
-cc.UIPageView.create = function () {
- var uiPageView = new cc.UIPageView();
- if (uiPageView && uiPageView.init()) {
- return uiPageView;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollView.js b/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollView.js
deleted file mode 100644
index 76ab662d96..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollView.js
+++ /dev/null
@@ -1,630 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.SCROLLVIEW_DIR = {
- NONE: 0,
- VERTICAL: 1,
- HORIZONTAL: 2
-};
-
-cc.SCROLLVIEW_MOVE_DIR = {
- NONE: 0,
- UP: 1,
- DOWN: 2,
- LEFT: 3,
- RIGHT: 4
-};
-
-cc.ScrollviewEventType = {
- TOP: 0,
- BOTTOM: 1,
- LEFT: 2,
- RIGHT: 3
-};
-
-/**
- * Base class for cc.UIScrollView
- * @class
- * @extends cc.Layout
- */
-cc.UIScrollView = cc.Layout.extend({
- _innerContainer: null,
- _direction: null,
- _moveDirection: null,
- _touchStartLocation: 0,
- _touchEndLocation: 0,
- _touchMoveStartLocation: 0,
- _topBoundary: 0,//test
- _bottomBoundary: 0,//test
- _leftBoundary: 0,
- _rightBoundary: 0,
- _topEnd: false,
- _bottomEnd: false,
- _leftEnd: false,
- _rightEnd: false,
- _autoScroll: false,
- _autoScrollOriginalSpeed: 0,
- _autoScrollAcceleration: 0,
- _bePressed: false,
- _slidTime: 0,
- _moveChildPoint: null,
- _childFocusCancelOffset: 0,
- _eventListener: null,
- _eventSelector: null,
- ctor: function () {
- cc.Layout.prototype.ctor.call(this);
- this._innerContainer = null;
- this._direction = cc.SCROLLVIEW_DIR.NONE;
- this._moveDirection = cc.SCROLLVIEW_MOVE_DIR.NONE;
- this._touchStartLocation = 0;
- this._touchEndLocation = 0;
- this._touchMoveStartLocation = 0;
- this._topBoundary = 0;//test
- this._bottomBoundary = 0;//test
- this._leftBoundary = 0;
- this._rightBoundary = 0;
- this._topEnd = false;
- this._bottomEnd = false;
- this._leftEnd = false;
- this._rightEnd = false;
- this._autoScroll = false;
- this._autoScrollOriginalSpeed = 0;
- this._autoScrollAcceleration = 600;
- this._bePressed = false;
- this._slidTime = 0;
- this._moveChildPoint = cc.p(0, 0);
- this._childFocusCancelOffset = 5;
- this._eventListener = null;
- this._eventSelector = null;
- },
- releaseResoures: function () {
- this.setUpdateEnabled(false);
- this.removeAllChildren();
- this._renderer.removeAllChildren(true);
- this._renderer.removeFromParent(true);
-
- cc.Layout.prototype.removeChild.call(this, this._innerContainer);
-
- this._children = [];
- },
-
- init: function () {
- if (cc.Layout.prototype.init.call(this)) {
- this.setUpdateEnabled(true);
- this.setTouchEnabled(true);
- this.setClippingEnabled(true);
- this._innerContainer.setTouchEnabled(false);
- return true;
- }
- return false;
- },
-
- initRenderer: function () {
- cc.Layout.prototype.initRenderer.call(this);
- this._innerContainer = cc.Layout.create();
- cc.Layout.prototype.addChild.call(this, this._innerContainer);
- },
-
- onSizeChanged: function () {
- cc.Layout.prototype.onSizeChanged.call(this);
- this._topBoundary = this._size.height;
- this._rightBoundary = this._size.width;
- var innerSize = this._innerContainer.getSize();
- var orginInnerSizeWidth = innerSize.width;
- var orginInnerSizeHeight = innerSize.height;
- var innerSizeWidth = Math.max(orginInnerSizeWidth, this._size.width);
- var innerSizeHeight = Math.max(orginInnerSizeHeight, this._size.height);
- this._innerContainer.setSize(cc.size(innerSizeWidth, innerSizeHeight));
- this._innerContainer.setPosition(cc.p(0, this._size.height - this._innerContainer.getSize().height));
- },
-
- setInnerContainerSize: function (size) {
- var innerSizeWidth = this._size.width;
- var innerSizeHeight = this._size.height;
- if (size.width < this._size.width) {
- cc.log("Inner width <= scrollview width, it will be force sized!");
- }
- else {
- innerSizeWidth = size.width;
- }
- if (size.height < this._size.height) {
- cc.log("Inner height <= scrollview height, it will be force sized!");
- }
- else {
- innerSizeHeight = size.height;
- }
- this._innerContainer.setSize(cc.size(innerSizeWidth, innerSizeHeight));
- this._innerContainer.setPosition(cc.p(0, this._size.height - this._innerContainer.getSize().height));
- },
-
- getInnerContainerSize: function () {
- return this._innerContainer.getSize();
- },
-
- /**
- * Add widget
- * @param {cc.UIWidget} widget
- * @returns {boolean}
- */
- addChild: function (widget) {
- return this._innerContainer.addChild(widget);
- },
-
- removeAllChildren: function () {
- this._innerContainer.removeAllChildren();
- },
-
- /**
- * remove widget child override
- * @param {cc.UIWidget} child
- * @returns {boolean}
- */
- removeChild: function (child) {
- return this._innerContainer.removeChild(child);
- },
-
- getChildren: function () {
- return this._innerContainer.getChildren();
- },
-
- moveChildren: function (offset) {
- switch (this._direction) {
- case cc.SCROLLVIEW_DIR.VERTICAL: // vertical
- var pos = this._innerContainer.getPosition();
- this._innerContainer.setPosition(cc.p(pos.x, pos.y + offset));
- break;
- case cc.SCROLLVIEW_DIR.HORIZONTAL: // horizontal
- var pos = this._innerContainer.getPosition();
- this._innerContainer.setPosition(cc.p(pos.x + offset, pos.y));
- break;
- default:
- break;
- }
- },
-
- autoScrollChildren: function (dt) {
- switch (this._direction) {
- case cc.SCROLLVIEW_DIR.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.SCROLLVIEW_MOVE_DIR.UP: // up
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
- case cc.SCROLLVIEW_MOVE_DIR.DOWN: // down
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(-curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
- default:
- break;
- }
- break;
-
- case cc.SCROLLVIEW_DIR.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.SCROLLVIEW_MOVE_DIR.LEFT: // left
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(-curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
-
- case cc.SCROLLVIEW_MOVE_DIR.RIGHT: // right
- var curDis = this.getCurAutoScrollDistance(dt);
- if (curDis <= 0) {
- curDis = 0;
- this.stopAutoScrollChildren();
- }
- if (!this.scrollChildren(curDis)) {
- this.stopAutoScrollChildren();
- }
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
- },
-
- startAutoScrollChildren: function (v) {
- this._autoScrollOriginalSpeed = v;
- this._autoScroll = true;
- },
-
- stopAutoScrollChildren: function () {
- this._autoScroll = false;
- this._autoScrollOriginalSpeed = 0.0;
- },
-
- getCurAutoScrollDistance: function (dt) {
- this._autoScrollOriginalSpeed -= this._autoScrollAcceleration * dt;
- return this._autoScrollOriginalSpeed * dt;
- },
-
- scrollChildren: function (touchOffset) {
- var realOffset = touchOffset;
-
- switch (this._direction) {
- case cc.SCROLLVIEW_DIR.VERTICAL: // vertical
- switch (this._moveDirection) {
- case cc.SCROLLVIEW_MOVE_DIR.UP: // up
- var icBottomPos = this._innerContainer.getBottomInParent();
- if (icBottomPos + touchOffset >= this._bottomBoundary) {
- realOffset = this._bottomBoundary - icBottomPos;
- this.moveChildren(realOffset);
- this._bottomEnd = true;
- this.scrollToBottomEvent();
- return false;
- }
- break;
- case cc.SCROLLVIEW_MOVE_DIR.DOWN: // down
- var icTopPos = this._innerContainer.getTopInParent();
- if (icTopPos + touchOffset <= this._topBoundary) {
- realOffset = this._topBoundary - icTopPos;
- this.moveChildren(realOffset);
- this._topEnd = true;
- this.scrollToTopEvent();
- return false;
- }
- break;
- default:
- break;
- }
- this.moveChildren(realOffset);
- this._topEnd = false;
- this._bottomEnd = false;
- return true;
- break;
- case cc.SCROLLVIEW_DIR.HORIZONTAL: // horizontal
- switch (this._moveDirection) {
- case cc.SCROLLVIEW_MOVE_DIR.LEFT: // left
- var icRightPos = this._innerContainer.getRightInParent();
- if (icRightPos + touchOffset <= this._rightBoundary) {
- realOffset = this._rightBoundary - icRightPos;
- this.moveChildren(realOffset);
- this._rightEnd = true;
- this.scrollToRightEvent();
- return false;
- }
- break;
- case cc.SCROLLVIEW_MOVE_DIR.RIGHT: // right
- var icLeftPos = this._innerContainer.getLeftInParent();
- if (icLeftPos + touchOffset >= this._leftBoundary) {
- realOffset = this._leftBoundary - icLeftPos;
- this.moveChildren(realOffset);
- this._leftEnd = true;
- this.scrollToLeftEvent();
- return false;
- }
- break;
- default:
- break;
- }
- this.moveChildren(realOffset);
- this._leftEnd = false;
- this._rightEnd = false;
- return true;
- break;
-
- default:
- break;
- }
-
- return false;
- },
-
- scrollToBottom: function () {
- this._moveDirection = cc.SCROLLVIEW_MOVE_DIR.UP; // up
- this.scrollChildren(this._innerContainer.getSize().height);
- },
-
- scrollToTop: function () {
- this._moveDirection = cc.SCROLLVIEW_MOVE_DIR.DOWN; // down
- this.scrollChildren(-this._innerContainer.getSize().height);
- },
-
- startRecordSlidAction: function () {
- if (this._children.length <= 0) {
- return;
- }
- if (this._autoScroll) {
- this.stopAutoScrollChildren();
- }
- this._bePressed = true;
- this._slidTime = 0.0;
- },
-
- endRecordSlidAction: function () {
- if (this._children.length <= 0) {
- return;
- }
- if (this._slidTime <= 0.016) {
- return;
- }
- var totalDis = 0;
- totalDis = this._touchEndLocation - this._touchStartLocation;
- var orSpeed = Math.abs(totalDis) / (this._slidTime);
- this.startAutoScrollChildren(orSpeed);
-
- this._bePressed = false;
- this._slidTime = 0.0;
- },
-
- handlePressLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- switch (this._direction) {
- case cc.SCROLLVIEW_DIR.VERTICAL: // vertical
- this._touchMoveStartLocation = nsp.y;
- this._touchStartLocation = nsp.y;
- break;
- case cc.SCROLLVIEW_DIR.HORIZONTAL: // horizontal
- this._touchMoveStartLocation = nsp.x;
- this._touchStartLocation = nsp.x;
- break;
- default:
- break;
- }
- this.startRecordSlidAction();
- },
-
- handleMoveLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- var offset = 0.0;
-
- switch (this._direction) {
- case cc.SCROLLVIEW_DIR.VERTICAL: // vertical
- var moveY = nsp.y;
- offset = moveY - this._touchMoveStartLocation;
- this._touchMoveStartLocation = moveY;
-
- if (offset < 0.0) {
- this._moveDirection = cc.SCROLLVIEW_MOVE_DIR.DOWN; // down
- }
- else if (offset > 0.0) {
- this._moveDirection = cc.SCROLLVIEW_MOVE_DIR.UP; // up
- }
- break;
-
- case cc.SCROLLVIEW_DIR.HORIZONTAL: // horizontal
- var moveX = nsp.x;
- offset = moveX - this._touchMoveStartLocation;
- this._touchMoveStartLocation = moveX;
-
- if (offset < 0) {
- this._moveDirection = cc.SCROLLVIEW_MOVE_DIR.LEFT; // left
- }
- else if (offset > 0) {
- this._moveDirection = cc.SCROLLVIEW_MOVE_DIR.RIGHT; // right
- }
- break;
-
- default:
- break;
- }
- this.scrollChildren(offset);
- },
-
- handleReleaseLogic: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- switch (this._direction) {
- case cc.SCROLLVIEW_DIR.VERTICAL: // vertical
- this._touchEndLocation = nsp.y;
- break;
-
- case cc.SCROLLVIEW_DIR.HORIZONTAL: // horizontal
- this._touchEndLocation = nsp.x;
- break;
-
- default:
- break;
- }
- this.endRecordSlidAction();
- },
-
- onTouchBegan: function (touchPoint) {
- var pass = cc.Layout.prototype.onTouchBegan.call(this, touchPoint);
- this.handlePressLogic(touchPoint);
- return pass;
- },
-
- onTouchMoved: function (touchPoint) {
- cc.Layout.prototype.onTouchMoved.call(this, touchPoint);
- this.handleMoveLogic(touchPoint);
- },
-
- onTouchEnded: function (touchPoint) {
- cc.Layout.prototype.onTouchEnded.call(this, touchPoint);
- this.handleReleaseLogic(touchPoint);
- },
-
- onTouchCancelled: function (touchPoint) {
- cc.Layout.prototype.onTouchCancelled.call(this, touchPoint);
- },
-
- onTouchLongClicked: function (touchPoint) {
-
- },
-
- update: function (dt) {
- if (this._autoScroll) {
- this.autoScrollChildren(dt);
- }
- this.recordSlidTime(dt);
- },
-
- recordSlidTime: function (dt) {
- if (this._bePressed) {
- this._slidTime += dt;
- }
- },
-
- /**
- * Intercept touch event
- * @param {number} handleState
- * @param {cc.UIWidget} sender
- * @param {cc.Point} touchPoint
- */
- interceptTouchEvent: function (handleState, sender, touchPoint) {
- switch (handleState) {
- case 0:
- this.handlePressLogic(touchPoint);
- break;
- case 1:
- var offset = 0;
- switch (this._direction) {
- case cc.SCROLLVIEW_DIR.VERTICAL: // vertical
- offset = Math.abs(sender.getTouchStartPos().y - touchPoint.y);
- break;
-
- case cc.SCROLLVIEW_DIR.HORIZONTAL: // horizontal
- offset = Math.abs(sender.getTouchStartPos().x - touchPoint.x);
- break;
-
- default:
- break;
- }
- if (offset > this._childFocusCancelOffset) {
- sender.setFocused(false);
- this.handleMoveLogic(touchPoint);
- }
- break;
-
- case 2:
- this.handleReleaseLogic(touchPoint);
- break;
-
- case 3:
- break;
- }
- },
-
- /**
- *
- * @param {number} handleState
- * @param {cc.UIWidget} sender
- * @param {cc.Point} touchPoint
- */
- checkChildInfo: function (handleState, sender, touchPoint) {
- this.interceptTouchEvent(handleState, sender, touchPoint);
- },
-
- scrollToTopEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.ScrollviewEventType.TOP);
- }
- },
-
- scrollToBottomEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.ScrollviewEventType.BOTTOM);
- }
- },
-
- scrollToLeftEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.ScrollviewEventType.LEFT);
- }
- },
-
- scrollToRightEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.ScrollviewEventType.RIGHT);
- }
- },
-
- addEventListener: function (target, selector) {
- this._eventListener = target;
- this._eventSelector = selector;
- },
-
- setDirection: function (dir) {
- this._direction = dir;
- },
-
- getDirection: function () {
- return this._direction;
- },
-
- setMoveDirection: function (dir) {
- this._moveDirection = dir;
- },
-
- getMoveDirection: function () {
- return this._moveDirection;
- },
-
- getInnerContainer: function () {
- return this._innerContainer;
- },
-
- /**
- * Sets LayoutType.
- * @param {cc.LayoutType} type
- */
- setLayoutType: function (type) {
- this._innerContainer.setLayoutType(type);
- },
-
- /**
- * Gets LayoutType.
- * @returns {cc.LayoutType}
- */
- getLayoutType: function () {
- return this._innerContainer.getLayoutType();
- },
-
- doLayout: function () {
- this._innerContainer.doLayout();
- },
-
- getDescription: function () {
- return "ScrollView";
- }
-});
-cc.UIScrollView.create = function () {
- var uiScrollView = new cc.UIScrollView();
- if (uiScrollView && uiScrollView.init()) {
- return uiScrollView;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UIButton.js b/extensions/CocoStudio/GUI/UIWidgets/UIButton.js
deleted file mode 100644
index 07acb32b39..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UIButton.js
+++ /dev/null
@@ -1,657 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-var NORMALRENDERERZ = 0;
-var PRESSEDRENDERERZ = 0;
-var DISABLEDRENDERERZ = 0;
-var TITLERENDERERZ = 1;
-
-/**
- * Base class for cc.UIButton
- * @class
- * @extends cc.UIWidget
- */
-cc.UIButton = cc.UIWidget.extend({
- _buttonNormalRenderer: null,
- _buttonClickedRenderer: null,
- _buttonDisableRenderer: null,
- _titleRenderer: null,
- _normalFileName: "",
- _clickedFileName: "",
- _disabledFileName: "",
- _prevIgnoreSize: true,
- _scale9Enabled: false,
-// CCRect _capInsets:null,
- _capInsetsNormal: null,
- _capInsetsPressed: null,
- _capInsetsDisabled: null,
- _normalTexType: null,
- _pressedTexType: null,
- _disabledTexType: null,
- _normalTextureSize: null,
- _pressedTextureSize: null,
- _disabledTextureSize: null,
- _pressedActionEnabled: false,
- _titleColor: null,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._buttonNormalRenderer = null;
- this._buttonClickedRenderer = null;
- this._buttonDisableRenderer = null;
- this._titleRenderer = null;
- this._normalFileName = "";
- this._clickedFileName = "";
- this._disabledFileName = "";
- this._prevIgnoreSize = true;
- this._scale9Enabled = false;
- this._capInsetsNormal = cc.RectZero();
- this._capInsetsPressed = cc.RectZero();
- this._capInsetsDisabled = cc.RectZero();
- this._normalTexType = cc.TextureResType.LOCAL;
- this._pressedTexType = cc.TextureResType.LOCAL;
- this._disabledTexType = cc.TextureResType.LOCAL;
- var locSize = this._size;
- this._normalTextureSize = cc.size(locSize.width, locSize.height);
- this._pressedTextureSize = cc.size(locSize.width, locSize.height);
- this._disabledTextureSize = cc.size(locSize.width, locSize.height);
- this._pressedActionEnabled = false;
- this._titleColor = cc.white();
- },
-
- init: function () {
- if (cc.UIWidget.prototype.init.call(this))
- return true;
- return false;
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._buttonNormalRenderer = cc.Sprite.create();
- this._buttonClickedRenderer = cc.Sprite.create();
- this._buttonDisableRenderer = cc.Sprite.create();
- this._titleRenderer = cc.LabelTTF.create("");
- this._renderer.addChild(this._buttonNormalRenderer, NORMALRENDERERZ);
- this._renderer.addChild(this._buttonClickedRenderer, PRESSEDRENDERERZ);
- this._renderer.addChild(this._buttonDisableRenderer, DISABLEDRENDERERZ);
- this._renderer.addChild(this._titleRenderer, TITLERENDERERZ);
- },
-
- /**
- * Sets if button is using scale9 renderer.
- * @param {Boolean} able
- */
- setScale9Enabled: function (able) {
- if (this._scale9Enabled == able) {
- return;
- }
- this._brightStyle = cc.BrightStyle.NONE;
- this._scale9Enabled = able;
-
- this._renderer.removeChild(this._buttonNormalRenderer, true);
- this._renderer.removeChild(this._buttonClickedRenderer, true);
- this._renderer.removeChild(this._buttonDisableRenderer, true);
-
- this._buttonNormalRenderer = null;
- this._buttonClickedRenderer = null;
- this._buttonDisableRenderer = null;
- if (this._scale9Enabled) {
- this._buttonNormalRenderer = cc.Scale9Sprite.create();
- this._buttonClickedRenderer = cc.Scale9Sprite.create();
- this._buttonDisableRenderer = cc.Scale9Sprite.create();
- }
- else {
- this._buttonNormalRenderer = cc.Sprite.create();
- this._buttonClickedRenderer = cc.Sprite.create();
- this._buttonDisableRenderer = cc.Sprite.create();
- }
-
- this.loadTextureNormal(this._normalFileName, this._normalTexType);
- this.loadTexturePressed(this._clickedFileName, this._pressedTexType);
- this.loadTextureDisabled(this._disabledFileName, this._disabledTexType);
- this._renderer.addChild(this._buttonNormalRenderer, NORMALRENDERERZ);
- this._renderer.addChild(this._buttonClickedRenderer, PRESSEDRENDERERZ);
- this._renderer.addChild(this._buttonDisableRenderer, DISABLEDRENDERERZ);
- if (this._scale9Enabled) {
- var ignoreBefore = this._ignoreSize;
- this.ignoreContentAdaptWithSize(false);
- this._prevIgnoreSize = ignoreBefore;
- }
- else {
- this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
- }
- this.setCapInsetsNormalRenderer(this._capInsetsNormal);
- this.setCapInsetsPressedRenderer(this._capInsetsPressed);
- this.setCapInsetsDisabledRenderer(this._capInsetsDisabled);
- this.setBright(this._bright);
- },
-
- /**
- * ignoreContentAdaptWithSize
- * @param {Boolean} ignore
- */
- ignoreContentAdaptWithSize: function (ignore) {
- if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
- cc.UIWidget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
- this._prevIgnoreSize = ignore;
- }
- },
-
- /**
- * Load textures for button.
- * @param {String} normal
- * @param {String} selected
- * @param {String} disabled
- * @param {cc.TextureResType} texType
- */
- loadTextures: function (normal, selected, disabled, texType) {
- this.loadTextureNormal(normal, texType);
- this.loadTexturePressed(selected, texType);
- this.loadTextureDisabled(disabled, texType);
- },
-
- /**
- * Load normal state texture for button.
- * @param {String} normal
- * @param {cc.TextureResType} texType
- */
- loadTextureNormal: function (normal, texType) {
- if (!normal) {
- return;
- }
- texType = texType||cc.TextureResType.LOCAL;
- this._normalFileName = normal;
- this._normalTexType = texType;
- if (this._scale9Enabled) {
- switch (this._normalTexType) {
- case cc.TextureResType.LOCAL:
- this._buttonNormalRenderer.initWithFile(normal);
- break;
- case cc.TextureResType.PLIST:
- this._buttonNormalRenderer.initWithSpriteFrameName(normal);
- break;
- default:
- break;
- }
- this._buttonNormalRenderer.setColor(this.getColor());
- this._buttonNormalRenderer.setOpacity(this.getOpacity());
- }
- else {
- switch (this._normalTexType) {
- case cc.TextureResType.LOCAL:
- this._buttonNormalRenderer.initWithFile(normal);
- break;
- case cc.TextureResType.PLIST:
- this._buttonNormalRenderer.initWithSpriteFrameName(normal);
- break;
- default:
- break;
- }
- this._buttonNormalRenderer.setColor(this.getColor());
- this._buttonNormalRenderer.setOpacity(this.getOpacity());
- }
- this._normalTextureSize = this._buttonNormalRenderer.getContentSize();
- this.updateAnchorPoint();
- this.normalTextureScaleChangedWithSize();
- },
-
- /**
- * Load selected state texture for button.
- * @param {String} selected
- * @param {cc.TextureResType} texType
- */
- loadTexturePressed: function (selected, texType) {
- if (!selected) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._clickedFileName = selected;
- this._pressedTexType = texType;
- if (this._scale9Enabled) {
- switch (this._pressedTexType) {
- case cc.TextureResType.LOCAL:
- this._buttonClickedRenderer.initWithFile(selected);
- break;
- case cc.TextureResType.PLIST:
- this._buttonClickedRenderer.initWithSpriteFrameName(selected);
- break;
- default:
- break;
- }
- this._buttonClickedRenderer.setColor(this.getColor());
- this._buttonClickedRenderer.setOpacity(this.getOpacity());
- }
- else {
- switch (this._pressedTexType) {
- case cc.TextureResType.LOCAL:
- this._buttonClickedRenderer.initWithFile(selected);
- break;
- case cc.TextureResType.PLIST:
- this._buttonClickedRenderer.initWithSpriteFrameName(selected);
- break;
- default:
- break;
- }
- this._buttonClickedRenderer.setColor(this.getColor());
- this._buttonClickedRenderer.setOpacity(this.getOpacity());
- }
- this._pressedTextureSize = this._buttonClickedRenderer.getContentSize();
- this.updateAnchorPoint();
- this.pressedTextureScaleChangedWithSize();
- },
-
- /**
- * Load dark state texture for button.
- * @param {String} disabled
- * @param {cc.TextureResType} texType
- */
- loadTextureDisabled: function (disabled, texType) {
- if (!disabled) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._disabledFileName = disabled;
- this._disabledTexType = texType;
- if (this._scale9Enabled) {
- switch (this._disabledTexType) {
- case cc.TextureResType.LOCAL:
- this._buttonDisableRenderer.initWithFile(disabled);
- break;
- case cc.TextureResType.PLIST:
- this._buttonDisableRenderer.initWithSpriteFrameName(disabled);
- break;
- default:
- break;
- }
- this._buttonDisableRenderer.setColor(this.getColor());
- this._buttonDisableRenderer.setOpacity(this.getOpacity());
- }
- else {
- switch (this._disabledTexType) {
- case cc.TextureResType.LOCAL:
- this._buttonDisableRenderer.initWithFile(disabled);
- break;
- case cc.TextureResType.PLIST:
- this._buttonDisableRenderer.initWithSpriteFrameName(disabled);
- break;
- default:
- break;
- }
- this._buttonDisableRenderer.setColor(this.getColor());
- this._buttonDisableRenderer.setOpacity(this.getOpacity());
- }
- this._disabledTextureSize = this._buttonDisableRenderer.getContentSize();
- this.updateAnchorPoint();
- this.disabledTextureScaleChangedWithSize();
- },
-
- /**
- * Sets capinsets for button, if button is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsets: function (capInsets) {
- this.setCapInsetsNormalRenderer(capInsets);
- this.setCapInsetsPressedRenderer(capInsets);
- this.setCapInsetsDisabledRenderer(capInsets);
- },
-
- /**
- * Sets capinsets for button, if button is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsetsNormalRenderer: function (capInsets) {
- this._capInsetsNormal = capInsets;
- if (!this._scale9Enabled) {
- return;
- }
- this._buttonNormalRenderer.setCapInsets(capInsets);
- },
-
- /**
- * Sets capinsets for button, if button is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsetsPressedRenderer: function (capInsets) {
- this._capInsetsPressed = capInsets;
- if (!this._scale9Enabled) {
- return;
- }
- this._buttonClickedRenderer.setCapInsets(capInsets);
- },
-
- /**
- * Sets capinsets for button, if button is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsetsDisabledRenderer: function (capInsets) {
- this._capInsetsDisabled = capInsets;
- if (!this._scale9Enabled) {
- return;
- }
- this._buttonDisableRenderer.setCapInsets(capInsets);
- },
-
- onPressStateChangedToNormal: function () {
- this._buttonNormalRenderer.setVisible(true);
- this._buttonClickedRenderer.setVisible(false);
- this._buttonDisableRenderer.setVisible(false);
- if (this._pressedActionEnabled) {
- this._buttonNormalRenderer.stopAllActions();
- this._buttonClickedRenderer.stopAllActions();
- this._buttonDisableRenderer.stopAllActions();
- var zoomAction = cc.ScaleTo.create(0.05, 1.0);
- var zoomAction1 = cc.ScaleTo.create(0.05, 1.0);
- var zoomAction2 = cc.ScaleTo.create(0.05, 1.0);
- this._buttonNormalRenderer.runAction(zoomAction);
- this._buttonClickedRenderer.runAction(zoomAction1);
- this._buttonDisableRenderer.runAction(zoomAction2);
- }
- },
-
- onPressStateChangedToPressed: function () {
- this._buttonNormalRenderer.setVisible(false);
- this._buttonClickedRenderer.setVisible(true);
- this._buttonDisableRenderer.setVisible(false);
- if (this._pressedActionEnabled) {
- this._buttonNormalRenderer.stopAllActions();
- this._buttonClickedRenderer.stopAllActions();
- this._buttonDisableRenderer.stopAllActions();
- var zoomAction = cc.ScaleTo.create(0.05, 1.1);
- var zoomAction1 = cc.ScaleTo.create(0.05, 1.1);
- var zoomAction2 = cc.ScaleTo.create(0.05, 1.1);
- this._buttonNormalRenderer.runAction(zoomAction);
- this._buttonClickedRenderer.runAction(zoomAction1);
- this._buttonDisableRenderer.runAction(zoomAction2);
- }
- },
-
- onPressStateChangedToDisabled: function () {
- this._buttonNormalRenderer.setVisible(false);
- this._buttonClickedRenderer.setVisible(false);
- this._buttonDisableRenderer.setVisible(true);
- },
-
- /**
- * override "setFlippedX" of widget.
- * @param {Boolean} flipX
- */
- setFlippedX: function (flipX) {
- this._titleRenderer.setFlippedX(flipX);
- if (this._scale9Enabled) {
- return;
- }
- this._buttonNormalRenderer.setFlippedX(flipX);
- this._buttonClickedRenderer.setFlippedX(flipX);
- this._buttonDisableRenderer.setFlippedX(flipX);
- },
-
- /**
- * override "setFlippedY" of widget.
- * @param {Boolean} flipY
- */
- setFlippedY: function (flipY) {
- this._titleRenderer.setFlippedY(flipY);
- if (this._scale9Enabled) {
- return;
- }
- this._buttonNormalRenderer.setFlippedY(flipY);
- this._buttonClickedRenderer.setFlippedY(flipY);
- this._buttonDisableRenderer.setFlippedY(flipY);
- },
-
- /**
- * override "isFlippedX" of widget.
- * @returns {Boolean}
- */
- isFlippedX: function () {
- if (this._scale9Enabled) {
- return false;
- }
- return this._buttonNormalRenderer.isFlippedX();
- },
-
- /**
- * override "isFlippedY" of widget.
- * @returns {Boolean}
- */
- isFlippedY: function () {
- if (this._scale9Enabled) {
- return false;
- }
- return this._buttonNormalRenderer.isFlippedY();
- },
-
- /**
- * override "setAnchorPoint" of widget.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- cc.UIWidget.prototype.setAnchorPoint.call(this,pt);
- this._buttonNormalRenderer.setAnchorPoint(pt);
- this._buttonClickedRenderer.setAnchorPoint(pt);
- this._buttonDisableRenderer.setAnchorPoint(pt);
- this._titleRenderer.setPosition(cc.p(this._size.width * (0.5 - this._anchorPoint.x), this._size.height * (0.5 - this._anchorPoint.y)));
- },
-
- onSizeChanged: function () {
- this.normalTextureScaleChangedWithSize();
- this.pressedTextureScaleChangedWithSize();
- this.disabledTextureScaleChangedWithSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._normalTextureSize;
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- if (this._bright) {
- switch (this._brightStyle) {
- case cc.BrightStyle.NORMAL:
- return this._buttonNormalRenderer;
- case cc.BrightStyle.HIGHLIGHT:
- return this._buttonClickedRenderer;
- default:
- return null;
- }
- }
- else {
- return this._buttonDisableRenderer;
- }
- },
-
- normalTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- if (!this._scale9Enabled) {
- this._buttonNormalRenderer.setScale(1.0);
- this._size = this._normalTextureSize;
- }
- }
- else {
- if (this._scale9Enabled) {
- this._buttonNormalRenderer.setPreferredSize(this._size);
- }
- else {
- var textureSize = this._normalTextureSize;
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._buttonNormalRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._buttonNormalRenderer.setScaleX(scaleX);
- this._buttonNormalRenderer.setScaleY(scaleY);
- }
- }
- },
-
- pressedTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- if (!this._scale9Enabled) {
- this._buttonClickedRenderer.setScale(1.0);
- }
- }
- else {
- if (this._scale9Enabled) {
- this._buttonClickedRenderer.setPreferredSize(this._size);
- }
- else {
- var textureSize = this._pressedTextureSize;
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._buttonClickedRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / this._pressedTextureSize.width;
- var scaleY = this._size.height / this._pressedTextureSize.height;
- this._buttonClickedRenderer.setScaleX(scaleX);
- this._buttonClickedRenderer.setScaleY(scaleY);
- }
- }
- },
-
- disabledTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- if (!this._scale9Enabled) {
- this._buttonDisableRenderer.setScale(1.0);
- }
- }
- else {
- if (this._scale9Enabled) {
- this._buttonDisableRenderer.setPreferredSize(this._size);
- }
- else {
- var textureSize = this._disabledTextureSize;
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._buttonDisableRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / this._disabledTextureSize.width;
- var scaleY = this._size.height / this._disabledTextureSize.height;
- this._buttonDisableRenderer.setScaleX(scaleX);
- this._buttonDisableRenderer.setScaleY(scaleY);
- }
- }
- },
-
- /**
- * Changes if button can be clicked zoom effect.
- * @param {Boolean} enabled
- */
- setPressedActionEnabled: function (enabled) {
- this._pressedActionEnabled = enabled;
- },
-
- /**
- * set title text
- * @param {String} text
- */
- setTitleText: function (text) {
- this._titleRenderer.setString(text);
- },
-
- /**
- * get title text
- * @returns {String} text
- */
- getTitleText: function () {
- return this._titleRenderer.getString();
- },
-
- /**
- * set title color
- * @param {cc.c3b} color
- */
- setTitleColor: function (color) {
- this._titleColor = color;
- this._titleRenderer.setColor(color);
- },
-
- /**
- * get title color
- * @returns {cc.c3b}
- */
- getTitleColor: function () {
- return this._titleRenderer.getColor();
- },
-
- /**
- * set title fontSize
- * @param {cc.Size} size
- */
- setTitleFontSize: function (size) {
- this._titleRenderer.setFontSize(size);
- },
-
- /**
- * get title fontSize
- * @returns {cc.Size}
- */
- getTitleFontSize: function () {
- return this._titleRenderer.getFontSize();
- },
-
- /**
- * set title fontName
- * @param {String} fontName
- */
- setTitleFontName: function (fontName) {
- this._titleRenderer.setFontName(fontName);
- },
-
- /**
- * get title fontName
- * @returns {String}
- */
- getTitleFontName: function () {
- return this._titleRenderer.getFontName();
- },
-
- /**
- * Sets color to widget
- * It default change the color of widget's children.
- * @param color
- */
- setColor: function (color) {
- cc.UIWidget.prototype.setColor.call(this,color);
- this.setTitleColor(this._titleColor);
- },
-
- getDescription: function () {
- return "Button";
- }
-
-});
-cc.UIButton.create = function () {
- var uiButton = new cc.UIButton();
- if (uiButton && uiButton.init()) {
- return uiButton;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UICheckBox.js b/extensions/CocoStudio/GUI/UIWidgets/UICheckBox.js
deleted file mode 100644
index c6cb7af173..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UICheckBox.js
+++ /dev/null
@@ -1,481 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-cc.CheckBoxEventType = {
- SELECTED: 0,
- UNSELECTED: 1
-};
-
-/**
- * Base class for cc.UICheckBox
- * @class
- * @extends cc.UIWidget
- */
-cc.UICheckBox = cc.UIWidget.extend({
- _backGroundBoxRenderer: null,
- _backGroundSelectedBoxRenderer: null,
- _frontCrossRenderer: null,
- _backGroundBoxDisabledRenderer: null,
- _frontCrossDisabledRenderer: null,
- _isSelected: true,
- _selectedStateEventListener: null,
- _selectedStateEventSelector: null,
- _backGroundTexType: null,
- _backGroundSelectedTexType: null,
- _frontCrossTexType: null,
- _backGroundDisabledTexType: null,
- _frontCrossDisabledTexType: null,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._backGroundBoxRenderer = null;
- this._backGroundSelectedBoxRenderer = null;
- this._frontCrossRenderer = null;
- this._backGroundBoxDisabledRenderer = null;
- this._frontCrossDisabledRenderer = null;
- this._isSelected = true;
- this._selectedStateEventListener = null;
- this._selectedStateEventSelector = null;
- this._backGroundTexType = cc.TextureResType.LOCAL;
- this._backGroundSelectedTexType = cc.TextureResType.LOCAL;
- this._frontCrossTexType = cc.TextureResType.LOCAL;
- this._backGroundDisabledTexType = cc.TextureResType.LOCAL;
- this._frontCrossDisabledTexType = cc.TextureResType.LOCAL;
- },
- init: function () {
- if (cc.UIWidget.prototype.init.call(this)) {
- this.setSelectedState(false);
- return true;
- }
- return false;
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._backGroundBoxRenderer = cc.Sprite.create();
- this._backGroundSelectedBoxRenderer = cc.Sprite.create();
- this._frontCrossRenderer = cc.Sprite.create();
- this._backGroundBoxDisabledRenderer = cc.Sprite.create();
- this._frontCrossDisabledRenderer = cc.Sprite.create();
- this._renderer.addChild(this._backGroundBoxRenderer);
- this._renderer.addChild(this._backGroundSelectedBoxRenderer);
- this._renderer.addChild(this._frontCrossRenderer);
- this._renderer.addChild(this._backGroundBoxDisabledRenderer);
- this._renderer.addChild(this._frontCrossDisabledRenderer);
- },
-
- /**
- * Load textures for checkbox.
- * @param {String} backGround
- * @param {String} backGroundSelected
- * @param {String} cross
- * @param {String} backGroundDisabled
- * @param {String} frontCrossDisabled
- * @param {cc.TextureResType} texType
- */
- loadTextures: function (backGround, backGroundSelected, cross, backGroundDisabled, frontCrossDisabled, texType) {
- this.loadTextureBackGround(backGround, texType);
- this.loadTextureBackGroundSelected(backGroundSelected, texType);
- this.loadTextureFrontCross(cross, texType);
- this.loadTextureBackGroundDisabled(backGroundDisabled, texType);
- this.loadTextureFrontCrossDisabled(frontCrossDisabled, texType);
- },
-
- /**
- * Load backGround texture for checkbox.
- * @param {String} backGround
- * @param {cc.TextureResType} texType
- */
- loadTextureBackGround: function (backGround, texType) {
- if (!backGround) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._backGroundTexType = texType;
- switch (this._backGroundTexType) {
- case cc.TextureResType.LOCAL:
- this._backGroundBoxRenderer.initWithFile(backGround);
- break;
- case cc.TextureResType.PLIST:
- this._backGroundBoxRenderer.initWithSpriteFrameName(backGround);
- break;
- default:
- break;
- }
- this._backGroundBoxRenderer.setColor(this.getColor());
- this._backGroundBoxRenderer.setOpacity(this.getOpacity());
- this.backGroundTextureScaleChangedWithSize();
- },
-
- /**
- * Load backGroundSelected texture for checkbox.
- * @param {String} backGroundSelected
- * @param {cc.TextureResType} texType
- */
- loadTextureBackGroundSelected: function (backGroundSelected, texType) {
- if (!backGroundSelected) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._backGroundSelectedTexType = texType;
- switch (this._backGroundSelectedTexType) {
- case cc.TextureResType.LOCAL:
- this._backGroundSelectedBoxRenderer.initWithFile(backGroundSelected);
- break;
- case cc.TextureResType.PLIST:
- this._backGroundSelectedBoxRenderer.initWithSpriteFrameName(backGroundSelected);
- break;
- default:
- break;
- }
- this._backGroundSelectedBoxRenderer.setColor(this.getColor());
- this._backGroundSelectedBoxRenderer.setOpacity(this.getOpacity());
- this.backGroundSelectedTextureScaleChangedWithSize();
- },
-
- /**
- * Load cross texture for checkbox.
- * @param {String} cross
- * @param {cc.TextureResType} texType
- */
- loadTextureFrontCross: function (cross, texType) {
- if (!cross) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._frontCrossTexType = texType;
- switch (this._frontCrossTexType) {
- case cc.TextureResType.LOCAL:
- this._frontCrossRenderer.initWithFile(cross);
- break;
- case cc.TextureResType.PLIST:
- this._frontCrossRenderer.initWithSpriteFrameName(cross);
- break;
- default:
- break;
- }
- this._frontCrossRenderer.setColor(this.getColor());
- this._frontCrossRenderer.setOpacity(this.getOpacity());
- this.frontCrossTextureScaleChangedWithSize();
- },
-
- /**
- * Load backGroundDisabled texture for checkbox.
- * @param {String} backGroundDisabled
- * @param {cc.TextureResType} texType
- */
- loadTextureBackGroundDisabled: function (backGroundDisabled, texType) {
- if (!backGroundDisabled) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._backGroundDisabledTexType = texType;
- switch (this._backGroundDisabledTexType) {
- case cc.TextureResType.LOCAL:
- this._backGroundBoxDisabledRenderer.initWithFile(backGroundDisabled);
- break;
- case cc.TextureResType.PLIST:
- this._backGroundBoxDisabledRenderer.initWithSpriteFrameName(backGroundDisabled);
- break;
- default:
- break;
- }
- this._backGroundBoxDisabledRenderer.setColor(this.getColor());
- this._backGroundBoxDisabledRenderer.setOpacity(this.getOpacity());
- this.backGroundDisabledTextureScaleChangedWithSize();
- },
-
- /**
- * Load frontCrossDisabled texture for checkbox.
- * @param {String} frontCrossDisabled
- * @param {cc.TextureResType} texType
- */
- loadTextureFrontCrossDisabled: function (frontCrossDisabled, texType) {
- if (!frontCrossDisabled) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._frontCrossDisabledTexType = texType;
- switch (this._frontCrossDisabledTexType) {
- case cc.TextureResType.LOCAL:
- this._frontCrossDisabledRenderer.initWithFile(frontCrossDisabled);
- break;
- case cc.TextureResType.PLIST:
- this._frontCrossDisabledRenderer.initWithSpriteFrameName(frontCrossDisabled);
- break;
- default:
- break;
- }
- this._frontCrossDisabledRenderer.setColor(this.getColor());
- this._frontCrossRenderer.setOpacity(this.getOpacity());
- this.frontCrossDisabledTextureScaleChangedWithSize();
- },
-
- onTouchEnded: function (touchPoint) {
- if (this._focus) {
- this.releaseUpEvent();
- if (this._isSelected) {
- this.setSelectedState(false);
- this.unSelectedEvent();
- }
- else {
- this.setSelectedState(true);
- this.selectedEvent();
- }
- }
- this.setFocused(false);
- this._widgetParent.checkChildInfo(2, this, touchPoint);
- },
-
- onPressStateChangedToNormal: function () {
- this._backGroundBoxRenderer.setVisible(true);
- this._backGroundSelectedBoxRenderer.setVisible(false);
- this._backGroundBoxDisabledRenderer.setVisible(false);
- this._frontCrossDisabledRenderer.setVisible(false);
- },
-
- onPressStateChangedToPressed: function () {
- this._backGroundBoxRenderer.setVisible(false);
- this._backGroundSelectedBoxRenderer.setVisible(true);
- this._backGroundBoxDisabledRenderer.setVisible(false);
- this._frontCrossDisabledRenderer.setVisible(false);
- },
-
- onPressStateChangedToDisabled: function () {
- this._backGroundBoxRenderer.setVisible(false);
- this._backGroundSelectedBoxRenderer.setVisible(false);
- this._backGroundBoxDisabledRenderer.setVisible(true);
- this._frontCrossRenderer.setVisible(false);
- if (this._isSelected) {
- this._frontCrossDisabledRenderer.setVisible(true);
- }
- },
-
- setSelectedState: function (selected) {
- if (selected == this._isSelected) {
- return;
- }
- this._isSelected = selected;
- this._frontCrossRenderer.setVisible(this._isSelected);
- },
-
- getSelectedState: function () {
- return this._isSelected;
- },
-
- selectedEvent: function () {
- if (this._selectedStateEventListener && this._selectedStateEventSelector) {
- this._selectedStateEventSelector.call(this._selectedStateEventListener, this, cc.CheckBoxEventType.SELECTED);
- }
- },
-
- unSelectedEvent: function () {
- if (this._selectedStateEventListener && this._selectedStateEventSelector) {
- this._selectedStateEventSelector.call(this._selectedStateEventListener, this, cc.CheckBoxEventType.UNSELECTED);
- }
- },
-
- /**
- * add event listener
- * @param {Object} target
- * @param {Function} selector
- */
- addEventListener: function (target, selector) {
- this._selectedStateEventListener = target;
- this._selectedStateEventSelector = selector;
- },
-
- /**
- * Sets whether the widget should be flipped horizontally or not.
- * @param {Boolean} flipX
- */
- setFlippedX: function (flipX) {
- this._backGroundBoxRenderer.setFlippedX(flipX);
- this._backGroundSelectedBoxRenderer.setFlippedX(flipX);
- this._frontCrossRenderer.setFlippedX(flipX);
- this._backGroundBoxDisabledRenderer.setFlippedX(flipX);
- this._frontCrossDisabledRenderer.setFlippedX(flipX);
- },
-
- /**
- * override "setFlippedY" of widget.
- * @param {Boolean} flipY
- */
- setFlippedY: function (flipY) {
- this._backGroundBoxRenderer.setFlippedY(flipY);
- this._backGroundSelectedBoxRenderer.setFlippedY(flipY);
- this._frontCrossRenderer.setFlippedY(flipY);
- this._backGroundBoxDisabledRenderer.setFlippedY(flipY);
- this._frontCrossDisabledRenderer.setFlippedY(flipY);
- },
-
- /**
- * override "isFlippedX" of widget.
- * @returns {Boolean}
- */
- isFlippedX: function () {
- return this._backGroundBoxRenderer.isFlippedX();
- },
-
- /**
- * override "isFlippedY" of widget.
- * @returns {Boolean}
- */
- isFlippedY: function () {
- return this._backGroundBoxRenderer.isFlippedY();
- },
-
- /**
- * override "setAnchorPoint" of widget.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- cc.UIWidget.prototype.setAnchorPoint.call(this, pt);
- this._backGroundBoxRenderer.setAnchorPoint(pt);
- this._backGroundSelectedBoxRenderer.setAnchorPoint(pt);
- this._backGroundBoxDisabledRenderer.setAnchorPoint(pt);
- this._frontCrossRenderer.setAnchorPoint(pt);
- this._frontCrossDisabledRenderer.setAnchorPoint(pt);
- },
-
- onSizeChanged: function () {
- this.backGroundTextureScaleChangedWithSize();
- this.backGroundSelectedTextureScaleChangedWithSize();
- this.frontCrossTextureScaleChangedWithSize();
- this.backGroundDisabledTextureScaleChangedWithSize();
- this.frontCrossDisabledTextureScaleChangedWithSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._backGroundBoxRenderer.getContentSize();
- },
-
- /**
- * override "getVirtualRenderer" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._backGroundBoxRenderer;
- },
-
- backGroundTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._backGroundBoxRenderer.setScale(1.0);
- this._size = this._backGroundBoxRenderer.getContentSize();
- }
- else {
- var textureSize = this._backGroundBoxRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._backGroundBoxRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._backGroundBoxRenderer.setScaleX(scaleX);
- this._backGroundBoxRenderer.setScaleY(scaleY);
- }
- },
-
- backGroundSelectedTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._backGroundSelectedBoxRenderer.setScale(1.0);
- }
- else {
- var textureSize = this._backGroundSelectedBoxRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._backGroundSelectedBoxRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._backGroundSelectedBoxRenderer.setScaleX(scaleX);
- this._backGroundSelectedBoxRenderer.setScaleY(scaleY);
- }
- },
-
- frontCrossTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._frontCrossRenderer.setScale(1.0);
- }
- else {
- var textureSize = this._frontCrossRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._frontCrossRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._frontCrossRenderer.setScaleX(scaleX);
- this._frontCrossRenderer.setScaleY(scaleY);
- }
- },
-
- backGroundDisabledTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._backGroundBoxDisabledRenderer.setScale(1.0);
- }
- else {
- var textureSize = this._backGroundBoxDisabledRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._backGroundBoxDisabledRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._backGroundBoxDisabledRenderer.setScaleX(scaleX);
- this._backGroundBoxDisabledRenderer.setScaleY(scaleY);
- }
- },
-
- frontCrossDisabledTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._frontCrossDisabledRenderer.setScale(1.0);
- }
- else {
- var textureSize = this._frontCrossDisabledRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._frontCrossDisabledRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._frontCrossDisabledRenderer.setScaleX(scaleX);
- this._frontCrossDisabledRenderer.setScaleY(scaleY);
- }
- },
-
- getDescription: function () {
- return "CheckBox";
- }
-});
-
-cc.UICheckBox.create = function () {
- var uiCheckBox = new cc.UICheckBox();
- if (uiCheckBox && uiCheckBox.init()) {
- return uiCheckBox;
- }
- return null;
-};
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UIImageView.js b/extensions/CocoStudio/GUI/UIWidgets/UIImageView.js
deleted file mode 100644
index 3e0fb5be50..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UIImageView.js
+++ /dev/null
@@ -1,346 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.UIButton
- * @class
- * @extends cc.UIWidget
- */
-cc.UIImageView = cc.UIWidget.extend({
- _clickCount: 0,
- _clickTimeInterval: 0,
- _startCheckDoubleClick: false,
- _touchRelease: false,
- _doubleClickEnabled: false,
- _scale9Enabled: false,
- _prevIgnoreSize: true,
- _capInsets: null,
- _imageRenderer: null,
- _textureFile: "",
- _imageTexType: null,
- _imageTextureSize: null,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._clickCount = 0;
- this._clickTimeInterval = 0;
- this._startCheckDoubleClick = false;
- this._touchRelease = false;
- this._doubleClickEnabled = false;
- this._scale9Enabled = false;
- this._prevIgnoreSize = true;
- this._capInsets = null;
- this._imageRenderer = null;
- this._textureFile = "";
- this._imageTexType = cc.TextureResType.LOCAL;
- this._imageTextureSize = this._size;
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._imageRenderer = cc.Sprite.create();
- this._renderer.addChild(this._imageRenderer);
- },
-
- /**
- * Load textures for button.
- * @param {String} fileName
- * @param {cc.TextureResType} texType
- */
- loadTexture: function (fileName, texType) {
- if (!fileName) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._textureFile = fileName;
- this._imageTexType = texType;
- switch (this._imageTexType) {
- case cc.TextureResType.LOCAL:
- if (this._scale9Enabled) {
- this._imageRenderer.initWithFile(fileName);
- this._imageRenderer.setColor(this.getColor());
- this._imageRenderer.setOpacity(this.getOpacity());
- }
- else {
- this._imageRenderer.initWithFile(fileName);
- this._imageRenderer.setColor(this.getColor());
- this._imageRenderer.setOpacity(this.getOpacity());
- }
- break;
- case cc.TextureResType.PLIST:
- if (this._scale9Enabled) {
- this._imageRenderer.initWithSpriteFrameName(fileName);
- this._imageRenderer.setColor(this.getColor());
- this._imageRenderer.setOpacity(this.getOpacity());
- }
- else {
- this._imageRenderer.initWithSpriteFrameName(fileName);
- this._imageRenderer.setColor(this.getColor());
- this._imageRenderer.setOpacity(this.getOpacity());
- }
- break;
- default:
- break;
- }
- this._imageTextureSize = this._imageRenderer.getContentSize();
- this.updateAnchorPoint();
- this.imageTextureScaleChangedWithSize();
- },
-
- /**
- * set texture rect
- * @param {cc.Rect} rect
- */
- setTextureRect: function (rect) {
- if (!this._scale9Enabled){
- this._imageRenderer.setTextureRect(rect);
- }
- },
-
- onTouchBegan: function (touchPoint) {
- this.setFocused(true);
- this._touchStartPos.x = touchPoint.x;
- this._touchStartPos.y = touchPoint.y;
- this._widgetParent.checkChildInfo(0, this, touchPoint);
- this.pushDownEvent();
-
- if (this._doubleClickEnabled) {
- this._clickTimeInterval = 0;
- this._startCheckDoubleClick = true;
- this._clickCount++;
- this._touchRelease = false;
- }
- return this._touchPassedEnabled;
- },
-
- onTouchEnded: function (touchPoint) {
- if (this._doubleClickEnabled) {
- if (this._clickCount >= 2) {
- this.doubleClickEvent();
- this._clickCount = 0;
- this._startCheckDoubleClick = false;
- }
- else {
- this._touchRelease = true;
- }
- }
- else {
- cc.UIWidget.prototype.onTouchEnded.call(this, touchPoint);
- }
- },
-
- doubleClickEvent: function () {
-
- },
-
- checkDoubleClick: function (dt) {
- if (this._startCheckDoubleClick) {
- this._clickTimeInterval += dt;
- if (this._clickTimeInterval >= 200 && this._clickCount > 0) {
- this._clickTimeInterval = 0;
- this._clickCount--;
- this._startCheckDoubleClick = false;
- }
- }
- else {
- if (this._clickCount <= 1) {
- if (this._touchRelease) {
- this.releaseUpEvent();
- this._clickTimeInterval = 0;
- this._clickCount = 0;
- this._touchRelease = false;
- }
- }
- }
- },
-
- setDoubleClickEnabled: function (bool) {
- if (bool == this._doubleClickEnabled) {
- return;
- }
- this._doubleClickEnabled = bool;
- },
-
- /**
- * Sets whether the widget should be flipped horizontally or not.
- * @param {Boolean} flipX
- */
- setFlippedX: function (flipX) {
- if (!this._scale9Enabled) {
- this._imageRenderer.setFlippedX(flipX);
- }
- },
-
- /**
- * override "setFlippedY" of widget.
- * @param {Boolean} flipY
- */
- setFlippedY: function (flipY) {
- if (!this._scale9Enabled) {
- this._imageRenderer.setFlippedY(flipY);
- }
- },
-
- /**
- * override "isFlippedX" of widget.
- * @returns {Boolean}
- */
- isFlippedX: function () {
- if (this._scale9Enabled)
- return false;
- else
- return this._imageRenderer.isFlippedX();
- },
-
- /**
- * override "isFlippedY" of widget.
- * @returns {Boolean}
- */
- isFlippedY: function () {
- if (this._scale9Enabled)
- return false;
- else
- return this._imageRenderer.isFlippedY();
- },
-
- /**
- * Sets if button is using scale9 renderer.
- * @param {Boolean} able
- */
- setScale9Enabled: function (able) {
- if (this._scale9Enabled == able) {
- return;
- }
-
-
- this._scale9Enabled = able;
- this._renderer.removeChild(this._imageRenderer, true);
- this._imageRenderer = null;
- if (this._scale9Enabled) {
- this._imageRenderer = cc.Scale9Sprite.create();
- }
- else {
- this._imageRenderer = cc.Sprite.create();
- }
- this.loadTexture(this._textureFile, this._imageTexType);
- this._renderer.addChild(this._imageRenderer);
- if (this._scale9Enabled) {
- var ignoreBefore = this._ignoreSize;
- this.ignoreContentAdaptWithSize(false);
- this._prevIgnoreSize = ignoreBefore;
- }
- else {
- this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
- }
- this.setCapInsets(this._capInsets);
- },
-
- /**
- * ignoreContentAdaptWithSize
- * @param {Boolean} ignore
- */
- ignoreContentAdaptWithSize: function (ignore) {
- if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
- cc.UIWidget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
- this._prevIgnoreSize = ignore;
- }
- },
-
- /**
- * Sets capinsets for button, if button is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsets: function (capInsets) {
- this._capInsets = capInsets;
- if (!this._scale9Enabled) {
- return;
- }
- this._imageRenderer.setCapInsets(capInsets);
- },
-
- /**
- * override "setAnchorPoint" of widget.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- cc.UIWidget.prototype.setAnchorPoint.call(this, pt);
- this._imageRenderer.setAnchorPoint(pt);
- },
-
- onSizeChanged: function () {
- this.imageTextureScaleChangedWithSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._imageTextureSize;
- },
-
- /**
- * override "getVirtualRenderer" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._imageRenderer;
- },
-
- imageTextureScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- if (!this._scale9Enabled) {
- this._imageRenderer.setScale(1.0);
- this._size = this._imageTextureSize;
- }
- }
- else {
- if (this._scale9Enabled) {
- this._imageRenderer.setPreferredSize(this._size);
- }
- else {
- var textureSize = this._imageRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._imageRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._imageRenderer.setScaleX(scaleX);
- this._imageRenderer.setScaleY(scaleY);
- }
- }
- },
- getDescription: function () {
- return "ImageView";
- }
-
-});
-
-cc.UIImageView.create = function () {
- var uiImageView = new cc.UIImageView();
- if (uiImageView && uiImageView.init()) {
- return uiImageView;
- }
- return null;
-};
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UILabel.js b/extensions/CocoStudio/GUI/UIWidgets/UILabel.js
deleted file mode 100644
index eb7a71dc70..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UILabel.js
+++ /dev/null
@@ -1,280 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.UIButton
- * @class
- * @extends cc.UIWidget
- */
-cc.UILabel = cc.UIWidget.extend({
- _touchScaleChangeEnabled: false,
- _normalScaleValue: 0,
- _fontName: "",
- _fontSize: 0,
- _onSelectedScaleOffset: 0,
- _labelRenderer: "",
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._touchScaleChangeEnabled = false;
- this._normalScaleValue = 0;
- this._fontName = "Thonburi";
- this._fontSize = 10;
- this._onSelectedScaleOffset = 0.5;
- this._labelRenderer = "";
- },
-
- init: function () {
- if (cc.UIWidget.prototype.init.call(this)) {
- return true;
- }
- return false;
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._labelRenderer = cc.LabelTTF.create();
- this._renderer.addChild(this._labelRenderer);
- },
-
- /**
- * Changes the string value of label.
- * @param {String} text
- */
- setText: function (text) {
- if (!text) {
- return;
- }
- this._labelRenderer.setString(text);
- this.labelScaleChangedWithSize();
- },
-
- /**
- * Gets the string value of label.
- * @returns {String}
- */
- getStringValue: function () {
- return this._labelRenderer.getString();
- },
-
- /**
- * Gets the string length of label.
- * @returns {Number}
- */
- getStringLength: function () {
- var str = this._labelRenderer.getString();
- return str.length;
- },
-
- /**
- * set fontSize
- * @param {cc.Size} size
- */
- setFontSize: function (size) {
- this._labelRenderer.setFontSize(size);
- this.labelScaleChangedWithSize();
- },
-
- /**
- * set fontName
- * @param {String} name
- */
- setFontName: function (name) {
- this._labelRenderer.setFontName(name);
- this.labelScaleChangedWithSize();
- },
-
- /**
- * set textAreaSize
- * @param {cc.Size} size
- */
- setTextAreaSize: function (size) {
- this._labelRenderer.setDimensions(size);
- this.labelScaleChangedWithSize();
- },
-
- /**
- * set Horizontal Alignment of cc.LabelTTF
- * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
- */
- setTextHorizontalAlignment: function (alignment) {
- this._labelRenderer.setHorizontalAlignment(alignment);
- this.labelScaleChangedWithSize();
- },
-
- /**
- * set Vertical Alignment of cc.LabelTTF
- * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment
- */
- setTextVerticalAlignment: function (alignment) {
- this._labelRenderer.setVerticalAlignment(alignment);
- this.labelScaleChangedWithSize();
- },
-
- /**
- * Sets the touch scale enabled of label.
- * @param {Boolean} enable
- */
- setTouchScaleChangeAble: function (enable) {
- this.setTouchScaleChangeEnabled(enable);
- },
-
- /**
- * Gets the touch scale enabled of label.
- * @returns {Boolean}
- */
- getTouchScaleChangeAble: function () {
- return this.isTouchScaleChangeEnabled();
- },
-
- /**
- * Sets the touch scale enabled of label.
- * @param {Boolean} enable
- */
- setTouchScaleChangeEnabled: function (enable) {
- this._touchScaleChangeEnabled = enable;
- this._normalScaleValue = this.getScale();
- },
-
- /**
- * Gets the touch scale enabled of label.
- * @returns {Boolean}
- */
- isTouchScaleChangeEnabled: function () {
- return this._touchScaleChangeEnabled;
- },
-
- onPressStateChangedToNormal: function () {
- if (!this._touchScaleChangeEnabled) {
- return;
- }
- this.clickScale(this._normalScaleValue);
- },
-
- onPressStateChangedToPressed: function () {
- if (!this._touchScaleChangeEnabled) {
- return;
- }
- this.clickScale(this._normalScaleValue + this._onSelectedScaleOffset);
- },
-
- onPressStateChangedToDisabled: function () {
-
- },
-
- clickScale: function (scale) {
- this._renderer.setScale(scale);
- },
-
- /**
- * override "setFlippedX" of widget.
- * @param {Boolean} flipX
- */
- setFlippedX: function (flipX) {
- this._labelRenderer.setFlippedX(flipX);
- },
-
- /**
- * override "setFlippedY" of widget.
- * @param {Boolean} flipY
- */
- setFlippedY: function (flipY) {
- this._labelRenderer.setFlippedY(flipY);
- },
-
- /**
- * override "isFlippedX" of widget.
- * @returns {Boolean}
- */
- isFlippedX: function () {
- return this._labelRenderer.isFlippedX();
- },
-
- /**
- * override "isFlippedY" of widget.
- * @returns {Boolean}
- */
- isFlippedY: function () {
- return this._labelRenderer.isFlippedY();
- },
-
- /**
- * override "setAnchorPoint" of widget.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- cc.UIWidget.prototype.setAnchorPoint.call(this, pt);
- this._labelRenderer.setAnchorPoint(pt);
- },
-
- onSizeChanged: function () {
- this.labelScaleChangedWithSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._labelRenderer.getContentSize();
- },
-
- /**
- * override "getVirtualRenderer" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._labelRenderer;
- },
-
- labelScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._labelRenderer.setScale(1.0);
- this._size = this._labelRenderer.getContentSize();
- }
- else {
- var textureSize = this._labelRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._labelRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._labelRenderer.setScaleX(scaleX);
- this._labelRenderer.setScaleY(scaleY);
- }
-
- },
-
- getDescription: function () {
- return "Label";
- }
-});
-
-cc.UILabel.create = function () {
- var uiLabel = new cc.UILabel();
- if (uiLabel && uiLabel.init()) {
- return uiLabel;
- }
- return null;
-};
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UILabelAtlas.js b/extensions/CocoStudio/GUI/UIWidgets/UILabelAtlas.js
deleted file mode 100644
index 557b74da1b..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UILabelAtlas.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.UICCLabelAtlas
- * @class
- * @extends cc.LabelAtlas
- */
-cc.UICCLabelAtlas = cc.LabelAtlas.extend({
-
- setProperty: function (string, charMapFile, itemWidth, itemHeight, startCharMap) {
- this.initWithString(string, charMapFile, itemWidth, itemHeight, startCharMap);
- },
-
- setProperty: function (string, texture, itemWidth, itemHeight, startCharMap) {
- this.initWithString(string, texture, itemWidth, itemHeight, startCharMap);
- },
-
- draw: function () {
- if (!this._textureAtlas) {
- return;
- }
-
- cc.AtlasNode.prototype.draw.call(this);
- },
- updateDisplayedOpacity: function (opacity) {
- cc.AtlasNode.prototype.setOpacity.call(this, opacity);
- }
-});
-
-cc.UICCLabelAtlas.create = function () {
- var uiCCLabelAtlas = new cc.UICCLabelAtlas();
- if (uiCCLabelAtlas && uiCCLabelAtlas.init()) {
- return uiCCLabelAtlas;
- }
- return null;
-};
-
-/**
- * Base class for cc.UILabelAtlas
- * @class
- * @extends cc.UIWidget
- */
-cc.UILabelAtlas = cc.UIWidget.extend({
- _labelAtlasRenderer: null,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._labelAtlasRenderer = null;
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._labelAtlasRenderer = cc.UICCLabelAtlas.create();
- this._renderer.addChild(this._labelAtlasRenderer);
- },
-
- /**
- * initializes the UILabelAtlas with a string, a char map file(the atlas), the width and height of each element and the starting char of the atlas
- * @param {String} stringValue
- * @param {String} charMapFile
- * @param {number} itemWidth
- * @param {number} itemHeight
- * @param {String} startCharMap
- * @param {Boolean} useSpriteFrame
- */
- setProperty: function (stringValue, charMapFile, itemWidth, itemHeight, startCharMap, useSpriteFrame) {
- this._labelAtlasRenderer.setProperty(stringValue, charMapFile, itemWidth, itemHeight, startCharMap[0]);
- this.updateAnchorPoint();
- this.labelAtlasScaleChangedWithSize();
- },
-
- /**
- * set string value for labelatlas.
- * @param {String} value
- */
- setStringValue: function (value) {
- this._labelAtlasRenderer.setString(value);
- this.labelAtlasScaleChangedWithSize();
- },
-
- /**
- * get string value for labelatlas.
- * @returns {String}
- */
- getStringValue: function () {
- return this._labelAtlasRenderer.getString();
- },
-
- /**
- * override "setAnchorPoint" of widget.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- cc.UIWidget.prototype.setAnchorPoint.call(this, pt);
- this._labelAtlasRenderer.setAnchorPoint(cc.p(pt.x, pt.y));
- },
-
- onSizeChanged: function () {
- this.labelAtlasScaleChangedWithSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._labelAtlasRenderer.getContentSize();
- },
-
- /**
- * override "getVirtualRenderer" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._labelAtlasRenderer;
- },
-
- labelAtlasScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._labelAtlasRenderer.setScale(1.0);
- this._size = this._labelAtlasRenderer.getContentSize();
- }
- else {
- var textureSize = this._labelAtlasRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._labelAtlasRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._labelAtlasRenderer.setScaleX(scaleX);
- this._labelAtlasRenderer.setScaleY(scaleY);
- }
- },
-
- getDescription: function () {
- return "LabelAtlase";
- }
-});
-
-cc.UILabelAtlas.create = function () {
- var uiLabelAtlas = new cc.UILabelAtlas();
- if (uiLabelAtlas && uiLabelAtlas.init()) {
- return uiLabelAtlas;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UILabelBMFont.js b/extensions/CocoStudio/GUI/UIWidgets/UILabelBMFont.js
deleted file mode 100644
index 7050a8d995..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UILabelBMFont.js
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-/**
- * Base class for cc.UILabelBMFont
- * @class
- * @extends cc.UIWidget
- */
-cc.UILabelBMFont = cc.UIWidget.extend({
- _labelBMFontRenderer: null,
- _fileHasInit: false,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._labelBMFontRenderer = null;
- this._fileHasInit = false;
- },
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._labelBMFontRenderer = cc.LabelBMFont.create();
- this._renderer.addChild(this._labelBMFontRenderer);
- },
-
- /**
- * init a bitmap font atlas with an initial string and the FNT file
- * @param {String} fileName
- */
- setFntFile: function (fileName) {
- if (!fileName) {
- return;
- }
- this._labelBMFontRenderer.initWithString("", fileName);
- this.updateAnchorPoint();
- this.labelBMFontScaleChangedWithSize();
- this._fileHasInit = true;
- },
-
- /**
- * set string value for labelbmfont
- * @param {String} value
- */
- setText: function (value) {
- if (!value || !this._fileHasInit) {
- return;
- }
- this._labelBMFontRenderer.setString(value);
- this.labelBMFontScaleChangedWithSize();
- },
-
- /**
- * get string value for labelbmfont.
- * @returns {String}
- */
- getStringValue: function () {
- return this._labelBMFontRenderer.getString();
- },
-
- /**
- * override "setAnchorPoint" of widget.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- cc.UIWidget.prototype.setAnchorPoint.call(this, pt);
- this._labelBMFontRenderer.setAnchorPoint(pt);
- },
-
- onSizeChanged: function () {
- this.labelBMFontScaleChangedWithSize();
- },
-
- /**
- * get content size
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._labelBMFontRenderer.getContentSize();
- },
-
- /**
- * override "getVirtualRenderer" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._labelBMFontRenderer;
- },
-
- labelBMFontScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._labelBMFontRenderer.setScale(1.0);
- this._size = this._labelBMFontRenderer.getContentSize();
- }
- else {
- var textureSize = this._labelBMFontRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._labelBMFontRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._labelBMFontRenderer.setScaleX(scaleX);
- this._labelBMFontRenderer.setScaleY(scaleY);
- }
- },
-
- getDescription: function () {
- return "LabelBMFont";
- }
-});
-
-cc.UILabelBMFont.create = function () {
- var uiLabelBMFont = new cc.UILabelBMFont();
- if (uiLabelBMFont && uiLabelBMFont.init()) {
- return uiLabelBMFont;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UILoadingBar.js b/extensions/CocoStudio/GUI/UIWidgets/UILoadingBar.js
deleted file mode 100644
index 167c3af9ce..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UILoadingBar.js
+++ /dev/null
@@ -1,326 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.LoadingBarType = { Left: 0, Right: 1};
-
-/**
- * Base class for cc.UILoadingBar
- * @class
- * @extends cc.UIWidget
- */
-cc.UILoadingBar = cc.UIWidget.extend({
- _barType: null,
- _percent: 100,
- _totalLength: 0,
- _barRenderer: null,
- _renderBarTexType: null,
- _barRendererTextureSize: null,
- _scale9Enabled: false,
- _prevIgnoreSize: true,
- _capInsets: null,
- _textureFile: "",
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._barType = cc.LoadingBarType.Left;
- this._percent = 100;
- this._totalLength = 0;
- this._barRenderer = null;
- this._renderBarTexType = cc.TextureResType.LOCAL;
- this._barRendererTextureSize = cc.size(0, 0);
- this._scale9Enabled = false;
- this._prevIgnoreSize = true;
- this._capInsets = cc.rect(0, 0, 0, 0);
- this._textureFile = "";
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._barRenderer = cc.Sprite.create();
- this._renderer.addChild(this._barRenderer);
- this._barRenderer.setAnchorPoint(cc.p(0.0, 0.5));
- },
-
- /**
- * Changes the progress direction of loadingbar.
- * LoadingBarTypeLeft means progress left to right, LoadingBarTypeRight otherwise.
- * @param {cc.LoadingBarType} dir
- */
- setDirection: function (dir) {
- if (this._barType == dir) {
- return;
- }
- this._barType = dir;
-
- switch (this._barType) {
- case cc.LoadingBarType.Left:
- this._barRenderer.setAnchorPoint(cc.p(0.0, 0.5));
- this._barRenderer.setPosition(cc.p(-this._totalLength * 0.5, 0.0));
- if (!this._scale9Enabled) {
- this._barRenderer.setFlippedX(false);
- }
- break;
- case cc.LoadingBarType.Right:
- this._barRenderer.setAnchorPoint(cc.p(1.0, 0.5));
- this._barRenderer.setPosition(cc.p(this._totalLength * 0.5, 0.0));
- if (!this._scale9Enabled) {
- this._barRenderer.setFlippedX(true);
- }
- break;
- }
- },
-
- /**
- * Gets the progress direction of loadingbar.
- * LoadingBarTypeLeft means progress left to right, LoadingBarTypeRight otherwise.
- * @returns {cc.LoadingBarType}
- */
- getDirection: function () {
- return this._barType;
- },
-
- /**
- * Load texture for loadingbar.
- * @param {String} texture
- * @param {cc.TextureResType} texType
- */
- loadTexture: function (texture, texType) {
- if (!texture) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._renderBarTexType = texType;
- this._textureFile = texture;
- switch (this._renderBarTexType) {
- case cc.TextureResType.LOCAL:
- if (this._scale9Enabled)
- this._barRenderer.initWithFile(texture);
- else
- this._barRenderer.initWithFile(texture);
- break;
- case cc.TextureResType.PLIST:
- if (this._scale9Enabled)
- this._barRenderer.initWithSpriteFrameName(texture);
- else
- this._barRenderer.initWithSpriteFrameName(texture);
- break;
- default:
- break;
- }
- if (this._scale9Enabled) {
- this._barRenderer.setColor(this.getColor());
- this._barRenderer.setOpacity(this.getOpacity());
- }
- else {
- this._barRenderer.setColor(this.getColor());
- this._barRenderer.setOpacity(this.getOpacity());
- }
- this._barRendererTextureSize.width = this._barRenderer.getContentSize().width;
- this._barRendererTextureSize.height = this._barRenderer.getContentSize().height;
-
- switch (this._barType) {
- case cc.LoadingBarType.Left:
- this._barRenderer.setAnchorPoint(cc.p(0.0, 0.5));
- if (!this._scale9Enabled) {
- this._barRenderer.setFlippedX(false);
- }
- break;
- case cc.LoadingBarType.Right:
- this._barRenderer.setAnchorPoint(cc.p(1.0, 0.5));
- if (!this._scale9Enabled) {
- this._barRenderer.setFlippedX(true);
- }
- break;
- }
- this.barRendererScaleChangedWithSize();
- },
-
- /**
- * Sets if loadingbar is using scale9 renderer.
- * @param {Boolean} enabled
- */
- setScale9Enabled: function (enabled) {
- if (this._scale9Enabled == enabled) {
- return;
- }
- this._scale9Enabled = enabled;
- this._renderer.removeChild(this._barRenderer, true);
- this._barRenderer = null;
- if (this._scale9Enabled) {
- this._barRenderer = cc.Scale9Sprite.create();
- }
- else {
- this._barRenderer = cc.Sprite.create();
- }
- this.loadTexture(this._textureFile, this._renderBarTexType);
- this._renderer.addChild(this._barRenderer);
- if (this._scale9Enabled) {
- var ignoreBefore = this._ignoreSize;
- this.ignoreContentAdaptWithSize(false);
- this._prevIgnoreSize = ignoreBefore;
- }
- else {
- this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
- }
- this.setCapInsets(this._capInsets);
- },
-
- /**
- * Sets capinsets for loadingbar, if loadingbar is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsets: function (capInsets) {
- this._capInsets = capInsets;
- if (!this._scale9Enabled) {
- return;
- }
- this._barRenderer.setCapInsets(capInsets);
- },
-
- /**
- * Changes the progress direction of loadingbar.
- * @param {number} percent
- */
- setPercent: function (percent) {
- if (percent < 0 || percent > 100) {
- return;
- }
- if (this._totalLength <= 0) {
- return;
- }
- this._percent = percent;
- var res = this._percent / 100.0;
-
- var x = 0, y = 0;
- switch (this._renderBarTexType) {
- case cc.TextureResType.PLIST:
- var barNode = this._barRenderer;
- if (barNode) {
- var to = barNode.getTextureRect().origin;
- x = to.x;
- y = to.y;
- }
- break;
- default:
- break;
- }
- if (this._scale9Enabled)
- this.setScale9Scale();
- else
- this._barRenderer.setTextureRect(cc.rect(x, y, this._barRendererTextureSize.width * res, this._barRendererTextureSize.height));
- },
-
- /**
- * Gets the progress direction of loadingbar.
- * @returns {number}
- */
- getPercent: function () {
- return this._percent;
- },
-
- onSizeChanged: function () {
- this.barRendererScaleChangedWithSize();
- },
-
- /**
- * override "ignoreContentAdaptWithSize" method of widget.
- * @param {Boolean}ignore
- */
- ignoreContentAdaptWithSize: function (ignore) {
- if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
- cc.UIWidget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
- this._prevIgnoreSize = ignore;
- }
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._barRendererTextureSize;
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._barRenderer;
- },
-
- barRendererScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- if (!this._scale9Enabled) {
- this._totalLength = this._barRendererTextureSize.width;
- this._barRenderer.setScale(1.0);
- this._size = this._barRendererTextureSize;
- }
- }
- else {
- this._totalLength = this._size.width;
- if (this._scale9Enabled) {
- this.setScale9Scale();
- }
- else {
-
- var textureSize = this._barRenderer.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._barRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._barRenderer.setScaleX(scaleX);
- this._barRenderer.setScaleY(scaleY);
- }
- }
- switch (this._barType) {
- case cc.LoadingBarType.Left:
- this._barRenderer.setPosition(cc.p(-this._totalLength * 0.5, 0.0));
- break;
- case cc.LoadingBarType.Right:
- this._barRenderer.setPosition(cc.p(this._totalLength * 0.5, 0.0));
- break;
- default:
- break;
- }
- },
-
- setScale9Scale: function () {
- var width = (this._percent) / 100 * this._totalLength;
- this._barRenderer.setPreferredSize(cc.size(width, this._barRendererTextureSize.height));
- },
-
- getDescription: function () {
- return "LoadingBar";
- }
-});
-
-cc.UILoadingBar.create = function () {
- var uiLoadingBar = new cc.UILoadingBar();
- if (uiLoadingBar && uiLoadingBar.init()) {
- return uiLoadingBar;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UISlider.js b/extensions/CocoStudio/GUI/UIWidgets/UISlider.js
deleted file mode 100644
index 2ddcc6fba8..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UISlider.js
+++ /dev/null
@@ -1,544 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.SliderEventType = {PERCENTCHANGED: 0};
-
-/**
- * Base class for cc.UISlider
- * @class
- * @extends cc.UIWidget
- */
-cc.UISlider = cc.UIWidget.extend({
- _barRenderer: null,
- _progressBarRenderer: null,
- _progressBarTextureSize: null,
- _slidBallNormalRenderer: null,
- _slidBallPressedRenderer: null,
- _slidBallDisabledRenderer: null,
- _slidBallRenderer: null,
- _barLength: 0,
- _percent: 0,
- _scale9Enabled: false,
- _prevIgnoreSize: true,
- _textureFile: "",
- _progressBarTextureFile: "",
- _slidBallNormalTextureFile: "",
- _slidBallPressedTextureFile: "",
- _slidBallDisabledTextureFile: "",
- _capInsetsBarRenderer: null,
- _capInsetsProgressBarRenderer: null,
- _slidPercentListener: null,
- _slidPercentSelector: null,
- _barTexType: null,
- _progressBarTexType: null,
- _ballNTexType: null,
- _ballPTexType: null,
- _ballDTexType: null,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._barRenderer = null;
- this._progressBarRenderer = null;
- this._progressBarTextureSize = cc.size(0, 0);
- this._slidBallNormalRenderer = null;
- this._slidBallPressedRenderer = null;
- this._slidBallDisabledRenderer = null;
- this._slidBallRenderer = null;
- this._barLength = 0;
- this._percent = 0;
- this._scale9Enabled = false;
- this._prevIgnoreSize = true;
- this._textureFile = "";
- this._progressBarTextureFile = "";
- this._slidBallNormalTextureFile = "";
- this._slidBallPressedTextureFile = "";
- this._slidBallDisabledTextureFile = "";
- this._capInsetsBarRenderer = cc.RectZero();
- this._capInsetsProgressBarRenderer = cc.RectZero();
- this._slidPercentListener = null;
- this._slidPercentSelector = null;
- this._barTexType = cc.TextureResType.LOCAL;
- this._progressBarTexType = cc.TextureResType.LOCAL;
- this._ballNTexType = cc.TextureResType.LOCAL;
- this._ballPTexType = cc.TextureResType.LOCAL;
- this._ballDTexType = cc.TextureResType.LOCAL;
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._barRenderer = cc.Sprite.create();
- this._progressBarRenderer = cc.Sprite.create();
- this._progressBarRenderer.setAnchorPoint(cc.p(0.0, 0.5));
- this._renderer.addChild(this._barRenderer, -1);
- this._renderer.addChild(this._progressBarRenderer, -1);
- this._slidBallNormalRenderer = cc.Sprite.create();
- this._slidBallPressedRenderer = cc.Sprite.create();
- this._slidBallPressedRenderer.setVisible(false);
- this._slidBallDisabledRenderer = cc.Sprite.create();
- this._slidBallDisabledRenderer.setVisible(false);
- this._slidBallRenderer = cc.Node.create();
- this._slidBallRenderer.addChild(this._slidBallNormalRenderer);
- this._slidBallRenderer.addChild(this._slidBallPressedRenderer);
- this._slidBallRenderer.addChild(this._slidBallDisabledRenderer);
- this._renderer.addChild(this._slidBallRenderer);
- },
-
- /**
- * Load texture for slider bar.
- * @param {String} fileName
- * @param {cc.TextureResType} texType
- */
- loadBarTexture: function (fileName, texType) {
- if (!fileName) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._textureFile = fileName;
- this._barTexType = texType;
- switch (this._barTexType) {
- case cc.TextureResType.LOCAL:
- this._barRenderer.initWithFile(fileName);
- break;
- case cc.TextureResType.PLIST:
- this._barRenderer.initWithSpriteFrameName(fileName);
- break;
- default:
- break;
- }
- if (this._scale9Enabled) {
- this._barRenderer.setColor(this.getColor());
- this._barRenderer.setOpacity(this.getOpacity());
- }
- else {
- this._barRenderer.setColor(this.getColor());
- this._barRenderer.setOpacity(this.getOpacity());
- }
- this.barRendererScaleChangedWithSize();
- },
-
- /**
- * Load dark state texture for slider progress bar.
- * @param {String} fileName
- * @param {cc.TextureResType} texType
- */
- loadProgressBarTexture: function (fileName, texType) {
- if (!fileName) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._progressBarTextureFile = fileName;
- this._progressBarTexType = texType;
- switch (this._progressBarTexType) {
- case cc.TextureResType.LOCAL:
- this._progressBarRenderer.initWithFile(fileName);
- break;
- case cc.TextureResType.PLIST:
- this._progressBarRenderer.initWithSpriteFrameName(fileName);
- break;
- default:
- break;
- }
- if (this._scale9Enabled) {
- this._progressBarRenderer.setColor(this.getColor());
- this._progressBarRenderer.setOpacity(this.getOpacity());
- }
- else {
- this._progressBarRenderer.setColor(this.getColor());
- this._progressBarRenderer.setOpacity(this.getOpacity());
- }
- this._progressBarRenderer.setAnchorPoint(cc.p(0.0, 0.5));
- this._progressBarTextureSize = this._progressBarRenderer.getContentSize();
- this.progressBarRendererScaleChangedWithSize();
- },
-
- /**
- * Sets if slider is using scale9 renderer.
- * @param {Boolean} able
- */
- setScale9Enabled: function (able) {
- if (this._scale9Enabled == able) {
- return;
- }
-
- this._scale9Enabled = able;
- this._renderer.removeChild(this._barRenderer, true);
- this._renderer.removeChild(this._progressBarRenderer, true);
- this._barRenderer = null;
- this._progressBarRenderer = null;
- if (this._scale9Enabled) {
- this._barRenderer = cc.Scale9Sprite.create();
- this._progressBarRenderer = cc.Scale9Sprite.create();
- }
- else {
- this._barRenderer = cc.Sprite.create();
- this._progressBarRenderer = cc.Sprite.create();
- }
- this.loadBarTexture(this._textureFile, this._barTexType);
- this.loadProgressBarTexture(this._progressBarTextureFile, this._progressBarTexType);
- this._renderer.addChild(this._barRenderer, -1);
- this._renderer.addChild(this._progressBarRenderer, -1);
- if (this._scale9Enabled) {
- var ignoreBefore = this._ignoreSize;
- this.ignoreContentAdaptWithSize(false);
- this._prevIgnoreSize = ignoreBefore;
- }
- else {
- this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
- }
- this.setCapInsetsBarRenderer(this._capInsetsBarRenderer);
- this.setCapInsetProgressBarRebderer(this._capInsetsProgressBarRenderer);
- },
-
- /**
- * override "ignoreContentAdaptWithSize" method of widget.
- * @param {Boolean} ignore
- */
- ignoreContentAdaptWithSize: function (ignore) {
- if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
- cc.UIWidget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
- this._prevIgnoreSize = ignore;
- }
- },
-
- /**
- * Sets capinsets for slider, if slider is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsets: function (capInsets) {
- this.setCapInsetsBarRenderer(capInsets);
- this.setCapInsetProgressBarRebderer(capInsets);
- },
-
- /**
- * Sets capinsets for slider, if slider is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsetsBarRenderer: function (capInsets) {
- this._capInsetsBarRenderer = capInsets;
- if (!this._scale9Enabled) {
- return;
- }
- this._barRenderer.setCapInsets(capInsets);
- },
-
- /**
- * Sets capinsets for slider, if slider is using scale9 renderer.
- * @param {cc.Rect} capInsets
- */
- setCapInsetProgressBarRebderer: function (capInsets) {
- this._capInsetsProgressBarRenderer = capInsets;
- if (!this._scale9Enabled) {
- return;
- }
- this._progressBarRenderer.setCapInsets(capInsets);
- },
-
- /**
- * Load textures for slider ball.
- * @param {String} normal
- * @param {String} pressed
- * @param {String} disabled
- * @param {cc.TextureResType} texType
- */
- loadSlidBallTextures: function (normal, pressed, disabled, texType) {
- this.loadSlidBallTextureNormal(normal, texType);
- this.loadSlidBallTexturePressed(pressed, texType);
- this.loadSlidBallTextureDisabled(disabled, texType);
- },
-
- /**
- * Load normal state texture for slider ball.
- * @param {String} normal
- * @param {cc.TextureResType} texType
- */
- loadSlidBallTextureNormal: function (normal, texType) {
- if (!normal) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._slidBallNormalTextureFile = normal;
- this._ballNTexType = texType;
- switch (this._ballNTexType) {
- case cc.TextureResType.LOCAL:
- this._slidBallNormalRenderer.initWithFile(normal);
- break;
- case cc.TextureResType.PLIST:
- this._slidBallNormalRenderer.initWithSpriteFrameName(normal);
- break;
- default:
- break;
- }
- this._slidBallNormalRenderer.setColor(this.getColor());
- this._slidBallNormalRenderer.setOpacity(this.getOpacity());
- },
-
- /**
- * Load selected state texture for slider ball.
- * @param {String} pressed
- * @param {cc.TextureResType} texType
- */
- loadSlidBallTexturePressed: function (pressed, texType) {
- if (!pressed) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._slidBallPressedTextureFile = pressed;
- this._ballPTexType = texType;
- switch (this._ballPTexType) {
- case cc.TextureResType.LOCAL:
- this._slidBallPressedRenderer.initWithFile(pressed);
- break;
- case cc.TextureResType.PLIST:
- this._slidBallPressedRenderer.initWithSpriteFrameName(pressed);
- break;
- default:
- break;
- }
- this._slidBallPressedRenderer.setColor(this.getColor());
- this._slidBallPressedRenderer.setOpacity(this.getOpacity());
- },
-
- /**
- * Load dark state texture for slider ball.
- * @param {String} disabled
- * @param {cc.TextureResType} texType
- */
- loadSlidBallTextureDisabled: function (disabled, texType) {
- if (!disabled) {
- return;
- }
- texType = texType || cc.TextureResType.LOCAL;
- this._slidBallDisabledTextureFile = disabled;
- this._ballDTexType = texType;
- switch (this._ballDTexType) {
- case cc.TextureResType.LOCAL:
- this._slidBallDisabledRenderer.initWithFile(disabled);
- break;
- case cc.TextureResType.PLIST:
- this._slidBallDisabledRenderer.initWithSpriteFrameName(disabled);
- break;
- default:
- break;
- }
- this._slidBallDisabledRenderer.setColor(this.getColor());
- this._slidBallDisabledRenderer.setOpacity(this.getOpacity());
- },
-
- /**
- * Changes the progress direction of slider.
- * @param {number} percent
- */
- setPercent: function (percent) {
- if (percent > 100) {
- percent = 100;
- }
- if (percent < 0) {
- percent = 0;
- }
- this._percent = percent;
- var dis = this._barLength * (percent / 100.0);
- this._slidBallRenderer.setPosition(cc.p(-this._barLength / 2.0 + dis, 0.0));
- if (this._scale9Enabled) {
- this._progressBarRenderer.setPreferredSize(cc.size(dis, this._progressBarTextureSize.height));
- }
- else {
- var x = 0, y = 0;
- switch (this._progressBarTexType) {
- case cc.TextureResType.PLIST:
- var barNode = this._progressBarRenderer;
- if (barNode) {
- var to = barNode.getTextureRect().origin;
- x = to.x;
- y = to.y;
- }
- break;
- default:
- break;
- }
- this._progressBarRenderer.setTextureRect(cc.rect(x, y, this._progressBarTextureSize.width * (percent / 100.0), this._progressBarTextureSize.height));
- }
- },
-
- onTouchBegan: function (touchPoint) {
- var pass = cc.UIWidget.prototype.onTouchBegan.call(this,touchPoint);
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- this.setPercent(this.getPercentWithBallPos(nsp.x));
- this.percentChangedEvent();
- return pass;
- },
-
- onTouchMoved: function (touchPoint) {
- var nsp = this._renderer.convertToNodeSpace(touchPoint);
- this._slidBallRenderer.setPosition(cc.p(nsp.x, 0));
- this.setPercent(this.getPercentWithBallPos(nsp.x));
- this.percentChangedEvent();
- },
-
- onTouchEnded: function (touchPoint) {
- cc.UIWidget.prototype.onTouchEnded.call(this, touchPoint);
- },
-
- onTouchCancelled: function (touchPoint) {
- cc.UIWidget.prototype.onTouchCancelled.call(this, touchPoint);
- },
-
- /**
- * get percent with ballPos
- * @param {cc.Point} px
- * @returns {number}
- */
- getPercentWithBallPos: function (px) {
- return (((px - (-this._barLength / 2.0)) / this._barLength) * 100.0);
- },
-
- /**
- * add event listener
- * @param {Object} target
- * @param {Function} selector
- */
- addEventListener: function (target, selector) {
- this._slidPercentListener = target;
- this._slidPercentSelector = selector;
- },
-
- percentChangedEvent: function () {
- if (this._slidPercentListener && this._slidPercentSelector) {
- this._slidPercentSelector.call(this._slidPercentListener, this, cc.SliderEventType.PERCENTCHANGED);
- }
- },
-
- /**
- * Gets the progress direction of slider.
- * @returns {number}
- */
- getPercent: function () {
- return this._percent;
- },
-
- onSizeChanged: function () {
- this.barRendererScaleChangedWithSize();
- this.progressBarRendererScaleChangedWithSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._barRenderer.getContentSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._barRenderer;
- },
-
- barRendererScaleChangedWithSize: function () {
- if (this._ignoreSize) {
-
- this._barRenderer.setScale(1.0);
- this._size = this._barRenderer.getContentSize();
- this._barLength = this._size.width;
- }
- else {
- this._barLength = this._size.width;
- if (this._scale9Enabled) {
- this._barRenderer.setPreferredSize(this._size);
- }
- else {
- var btextureSize = this._barRenderer.getContentSize();
- if (btextureSize.width <= 0.0 || btextureSize.height <= 0.0) {
- this._barRenderer.setScale(1.0);
- return;
- }
- var bscaleX = this._size.width / btextureSize.width;
- var bscaleY = this._size.height / btextureSize.height;
- this._barRenderer.setScaleX(bscaleX);
- this._barRenderer.setScaleY(bscaleY);
- }
- }
- this.setPercent(this._percent);
- },
-
- progressBarRendererScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- if (!this._scale9Enabled) {
- var ptextureSize = this._progressBarTextureSize;
- var pscaleX = this._size.width / ptextureSize.width;
- var pscaleY = this._size.height / ptextureSize.height;
- this._progressBarRenderer.setScaleX(pscaleX);
- this._progressBarRenderer.setScaleY(pscaleY);
- }
- }
- else {
- if (this._scale9Enabled) {
- this._progressBarRenderer.setPreferredSize(this._size);
- }
- else {
- var ptextureSize = this._progressBarTextureSize;
- if (ptextureSize.width <= 0.0 || ptextureSize.height <= 0.0) {
- this._progressBarRenderer.setScale(1.0);
- return;
- }
- var pscaleX = this._size.width / ptextureSize.width;
- var pscaleY = this._size.height / ptextureSize.height;
- this._progressBarRenderer.setScaleX(pscaleX);
- this._progressBarRenderer.setScaleY(pscaleY);
- }
- }
- this._progressBarRenderer.setPosition(cc.p(-this._barLength * 0.5, 0.0));
- this.setPercent(this._percent);
- },
-
- onPressStateChangedToNormal: function () {
- this._slidBallNormalRenderer.setVisible(true);
- this._slidBallPressedRenderer.setVisible(false);
- this._slidBallDisabledRenderer.setVisible(false);
- },
-
- onPressStateChangedToPressed: function () {
- this._slidBallNormalRenderer.setVisible(false);
- this._slidBallPressedRenderer.setVisible(true);
- this._slidBallDisabledRenderer.setVisible(false);
- },
-
- onPressStateChangedToDisabled: function () {
- this._slidBallNormalRenderer.setVisible(false);
- this._slidBallPressedRenderer.setVisible(false);
- this._slidBallDisabledRenderer.setVisible(true);
- },
-
- getDescription: function () {
- return "Slider";
- }
-});
-cc.UISlider.create = function () {
- var uiSlider = new cc.UISlider();
- if (uiSlider && uiSlider.init()) {
- return uiSlider;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/GUI/UIWidgets/UITextField.js b/extensions/CocoStudio/GUI/UIWidgets/UITextField.js
deleted file mode 100644
index cca37bc444..0000000000
--- a/extensions/CocoStudio/GUI/UIWidgets/UITextField.js
+++ /dev/null
@@ -1,584 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-cc.TextFiledEventType = {
- ATTACH_WITH_IME: 0,
- DETACH_WITH_IME: 1,
- INDERT_TEXT: 2,
- DELETE_BACKWARD: 3
-};
-
-/**
- * Base class for cc.UISlider
- * @class
- * @extends cc.UIWidget
- */
-cc.UICCTextField = cc.TextFieldTTF.extend({
- _maxLengthEnabled: false,
- _maxLength: 0,
- _passwordEnabled: false,
- _passwordStyleText: "",
- _attachWithIME: false,
- _detachWithIME: false,
- _insertText: false,
- _deleteBackward: false,
- ctor: function () {
- cc.TextFieldTTF.prototype.ctor.call(this);
- this._maxLengthEnabled = false;
- this._maxLength = 0;
- this._passwordEnabled = false;
- this._passwordStyleText = "*";
- this._attachWithIME = false;
- this._detachWithIME = false;
- this._insertText = false;
- this._deleteBackward = false;
- },
- onEnter: function () {
- cc.TextFieldTTF.prototype.onEnter.call(this);
- cc.TextFieldTTF.prototype.setDelegate.call(this,this);
- },
-
- //CCTextFieldDelegate
-
- onTextFieldAttachWithIME: function (sender) {
- this.setAttachWithIME(true);
- return false;
- },
-
- onTextFieldInsertText: function (sender, text, len) {
- if (len == 1 && text == "\n") {
- return false;
- }
- this.setInsertText(true);
- if (this._maxLengthEnabled) {
- if (cc.TextFieldTTF.prototype.getCharCount.call(this) >= this._maxLength) {
- return true;
- }
- }
-
- return false;
- },
-
- onTextFieldDeleteBackward: function (sender, delText, nLen) {
- this.setDeleteBackward(true);
- return false;
- },
-
- onTextFieldDetachWithIME: function (sender) {
- this.setDetachWithIME(true);
- return false;
- },
-
- insertText: function (text, len) {
- var str_text = text;
- var locString = cc.TextFieldTTF.prototype.getString.call(this);
- var str_len = locString.length;
- var multiple, header;
- if (text != "\n") {
- if (this._maxLengthEnabled) {
- multiple = 1;
- header = text.charCodeAt(0);
- if (header < 0 || header > 127) {
- multiple = 3;
- }
-
- if (str_len + len > this._maxLength * multiple) {
- str_text = str_text.substr(0, this._maxLength * multiple);
- len = this._maxLength * multiple;
- }
- }
- }
- cc.TextFieldTTF.prototype.insertText.call(this,str_text, len);
-
- // password
- if (this._passwordEnabled) {
- if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0) {
- this.setPasswordText(this._inputText);
- }
- }
- },
-
- deleteBackward: function () {
- cc.TextFieldTTF.prototype.deleteBackward.call(this);
-
- if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0) {
- // password
- if (this._passwordEnabled) {
- this.setPasswordText(this._inputText);
- }
- }
- },
-
- openIME: function () {
- cc.TextFieldTTF.prototype.attachWithIME.call(this);
- },
-
- closeIME: function () {
- cc.TextFieldTTF.prototype.detachWithIME.call(this);
- },
- onDraw:function (sender) {
- return false;
- },
- setMaxLengthEnabled: function (enable) {
- this._maxLengthEnabled = enable;
- },
-
- isMaxLengthEnabled: function () {
- return this._maxLengthEnabled;
- },
-
- setMaxLength: function (length) {
- this._maxLength = length;
- },
-
- getMaxLength: function () {
- return this._maxLength;
- },
-
- getCharCount: function () {
- return cc.TextFieldTTF.prototype.getCharCount.call(this);
- },
-
- setPasswordEnabled: function (enable) {
- this._passwordEnabled = enable;
- },
-
- isPasswordEnabled: function () {
- return this._passwordEnabled;
- },
-
- setPasswordStyleText: function (styleText) {
- if (styleText.length > 1) {
- return;
- }
- var header = styleText.charCodeAt(0);
- if (header < 33 || header > 126) {
- return;
- }
- this._passwordStyleText = styleText;
- },
-
- setPasswordText: function (text) {
- var tempStr = "";
- for (var i = 0; i < text.length; ++i) {
- tempStr += this._passwordStyleText;
- }
- cc.LabelTTF.prototype.setString.call(this, tempStr);
- },
-
- setAttachWithIME: function (attach) {
- this._attachWithIME = attach;
- },
-
- getAttachWithIME: function () {
- return this._attachWithIME;
- },
-
- setDetachWithIME: function (detach) {
- this._detachWithIME = detach;
- },
-
- getDetachWithIME: function () {
- return this._detachWithIME;
- },
-
- setInsertText: function (insert) {
- this._insertText = insert;
- },
-
- getInsertText: function () {
- return this._insertText;
- },
-
- setDeleteBackward: function (deleteBackward) {
- this._deleteBackward = deleteBackward;
- },
-
- getDeleteBackward: function () {
- return this._deleteBackward;
- }
-});
-
-cc.UICCTextField.create = function (placeholder, fontName, fontSize) {
- var ret = new cc.UICCTextField();
- if (ret && ret.initWithString("", fontName, fontSize)) {
- if (placeholder) {
- ret.setPlaceHolder(placeholder);
- }
- return ret;
- }
- return null;
-};
-
-/**
- * Base class for cc.UITextField
- * @class
- * @extends cc.UIWidget
- */
-cc.UITextField = cc.UIWidget.extend({
- _textFieldRenderer: null,
- _touchWidth: 0,
- _touchHeight: 0,
- _useTouchArea: false,
- _eventListener: null,
- _eventSelector: null,
- _attachWithIMEListener: null,
- _detachWithIMEListener: null,
- _insertTextListener: null,
- _deleteBackwardListener: null,
- _attachWithIMESelector: null,
- _detachWithIMESelector: null,
- _insertTextSelector: null,
- _deleteBackwardSelector: null,
- ctor: function () {
- cc.UIWidget.prototype.ctor.call(this);
- this._textFieldRenderer = null;
- this._touchWidth = 0;
- this._touchHeight = 0;
- this._useTouchArea = false;
-
- this._eventListener = null;
- this._eventSelector = null;
- this._attachWithIMEListener = null;
- this._detachWithIMEListener = null;
- this._insertTextListener = null;
- this._deleteBackwardListener = null;
- this._attachWithIMESelector = null;
- this._detachWithIMESelector = null;
- this._insertTextSelector = null;
- this._deleteBackwardSelector = null;
- },
-
- init: function () {
- if (cc.UIWidget.prototype.init.call(this)) {
- this.setUpdateEnabled(true);
- return true;
- }
- return false;
- },
-
- initRenderer: function () {
- cc.UIWidget.prototype.initRenderer.call(this);
- this._textFieldRenderer = cc.UICCTextField.create("input words here", "Thonburi", 20);
- this._renderer.addChild(this._textFieldRenderer);
-
- },
-
- /**
- * set touch size
- * @param {cc.Size} size
- */
- setTouchSize: function (size) {
- this._useTouchArea = true;
- this._touchWidth = size.width;
- this._touchHeight = size.height;
- },
-
- /**
- * Changes the string value of textField.
- * @param {String} text
- */
- setText: function (text) {
- if (!text) {
- return;
- }
- this._textFieldRenderer.setString(text);
- this.textfieldRendererScaleChangedWithSize();
- },
-
- /**
- * @param {String} value
- */
- setPlaceHolder: function (value) {
- this._textFieldRenderer.setPlaceHolder(value);
- this.textfieldRendererScaleChangedWithSize();
- },
-
- /**
- * @param {cc.Size} size
- */
- setFontSize: function (size) {
- this._textFieldRenderer.setFontSize(size);
- this.textfieldRendererScaleChangedWithSize();
- },
-
- /**
- * @param {String} name
- */
- setFontName: function (name) {
- this._textFieldRenderer.setFontName(name);
- this.textfieldRendererScaleChangedWithSize();
- },
-
- didNotSelectSelf: function () {
- this._textFieldRenderer.detachWithIME();
- },
-
- getStringValue: function () {
- return this._textFieldRenderer.getString();
- },
-
- onTouchBegan: function (touchPoint) {
- var pass = cc.UIWidget.prototype.onTouchBegan.call(this, touchPoint);
- return pass;
- },
-
- onTouchEnded: function (touchPoint) {
- cc.UIWidget.prototype.onTouchEnded.call(this, touchPoint);
- this._textFieldRenderer.attachWithIME();
- },
-
- /**
- * @param {Boolean} enable
- */
- setMaxLengthEnabled: function (enable) {
- this._textFieldRenderer.setMaxLengthEnabled(enable);
- },
-
- /**
- * @returns {Boolean}
- */
- isMaxLengthEnabled: function () {
- return this._textFieldRenderer.isMaxLengthEnabled();
- },
-
- /**
- * @param {number} length
- */
- setMaxLength: function (length) {
- this._textFieldRenderer.setMaxLength(length);
- },
-
- /**
- * @returns {number} length
- */
- getMaxLength: function () {
- return this._textFieldRenderer.getMaxLength();
- },
-
- /**
- * @param {Boolean} enable
- */
- setPasswordEnabled: function (enable) {
- this._textFieldRenderer.setPasswordEnabled(enable);
- },
-
- /**
- * @returns {Boolean}
- */
- isPasswordEnabled: function () {
- return this._textFieldRenderer.isPasswordEnabled();
- },
-
- /**
- * @param {String} enable
- */
- setPasswordStyleText: function (styleText) {
- this._textFieldRenderer.setPasswordStyleText(styleText);
- },
-
- update: function (dt) {
- if (this.getAttachWithIME()) {
- this.attachWithIMEEvent();
- this.setAttachWithIME(false);
- }
- if (this.getDetachWithIME()) {
- this.detachWithIMEEvent();
- this.setDetachWithIME(false);
- }
- if (this.getInsertText()) {
- this.insertTextEvent();
- this.setInsertText(false);
-
- this.textfieldRendererScaleChangedWithSize();
- }
- if (this.getDeleteBackward()) {
- this.deleteBackwardEvent();
- this.setDeleteBackward(false);
- }
- },
-
- getAttachWithIME: function () {
- return this._textFieldRenderer.getAttachWithIME();
- },
-
- setAttachWithIME: function (attach) {
- this._textFieldRenderer.setAttachWithIME(attach);
- },
-
- getDetachWithIME: function () {
- return this._textFieldRenderer.getDetachWithIME();
- },
-
- setDetachWithIME: function (detach) {
- this._textFieldRenderer.setDetachWithIME(detach);
- },
-
- /**
- * get insertText
- * @returns {String}
- */
- getInsertText: function () {
- return this._textFieldRenderer.getInsertText();
- },
-
- /**
- * set insertText
- * @param {String} insertText
- */
- setInsertText: function (insertText) {
- this._textFieldRenderer.setInsertText(insertText);
- },
-
- /**
- * @returns {Boolean}
- */
- getDeleteBackward: function () {
- return this._textFieldRenderer.getDeleteBackward();
- },
-
- /**
- * @param {Boolean} deleteBackward
- */
- setDeleteBackward: function (deleteBackward) {
- this._textFieldRenderer.setDeleteBackward(deleteBackward);
- },
-
- attachWithIMEEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.TextFiledEventType.ATTACH_WITH_IME);
- }
- },
-
- detachWithIMEEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.TextFiledEventType.DETACH_WITH_IME);
- }
- },
-
- insertTextEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.TextFiledEventType.INDERT_TEXT);
- }
- },
-
- deleteBackwardEvent: function () {
- if (this._eventListener && this._eventSelector) {
- this._eventSelector.call(this._eventListener, this, cc.TextFiledEventType.DELETE_BACKWARD);
- }
- },
-
- /**
- * add event listener
- * @param {Object} target
- * @param {Function} selector
- */
- addEventListener: function (target, selector) {
- this._eventListener = target;
- this._eventSelector = selector;
- },
-
- hitTest: function (pt) {
- var nsp = this._renderer.convertToNodeSpace(pt);
- var locSize = this._textFieldRenderer.getContentSize();
- var bb = cc.rect(-locSize.width * this._anchorPoint.x, -locSize.height * this._anchorPoint.y, locSize.width, locSize.height);
- if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) {
- return true;
- }
- return false;
- },
-
- /**
- * override "setAnchorPoint" of widget.
- * @param {cc.Point} pt
- */
- setAnchorPoint: function (pt) {
- cc.UIWidget.prototype.setAnchorPoint.call(this, pt);
- this._textFieldRenderer.setAnchorPoint(pt);
- },
-
- /**
- * @param {cc.c3b} color
- */
- setColor: function (color) {
- cc.UIWidget.prototype.setColor.call(this, color);
- this._textFieldRenderer.setColor(color);
- },
-
- /**
- * @param {number} opacity
- */
- setOpacity: function (opacity) {
- cc.UIWidget.prototype.setOpacity.call(this, opacity);
- this._textFieldRenderer.setOpacity(opacity);
- },
-
- onSizeChanged: function () {
- this.textfieldRendererScaleChangedWithSize();
- },
-
- textfieldRendererScaleChangedWithSize: function () {
- if (this._ignoreSize) {
- this._textFieldRenderer.setScale(1.0);
- this._size = this.getContentSize();
- }
- else {
- var textureSize = this.getContentSize();
- if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
- this._textFieldRenderer.setScale(1.0);
- return;
- }
- var scaleX = this._size.width / textureSize.width;
- var scaleY = this._size.height / textureSize.height;
- this._textFieldRenderer.setScaleX(scaleX);
- this._textFieldRenderer.setScaleY(scaleY);
- }
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Size}
- */
- getContentSize: function () {
- return this._textFieldRenderer.getContentSize();
- },
-
- /**
- * override "getContentSize" method of widget.
- * @returns {cc.Node}
- */
- getVirtualRenderer: function () {
- return this._textFieldRenderer;
- },
-
- getDescription: function () {
- return "TextField";
- }
-});
-cc.UITextField.create = function () {
- var uiTextField = new cc.UITextField();
- if (uiTextField && uiTextField.init()) {
- return uiTextField;
- }
- return null;
-};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Reader/CCSGUIReader.js b/extensions/CocoStudio/Reader/CCSGUIReader.js
deleted file mode 100644
index 08437911f4..0000000000
--- a/extensions/CocoStudio/Reader/CCSGUIReader.js
+++ /dev/null
@@ -1,1299 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-var kCCSVersion = 1.0;
-cc.CCSGUIReader = cc.Class.extend({
- _filePath: "",
- _olderVersion: false,
- ctor: function () {
- this._filePath = "";
- this._olderVersion = false;
- },
-
- purgeCCSGUIReader: function () {
- this._instance = null;
- },
-
- getVersionInteger: function (str) {
- /*********temp***********/
- var strVersion = str;
- var length = strVersion.length;
- if (length < 7) {
- return 0;
- }
- var pos = strVersion.indexOf(".");
- var t = strVersion.substr(0, pos);
- strVersion = strVersion.substr(pos + 1, strVersion.length - 1);
-
- pos = strVersion.indexOf(".");
- var h = strVersion.substr(0, pos);
- strVersion = strVersion.substr(pos + 1, strVersion.length - 1);
-
- pos = strVersion.indexOf(".");
- var te = strVersion.substr(0, pos);
- strVersion = strVersion.substr(pos + 1, strVersion.length - 1);
-
- pos = strVersion.indexOf(".");
- var s;
- if(pos==-1){
- s = strVersion;
- }else{
- s = strVersion.substr(0, pos);
- }
-
- var it = parseInt(t);
- var ih = parseInt(h);
- var ite = parseInt(te);
- var is = parseInt(s);
-
- var version = it * 1000 + ih * 100 + ite * 10 + is;
- return version;
- },
-
- widgetFromJsonDictionary: function (data) {
- var widget = null;
- var classname = data["classname"];
- var uiOptions = data["options"];
- if (classname == "Button") {
- widget = cc.UIButton.create();
- this.setPropsForButtonFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "CheckBox") {
- widget = cc.UICheckBox.create();
- this.setPropsForCheckBoxFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Label") {
- widget = cc.UILabel.create();
- this.setPropsForLabelFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LabelAtlas") {
- widget = cc.UILabelAtlas.create();
- this.setPropsForLabelAtlasFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LoadingBar") {
- widget = cc.UILoadingBar.create();
- this.setPropsForLoadingBarFromJsonDictionary(widget, uiOptions);
- } else if (classname == "ScrollView") {
- widget = cc.UIScrollView.create();
- this.setPropsForScrollViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextArea") {
- widget = cc.UITextArea.create();
- this.setPropsForTextAreaFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextButton") {
- widget = cc.UITextButton.create();
- this.setPropsForTextButtonFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "TextField") {
- widget = cc.UITextField.create();
- this.setPropsForTextFieldFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "ImageView") {
- widget = cc.UIImageView.create();
- this.setPropsForImageViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Panel") {
- widget = cc.UIPanel.create();
- this.setPropsForPanelFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "Slider") {
- widget = cc.UISlider.create();
- this.setPropsForSliderFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "ListView") {
-// widget = UIListView.create();
-// setPropsForListViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "PageView") {
- widget = cc.UIPageView.create();
- this.setPropsForPageViewFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "LabelBMFont") {
- widget = cc.UILabelBMFont.create();
- this.setPropsForLabelBMFontFromJsonDictionary(widget, uiOptions);
- }
- else if (classname == "DragPanel") {
- widget = cc.UIDragPanel.create();
- this.setPropsForDragPanelFromJsonDictionary(widget, uiOptions);
- }
-
- var children = data["children"];
- for (var i = 0; i < children.length; i++) {
- var subData = children[i];
- var child = this.widgetFromJsonDictionary(subData);
- if (child) {
- widget.addChild(child);
- }
- subData = null;
- }
-
- uiOptions = null;
- return widget;
- },
-
-
- widgetFromJsonFile: function (fileName) {
- this._olderVersion = false;
- var des = null;
- var jsonpath = "";
- var jsonDict = null;
- jsonpath = cc.FileUtils.getInstance().fullPathForFilename(fileName);
-
- var size = 0;
- des = cc.FileUtils.getInstance().getTextFileData(jsonpath, "r", size);
- if (!des) {
- cc.log("read json file[" + fileName + "] error!");
- return null;
- }
- var strDes = des;
- jsonDict = JSON.parse(strDes);
-
- var fileVersion = jsonDict["version"];
- if (!fileVersion || this.getVersionInteger(fileVersion) < 250) {
- this._olderVersion = true;
- }
-
- var textures = jsonDict["textures"];
- var pos = jsonpath.lastIndexOf('/');
- this._filePath = jsonpath.substr(0, pos + 1);
- for (var i = 0; i < textures.length; i++) {
- var file = textures[i];
- var tp = this._filePath;
- tp+=file;
- cc.UIHelper.getInstance().addSpriteFrame(tp);
- }
- var fileDesignWidth = jsonDict["designWidth"];
- var fileDesignHeight = jsonDict["designHeight"];
- if (fileDesignWidth <= 0 || fileDesignHeight <= 0) {
- cc.log("Read design size error!");
- var winSize = cc.Director.getInstance().getWinSize();
- cc.UIHelper.getInstance().setFileDesignWidth(winSize.width);
- cc.UIHelper.getInstance().setFileDesignHeight(winSize.height);
- }
- else {
- cc.UIHelper.getInstance().setFileDesignWidth(fileDesignWidth);
- cc.UIHelper.getInstance().setFileDesignHeight(fileDesignHeight);
- }
- var widgetTree = jsonDict["widgetTree"];
- var widget = this.widgetFromJsonDictionary(widgetTree);
-
- var size = widget.getContentSize();
- if (size.width == 0 && size.height == 0) {
- widget.setSize(cc.size(fileDesignWidth, fileDesignHeight));
- }
-
- var actions = jsonDict["animation"];
-
- var rootWidget = widget;
- cc.CCSActionManager.getInstance().initWithDictionary(fileName, actions, rootWidget);
-
- widgetTree = null;
- actions = null;
- jsonDict = null;
- des = null;
- return widget;
- },
-
- setPropsForWidgetFromJsonDictionary: function (widget, options) {
- var ignoreSizeExsit = options["ignoreSize"];
- if (ignoreSizeExsit) {
- widget.ignoreContentAdaptWithSize(options["ignoreSize"]);
- }
-
- var w = options["width"];
- var h = options["height"];
- widget.setSize(cc.size(w, h));
-
- widget.setTag(options["tag"]);
- widget.setActionTag(options["actiontag"]);
- widget.setTouchEnabled(options["touchAble"]);
- var name = options["name"];
- var widgetName = name ? name : "default";
- widget.setName(widgetName);
- var x = options["x"];
- var y = options["y"];
- widget.setPosition(cc.p(x, y));
- var sx = options["scaleX"];
- if (sx) {
- widget.setScaleX(options["scaleX"]);
- }
- var sy = options["scaleY"];
- if (sy) {
- widget.setScaleY(options["scaleY"]);
- }
- var rt = options["rotation"];
- if (rt) {
- widget.setRotation(options["rotation"]);
- }
- var vb = options["visible"];
- if (vb) {
- widget.setVisible(options["visible"]);
- }
-// widget.setUseMergedTexture(options["useMergedTexture"));
- var z = options["ZOrder"];
- widget.setZOrder(z);
- },
-
- setColorPropsForWidgetFromJsonDictionary: function (widget, options) {
- var op = options["opacity"];
- if (op) {
- widget.setOpacity(options["opacity"]);
- }
- var colorR = options["colorR"];
- var colorG = options["colorG"];
- var colorB = options["colorB"];
- colorR = (colorR || colorR == 0) ? options["colorR"] : 255;
- colorG = (colorG || colorG == 0) ? options["colorG"] : 255;
- colorB = (colorB || colorB == 0) ? options["colorB"] : 255;
- widget.setColor(cc.c3b(colorR, colorG, colorB));
- var apx = options["anchorPointX"];
- apx = (apx || apx == 0) ? apx : ((widget.getWidgetType() == cc.WidgetType.Widget) ? 0.5 : 0);
- var apy = options["anchorPointY"];
- apy = (apy || apy == 0) ? apy : ((widget.getWidgetType() == cc.WidgetType.Widget) ? 0.5 : 0);
- widget.setAnchorPoint(cc.p(apx, apy));
- var flipX = options["flipX"];
- var flipY = options["flipY"];
- widget.setFlippedX(flipX);
- widget.setFlippedY(flipY);
- },
-
- setPropsForButtonFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var button = widget;
- var scale9Enable = options["scale9Enable"];
- button.setScale9Enabled(scale9Enable);
-
- var tp_n = this._filePath;
- var tp_p = this._filePath;
- var tp_d = this._filePath;
-
- var normalFileName = options["normal"];
- var pressedFileName = options["pressed"];
- var disabledFileName = options["disabled"];
-
- var normalFileName_tp = normalFileName ? tp_n + normalFileName : null;
- var pressedFileName_tp = pressedFileName ? tp_p + pressedFileName : null;
- var disabledFileName_tp = disabledFileName ? tp_d + disabledFileName : null;
- var useMergedTexture = options["useMergedTexture"];
- if (scale9Enable) {
- var cx = options["capInsetsX"];
- var cy = options["capInsetsY"];
- var cw = options["capInsetsWidth"];
- var ch = options["capInsetsHeight"];
-
- if (useMergedTexture) {
- button.loadTextures(normalFileName, pressedFileName, disabledFileName, cc.TextureResType.PLIST);
- }
- else {
- button.loadTextures(normalFileName_tp, pressedFileName_tp, disabledFileName_tp);
- }
- button.setCapInsets(cc.rect(cx, cy, cw, ch));
- var sw = options["scale9Width"];
- var sh = options["scale9Height"];
- if (sw && sh) {
- var swf = options["scale9Width"];
- var shf = options["scale9Height"];
- button.setSize(cc.size(swf, shf));
- }
- }
- else {
- if (useMergedTexture) {
- button.loadTextures(normalFileName, pressedFileName, disabledFileName, cc.TextureResType.PLIST);
- }
- else {
- button.loadTextures(normalFileName_tp, pressedFileName_tp, disabledFileName_tp);
- }
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var button = widget;
- var scale9Enable = options["scale9Enable"];
- button.setScale9Enabled(scale9Enable);
-
- var normalDic = options["normalData"];
- var normalType = normalDic["resourceType"];
- switch (normalType) {
- case 0:
- var tp_n = this._filePath;
- var normalFileName = normalDic["path"];
- var normalFileName_tp = normalFileName ? tp_n + normalFileName : null;
- button.loadTextureNormal(normalFileName_tp);
- break;
- case 1:
- var normalFileName = normalDic["path"];
- button.loadTextureNormal(normalFileName, cc.TextureResType.PLIST);
- break;
- default:
- break;
- }
- normalDic = null;
- var pressedDic = options["pressedData"];
- var pressedType = pressedDic["resourceType"];
- switch (pressedType) {
- case 0:
- {
- var tp_p = this._filePath;
- var pressedFileName = pressedDic["path"];
- var pressedFileName_tp = pressedFileName ? tp_p + pressedFileName : null;
- button.loadTexturePressed(pressedFileName_tp);
- break;
- }
- case 1:
- {
- var pressedFileName = pressedDic["path"];
- button.loadTexturePressed(pressedFileName, cc.TextureResType.PLIST);
- break;
- }
- default:
- break;
- }
- pressedDic = null;
- var disabledDic = options["disabledData"];
- var disabledType = disabledDic["resourceType"];
- switch (disabledType) {
- case 0:
- var tp_d = this._filePath;
- var disabledFileName = disabledDic["path"];
- var disabledFileName_tp = disabledFileName ? tp_d + disabledFileName : null;
- button.loadTextureDisabled(disabledFileName_tp);
- break;
- case 1:
- var disabledFileName = disabledDic["path"];
- button.loadTextureDisabled(disabledFileName, cc.TextureResType.PLIST);
- break;
- default:
- break;
- }
- disabledDic = null;
- if (scale9Enable) {
- var cx = options["capInsetsX"];
- var cy = options["capInsetsY"];
- var cw = options["capInsetsWidth"];
- var ch = options["capInsetsHeight"];
-
- button.setCapInsets(cc.rect(cx, cy, cw, ch));
- var sw = options["scale9Width"];
- var sh = options["scale9Height"];
- if (sw && sh) {
- var swf = options["scale9Width"];
- var shf = options["scale9Height"];
- button.setSize(cc.size(swf, shf));
- }
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForCheckBoxFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var checkBox = widget;
- var backGroundFileName = options["backGroundBox"];
- var backGroundSelectedFileName = options["backGroundBoxSelected"];
- var frontCrossFileName = options["frontCross"];
- var backGroundDisabledFileName = options["backGroundBoxDisabled"];
- var frontCrossDisabledFileName = options["frontCrossDisabled"];
-
-
- var tp_b = this._filePath;
- var tp_bs = this._filePath;
- var tp_c = this._filePath;
- var tp_bd = this._filePath;
- var tp_cd = this._filePath;
-
- var backGroundFileName_tp = backGroundFileName ? tp_b + backGroundFileName : null;
- var backGroundSelectedFileName_tp = backGroundSelectedFileName ? tp_bs + backGroundSelectedFileName : null;
- var frontCrossFileName_tp = frontCrossFileName ? tp_c + frontCrossFileName : null;
- var backGroundDisabledFileName_tp = backGroundDisabledFileName ? tp_bd + backGroundDisabledFileName : null;
- var frontCrossDisabledFileName_tp = frontCrossDisabledFileName ? tp_cd + frontCrossDisabledFileName : null;
- var useMergedTexture = options["useMergedTexture"];
-
- if (useMergedTexture) {
- checkBox.loadTextures(backGroundFileName, backGroundSelectedFileName, frontCrossFileName, backGroundDisabledFileName, frontCrossDisabledFileName, cc.TextureResType.PLIST);
- }
- else {
- checkBox.loadTextures(backGroundFileName_tp, backGroundSelectedFileName_tp, frontCrossFileName_tp, backGroundDisabledFileName_tp, frontCrossDisabledFileName_tp);
- }
-
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var checkBox = widget;
-
- var backGroundDic = options["backGroundBoxData"];
- var backGroundType = backGroundDic["resourceType"];
- switch (backGroundType) {
- case 0:
- var tp_b = this._filePath;
- var backGroundFileName = backGroundDic["path"];
- var backGroundFileName_tp = backGroundFileName ? tp_b + backGroundFileName : null;
- checkBox.loadTextureBackGround(backGroundFileName_tp);
- break;
- case 1:
- var backGroundFileName = backGroundDic["path"];
- checkBox.loadTextureBackGround(backGroundFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- backGroundDic = null;
-
- var backGroundSelectedDic = options["backGroundBoxSelectedData"];
- var backGroundSelectedType = backGroundSelectedDic["resourceType"];
- switch (backGroundSelectedType) {
- case 0:
- var tp_bs = this._filePath;
- var backGroundSelectedFileName = backGroundSelectedDic["path"];
- var backGroundSelectedFileName_tp = backGroundSelectedFileName ? tp_bs + backGroundSelectedFileName : null;
- checkBox.loadTextureBackGroundSelected(backGroundSelectedFileName_tp);
- break;
- case 1:
- var backGroundSelectedFileName = backGroundSelectedDic["path"];
- checkBox.loadTextureBackGroundSelected(backGroundSelectedFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- backGroundSelectedDic = null;
-
- var frontCrossDic = options["frontCrossData"];
- var frontCrossType = frontCrossDic["resourceType"];
- switch (frontCrossType) {
- case 0:
- var tp_c = this._filePath;
- var frontCrossFileName = frontCrossDic["path"];
- var frontCrossFileName_tp = frontCrossFileName ? tp_c + frontCrossFileName : null;
- checkBox.loadTextureFrontCross(frontCrossFileName_tp);
- break;
- case 1:
- var frontCrossFileName = frontCrossDic["path"];
- checkBox.loadTextureFrontCross(frontCrossFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- frontCrossDic = null;
-
- var backGroundDisabledDic = options["backGroundBoxDisabledData"];
- var backGroundDisabledType = backGroundDisabledDic["resourceType"];
- switch (backGroundDisabledType) {
- case 0:
- var tp_bd = this._filePath;
- var backGroundDisabledFileName = backGroundDisabledDic["path"];
- var backGroundDisabledFileName_tp = backGroundDisabledFileName ? tp_bd + backGroundDisabledFileName : null;
- checkBox.loadTextureBackGroundDisabled(backGroundDisabledFileName_tp);
- break;
- case 1:
- var backGroundDisabledFileName = backGroundDisabledDic["path"];
- checkBox.loadTextureBackGroundDisabled(backGroundDisabledFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- backGroundDisabledDic = null;
-
- var frontCrossDisabledDic = options["frontCrossDisabledData"];
- var frontCrossDisabledType = frontCrossDisabledDic["resourceType"];
- switch (frontCrossDisabledType) {
- case 0:
- var tp_cd = this._filePath;
- var frontCrossDisabledFileName = options["path"];
- var frontCrossDisabledFileName_tp = frontCrossDisabledFileName ? tp_cd + frontCrossDisabledFileName : null;
- checkBox.loadTextureFrontCrossDisabled(frontCrossDisabledFileName_tp);
- break;
- case 1:
- var frontCrossDisabledFileName = options["path"];
- checkBox.loadTextureFrontCrossDisabled(frontCrossDisabledFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- frontCrossDisabledDic = null;
-
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForImageViewFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
-
- var imageView = widget;
- var imageFileName = options["fileName"];
- var scale9EnableExist = options["scale9Enable"];
- var scale9Enable = false;
- if (scale9EnableExist) {
- scale9Enable = options["scale9Enable"];
- }
- imageView.setScale9Enabled(scale9Enable);
-
- var tp_i = this._filePath;
- var imageFileName_tp = null;
- if (imageFileName) {
- imageFileName_tp = tp_i + imageFileName;
- }
-
- var useMergedTexture = options["useMergedTexture"];
- if (scale9Enable) {
- if (useMergedTexture) {
- imageView.loadTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- imageView.loadTexture(imageFileName_tp);
- }
-
- var sw = options["scale9Width"];
- var sh = options["scale9Height"];
- if (sw && sh) {
- var swf = options["scale9Width"];
- var shf = options["scale9Height"];
- imageView.setSize(cc.size(swf, shf));
- }
-
- var cx = options["capInsetsX"];
- var cy = options["capInsetsY"];
- var cw = options["capInsetsWidth"];
- var ch = options["capInsetsHeight"];
- imageView.setCapInsets(cc.rect(cx, cy, cw, ch));
-
- }
- else {
- if (useMergedTexture) {
- imageView.loadTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- imageView.loadTexture(imageFileName_tp);
- }
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
-
- var imageView = widget;
-
- var imageFileNameDic = options["fileNameData"];
- var imageFileNameType = imageFileNameDic["resourceType"];
- switch (imageFileNameType) {
- case 0:
- var tp_i = this._filePath;
- var imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = null;
- if (imageFileName) {
- imageFileName_tp = tp_i + imageFileName;
- imageView.loadTexture(imageFileName_tp);
- }
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- imageView.loadTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- imageFileNameDic = null;
-
- var scale9EnableExist = options["scale9Enable"];
- var scale9Enable = false;
- if (scale9EnableExist) {
- scale9Enable = options["scale9Enable"];
- }
- imageView.setScale9Enabled(scale9Enable);
-
-
- if (scale9Enable) {
- var sw = options["scale9Width"];
- var sh = options["scale9Height"];
- if (sw && sh) {
- var swf = options["scale9Width"];
- var shf = options["scale9Height"];
- imageView.setSize(cc.size(swf, shf));
- }
-
- var cx = options["capInsetsX"];
- var cy = options["capInsetsY"];
- var cw = options["capInsetsWidth"];
- var ch = options["capInsetsHeight"];
-
- imageView.setCapInsets(cc.rect(cx, cy, cw, ch));
-
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForLabelFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var label = widget;
- var touchScaleChangeAble = options["touchScaleEnable"];
- label.setTouchScaleChangeAble(touchScaleChangeAble);
- var text = options["text"];
- label.setText(text);
- var fs = options["fontSize"];
- if (fs) {
- label.setFontSize(options["fontSize"]);
- }
- var fn = options["fontName"];
- if (fn) {
- label.setFontName(options["fontName"]);
- }
- var cro = options["colorR"];
- var cgo = options["colorG"];
- var cbo = options["colorB"];
- var cr = cro ? options["colorR"] : 255;
- var cg = cgo ? options["colorG"] : 255;
- var cb = cbo ? options["colorB"] : 255;
- var tc = cc.c3b(cr, cg, cb);
- label.setColor(tc);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLabelAtlasFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var labelAtlas = widget;
- var sv = options.hasOwnProperty("stringValue");
- var cmf = options.hasOwnProperty("charMapFile");
- var iw = options.hasOwnProperty("itemWidth");
- var ih = options.hasOwnProperty("itemHeight");
- var scm = options.hasOwnProperty("startCharMap");
- if (sv && cmf && iw && ih && scm && options["charMapFile"]) {
- var tp_c = this._filePath;
- var cmf_tp = null;
- var cmft = options["charMapFile"];
- cmf_tp = tp_c + cmft;
-
- labelAtlas.setProperty(options["stringValue"], cmf_tp, options["itemWidth"], options["itemHeight"], options["startCharMap"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var labelAtlas = widget;
- var sv = options.hasOwnProperty("stringValue");
- var cmf = options.hasOwnProperty("charMapFile");
- var iw = options.hasOwnProperty("itemWidth");
- var ih = options.hasOwnProperty("itemHeight");
- var scm = options.hasOwnProperty("startCharMap");
- if (sv && cmf && iw && ih && scm) {
-
- var cmftDic = options["charMapFileData"];
- var cmfType = cmftDic["resourceType"];
- switch (cmfType) {
- case 0:
- var tp_c = this._filePath;
- var cmfPath = cmftDic["path"];
- var cmf_tp = tp_c+cmfPath;
- labelAtlas.setProperty(options["stringValue"], cmf_tp, options["itemWidth"], options["itemHeight"], options["startCharMap"]);
- break;
- case 1:
- cc.log("Wrong res type of LabelAtlas!");
- break;
- default:
- break;
- }
- cmftDic = null;
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForContainerWidgetFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var containerWidget = widget;
- if (containerWidget instanceof cc.UIScrollView ||
- containerWidget instanceof cc.UIListView ||
- containerWidget instanceof cc.UIDragPanel) {
- containerWidget.setClippingEnable(options["clipAble"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForPanelFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForContainerWidgetFromJsonDictionary(widget, options);
- var panel = widget;
- var backGroundScale9Enable = options["backGroundScale9Enable"];
- panel.setBackGroundImageScale9Enabled(backGroundScale9Enable);
- var cr = options["bgColorR"];
- var cg = options["bgColorG"];
- var cb = options["bgColorB"];
-
- var scr = options["bgStartColorR"];
- var scg = options["bgStartColorG"];
- var scb = options["bgStartColorB"];
-
- var ecr = options["bgEndColorR"];
- var ecg = options["bgEndColorG"];
- var ecb = options["bgEndColorB"];
-
- var bgcv1 = options["vectorX"];
- var bgcv2 = options["vectorY"];
- panel.setBackGroundColorVector(cc.p(bgcv1, bgcv2));
-
- var co = options["bgColorOpacity"];
-
- var colorType = options["colorType"];
- panel.setBackGroundColorType(colorType);
- panel.setBackGroundColor(cc.c3b(scr, scg, scb), cc.c3b(ecr, ecg, ecb));
- panel.setBackGroundColor(cc.c3b(cr, cg, cb));
- panel.setBackGroundColorOpacity(co);
-
- var tp_b = this._filePath;
- var imageFileName = options["backGroundImage"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- var useMergedTexture = options["useMergedTexture"];
- if (backGroundScale9Enable) {
- var cx = options["capInsetsX"];
- var cy = options["capInsetsY"];
- var cw = options["capInsetsWidth"];
- var ch = options["capInsetsHeight"];
- if (useMergedTexture) {
- panel.setBackGroundImage(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- panel.setBackGroundImage(imageFileName_tp);
- }
- panel.setBackGroundImageCapInsets(cc.rect(cx, cy, cw, ch));
- }
- else {
-
- if (useMergedTexture) {
- panel.setBackGroundImage(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- panel.setBackGroundImage(imageFileName_tp);
- }
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForContainerWidgetFromJsonDictionary(widget, options);
- var panel = widget;
- var backGroundScale9Enable = options["backGroundScale9Enable"];
- panel.setBackGroundImageScale9Enabled(backGroundScale9Enable);
- var cr = options["bgColorR"];
- var cg = options["bgColorG"]
- var cb = options["bgColorB"];
-
- var scr = options["bgStartColorR"];
- var scg = options["bgStartColorG"]
- var scb = options["bgStartColorB"];
-
- var ecr = options["bgEndColorR"];
- var ecg = options["bgEndColorG"];
- var ecb = options["bgEndColorB"];
-
- var bgcv1 = options["vectorX"];
- var bgcv2 = options["vectorY"];
- panel.setBackGroundColorVector(cc.p(bgcv1, bgcv2));
-
- var co = options["bgColorOpacity"];
-
- var colorType = options["colorType"];
- panel.setBackGroundColorType(colorType);
- panel.setBackGroundColor(cc.c3b(scr, scg, scb), cc.c3b(ecr, ecg, ecb));
- panel.setBackGroundColor(cc.c3b(cr, cg, cb));
- panel.setBackGroundColorOpacity(co);
-
-
- var imageFileNameDic = options["backGroundImageData"]||{};
- var imageFileNameType = imageFileNameDic["resourceType"];
- switch (imageFileNameType) {
- case 0:
- var tp_b = this._filePath;
- var imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- panel.setBackGroundImage(imageFileName_tp);
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- panel.setBackGroundImage(imageFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- imageFileNameDic = null;
-
- if (backGroundScale9Enable) {
- var cx = options["capInsetsX"];
- var cy = options["capInsetsY"];
- var cw = options["capInsetsWidth"];
- var ch = options["capInsetsHeight"];
- panel.setBackGroundImageCapInsets(cc.rect(cx, cy, cw, ch));
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForScrollViewFromJsonDictionary: function (widget, options) {
- this.setPropsForPanelFromJsonDictionary(widget, options);
- var scrollView = widget;
- var innerWidth = options["innerWidth"];
- var innerHeight = options["innerHeight"];
- scrollView.setInnerContainerSize(cc.size(innerWidth, innerHeight));
- /* gui mark */
- var direction = options["direction"];
- scrollView.setDirection(direction);
- /**/
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForSliderFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var slider = widget;
-
- var barTextureScale9Enable = options["barTextureScale9Enable"];
- slider.setScale9Enabled(barTextureScale9Enable);
- var bt = options["barFileName"];
- var barLength = options["length"];
- var useMergedTexture = options["useMergedTexture"];
- if (bt) {
- if (barTextureScale9Enable) {
- var tp_b = this._filePath;
- var imageFileName = options["barFileName"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- if (useMergedTexture) {
- slider.loadBarTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- slider.loadBarTexture(imageFileName_tp);
- }
- slider.setSize(cc.size(barLength, slider.getContentSize().height));
- }
- else {
- var tp_b = this._filePath;
- var imageFileName = options["barFileName"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- if (useMergedTexture) {
- slider.loadBarTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- slider.loadBarTexture(imageFileName_tp);
- }
- }
- }
- var tp_n = this._filePath;
- var tp_p = this._filePath;
- var tp_d = this._filePath;
-
- var normalFileName = options["ballNormal"];
- var pressedFileName = options["ballPressed"];
- var disabledFileName = options["ballDisabled"];
-
- var normalFileName_tp = normalFileName ? tp_n + normalFileName : null;
- var pressedFileName_tp = pressedFileName ? tp_p + pressedFileName : null;
- var disabledFileName_tp = disabledFileName ? tp_d + disabledFileName : null;
- if (useMergedTexture) {
- slider.loadSlidBallTextures(normalFileName, pressedFileName, disabledFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- slider.loadSlidBallTextures(normalFileName_tp, pressedFileName_tp, disabledFileName_tp);
- }
- slider.setPercent(options["percent"]);
-
- var tp_b = this._filePath;
- var imageFileName = options["progressBarFileName"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- if (useMergedTexture) {
- slider.loadProgressBarTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- slider.loadProgressBarTexture(imageFileName_tp);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var slider = widget;
-
- var barTextureScale9Enable = options["barTextureScale9Enable"];
- slider.setScale9Enabled(barTextureScale9Enable);
- var bt = options["barFileName"];
- var barLength = options["length"];
- if (bt) {
- if (barTextureScale9Enable) {
-
- var imageFileNameDic = options["barFileNameData"];
- var imageFileType = imageFileNameDic["resourceType"];
- switch (imageFileType) {
- case 0:
- var tp_b = this._filePath;
- var imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- slider.loadBarTexture(imageFileName_tp);
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- slider.loadBarTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
-
- slider.setSize(cc.size(barLength, slider.getContentSize().height));
- imageFileNameDic = null;
- }
- else {
- var imageFileNameDic = options["barFileNameData"];
- var imageFileType = imageFileNameDic["resourceType"];
- switch (imageFileType) {
- case 0:
- var tp_b = this._filePath;
- var imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- slider.loadBarTexture(imageFileName_tp);
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- slider.loadBarTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- imageFileNameDic = null;
- }
- }
-
- var normalDic = options["ballNormalData"];
- var normalType = normalDic["resourceType"];
- switch (normalType) {
- case 0:
- var tp_n = this._filePath;
- var normalFileName = normalDic["path"];
- var normalFileName_tp = normalFileName ? tp_n + normalFileName : null;
- slider.loadSlidBallTextureNormal(normalFileName_tp);
- break;
- case 1:
- var normalFileName = normalDic["path"];
- slider.loadSlidBallTextureNormal(normalFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- normalDic = null;
-
- var pressedDic = options["ballPressedData"];
- var pressedType = pressedDic["resourceType"];
- switch (pressedType) {
- case 0:
- var tp_p = this._filePath;
- var pressedFileName = pressedDic["path"];
- var pressedFileName_tp = pressedFileName ? tp_p + pressedFileName : null;
- slider.loadSlidBallTexturePressed(pressedFileName_tp);
- break;
- case 1:
- var pressedFileName = pressedDic["path"];
- slider.loadSlidBallTexturePressed(pressedFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- pressedDic = null;
-
- var disabledDic = options["ballDisabledData"];
- var disabledType = disabledDic["resourceType"];
- switch (disabledType) {
- case 0:
- var tp_d = this._filePath;
- var disabledFileName = disabledDic["path"];
- var disabledFileName_tp = disabledFileName ? tp_d + disabledFileName : null;
- slider.loadSlidBallTextureDisabled(disabledFileName_tp);
- break;
- case 1:
- var disabledFileName = disabledDic["path"];
- slider.loadSlidBallTextureDisabled(disabledFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- disabledDic = null;
-
- slider.setPercent(options["percent"]);
-
- var progressBarDic = options["progressBarData"];
- var progressBarType = progressBarDic["resourceType"];
- switch (progressBarType) {
- case 0:
- var tp_b = this._filePath;
- var imageFileName = progressBarDic["path"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- slider.loadProgressBarTexture(imageFileName_tp);
- break;
- case 1:
- var imageFileName = progressBarDic["path"];
- slider.loadProgressBarTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForTextAreaFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var textArea = widget;
- textArea.setText(options["text"]);
- var fs = options["fontSize"];
- if (fs) {
- textArea.setFontSize(options["fontSize"]);
- }
- var cr = options["colorR"]
- var cg = options["colorG"];
- var cb = options["colorB"];
- textArea.setColor(cc.c3b(cr, cg, cb));
- textArea.setFontName(options["fontName"]);
- var aw = options["areaWidth"];
- var ah = options["areaHeight"];
- if (aw && ah) {
- var size = cc.size(options["areaWidth"], options["areaHeight"]);
- textArea.setTextAreaSize(size);
- }
- var ha = options["hAlignment"];
- if (ha) {
- textArea.setTextHorizontalAlignment(options["hAlignment"]);
- }
- var va = options["vAlignment"];
- if (va) {
- textArea.setTextVerticalAlignment(options["vAlignment"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForTextButtonFromJsonDictionary: function (widget, options) {
- this.setPropsForButtonFromJsonDictionary(widget, options);
-
- var textButton = widget;
- textButton.setTitleText(options["text"]||"");
- var cr = options["textColorR"];
- var cg = options["textColorG"];
- var cb = options["textColorB"];
- var cri = cr ? options["textColorR"] : 255;
- var cgi = cg ? options["textColorG"] : 255;
- var cbi = cb ? options["textColorB"] : 255;
- textButton.setTitleColor(cc.c3b(cri, cgi, cbi));
- var fs = options["fontSize"];
- if (fs) {
- textButton.setTitleFontSize(options["fontSize"]);
- }
- var fn = options["fontName"];
- if (fn) {
- textButton.setTitleFontName(options["fontName"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForTextFieldFromJsonDictionary: function (widget, options) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var textField = widget;
- var ph = options["placeHolder"];
- if (ph) {
- textField.setPlaceHolder(options["placeHolder"]);
- }
- textField.setText(options["text"]);
- var fs = options["fontSize"];
- if (fs) {
- textField.setFontSize(options["fontSize"]);
- }
- var fn = options["fontName"];
- if (fn) {
- textField.setFontName(options["fontName"]);
- }
- var tsw = options["touchSizeWidth"];
- var tsh = options["touchSizeHeight"];
- if (tsw && tsh) {
- textField.setTouchSize(cc.size(options["touchSizeWidth"], options["touchSizeHeight"]));
- }
-
- var dw = options["width"];
- var dh = options["height"];
- if (dw > 0.0 || dh > 0.0) {
- //textField.setSize(CCSizeMake(dw, dh));
- }
- var maxLengthEnable = options["maxLengthEnable"];
- textField.setMaxLengthEnable(maxLengthEnable);
-
- if (maxLengthEnable) {
- var maxLength = options["maxLength"];
- textField.setMaxLength(maxLength);
- }
- var passwordEnable = options["passwordEnable"];
- textField.setPasswordEnable(passwordEnable);
- if (passwordEnable) {
- textField.setPasswordStyleText(options["passwordStyleText"]);
- }
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLoadingBarFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var loadingBar = widget;
- var useMergedTexture = options["useMergedTexture"];
- var tp_b = this._filePath;
- var imageFileName = options["texture"];
- var imageFileName_tp = imageFileName ? tp_b + imageFileName : null;
- if (useMergedTexture) {
- loadingBar.loadTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- }
- else {
- loadingBar.loadTexture(imageFileName_tp);
- }
- loadingBar.setDirection(options["direction"]);
- loadingBar.setPercent(options["percent"]);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
- var loadingBar = widget;
-
- var imageFileNameDic = options["textureData"];
- var imageFileNameType = imageFileNameDic["resourceType"];
- switch (imageFileNameType) {
- case 0:
- var tp_i = this._filePath;
- var imageFileName = imageFileNameDic["path"];
- var imageFileName_tp = null;
- if (imageFileName) {
- imageFileName_tp = tp_i + imageFileName;
- loadingBar.loadTexture(imageFileName_tp);
- }
- break;
- case 1:
- var imageFileName = imageFileNameDic["path"];
- loadingBar.loadTexture(imageFileName, cc.RESOURCE_TYPE.PLIST);
- break;
- default:
- break;
- }
- imageFileNameDic = null;
-
- /* gui mark add load bar scale9 parse */
- var scale9Enable = options["scale9Enable"];
- loadingBar.setScale9Enabled(scale9Enable);
-
- if (scale9Enable) {
- var cx = options["capInsetsX"];
- var cy = options["capInsetsY"];
- var cw = options["capInsetsWidth"];
- var ch = options["capInsetsHeight"];
-
- loadingBar.setCapInsets(cc.rect(cx, cy, cw, ch));
-
- var width = options["width"];
- var height = options["height"];
- loadingBar.setSize(cc.size(width, height));
- }
- /**/
-
- loadingBar.setDirection(options["direction"]);
- loadingBar.setPercent(options["percent"]);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForListViewFromJsonDictionary: function (widget, options) {
- this.setPropsForScrollViewFromJsonDictionary(widget, options);
- },
-
- setPropsForPageViewFromJsonDictionary: function (widget, options) {
- this.setPropsForPanelFromJsonDictionary(widget, options);
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- },
-
- setPropsForLabelBMFontFromJsonDictionary: function (widget, options) {
- if (this._olderVersion) {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
-
- var labelBMFont = widget;
-
- var tp_c = this._filePath;
- var cmf_tp = null;
- var cmft = options["fileName"];
- cmf_tp = tp_c + cmft;
-
- labelBMFont.setFntFile(cmf_tp);
-
- var text = options["text"];
- labelBMFont.setText(text);
-
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- else {
- this.setPropsForWidgetFromJsonDictionary(widget, options);
-
- var labelBMFont = widget;
-
- var cmftDic = options["fileNameData"];
- var cmfType = cmftDic["resourceType"];
- switch (cmfType) {
- case 0:
- var tp_c = this._filePath;
- var cmfPath = cmftDic["path"];
- var cmf_tp = tp_c + cmfPath;
- labelBMFont.setFntFile(cmf_tp);
- break;
- case 1:
- cc.log("Wrong res type of LabelAtlas!");
- break;
- default:
- break;
- }
- cmftDic = null;
-
- var text = options["text"];
- labelBMFont.setText(text);
-
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
- },
-
- setPropsForDragPanelFromJsonDictionary: function (widget, options) {
- this.setPropsForPanelFromJsonDictionary(widget, options);
-
- var dragPanel = widget;
-
- var bounceEnable = options["bounceEnable"];
- dragPanel.setBounceEnabled(bounceEnable);
-
- var innerWidth = options["innerWidth"];
- var innerHeight = options["innerHeight"];
- dragPanel.setInnerContainerSize(cc.size(innerWidth, innerHeight));
-
- this.setColorPropsForWidgetFromJsonDictionary(widget, options);
- }
-});
-cc.CCSGUIReader._instance = null;
-cc.CCSGUIReader.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.CCSGUIReader();
- }
- return this._instance;
-};
diff --git a/extensions/CocoStudio/Reader/CCSSceneReader.js b/extensions/CocoStudio/Reader/CCSSceneReader.js
deleted file mode 100644
index 6bfb4ea3e9..0000000000
--- a/extensions/CocoStudio/Reader/CCSSceneReader.js
+++ /dev/null
@@ -1,336 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-cc.CCSSceneReader = cc.Class.extend({
- _baseBath:"",
- ctor: function () {
- this._instance = null;
- this._baseBath = "";
- },
- createNodeWithSceneFile: function (pszFileName) {
- var size = 0;
- var data = 0;
- var node = null;
- do {
- if (!pszFileName)
- break;
-
- var strFileName = pszFileName;
- var pos = strFileName.lastIndexOf("/");
- if(pos>-1){
- this._baseBath =strFileName.substr(0,pos+1);
- }
- data = cc.FileUtils.getInstance().getTextFileData(pszFileName, "r", size);
-
- if (!data)
- break;
-
- var jsonDict = JSON.parse(data);
- node = this.createObject(jsonDict, null);
- } while (0);
- this._baseBath = "";
- return node;
- },
-
- createObject: function (inputFiles, parenet) {
- var className = inputFiles["classname"];
- if (className == "CCNode") {
- var gb = null;
- if (!parenet) {
- gb = cc.Node.create();
- }
- else {
- gb = cc.Node.create();
- parenet.addChild(gb);
- }
-
- this.setPropertyFromJsonDict(gb, inputFiles);
-
- var components = inputFiles["components"];
- for (var i = 0; i < components.length; i++) {
- var subDict = components[i];
- if (!subDict) {
- break;
- }
- var className = subDict["classname"];
- var comName = subDict["name"];
-
- var fileData = subDict["fileData"];
- var path = "";
- var plistFile = "";
- var resType = 0;
- path +=this._baseBath;
- if (fileData != null) {
- var file = fileData["path"];
- resType = fileData["resourceType"]
- resType = (resType || resType == 0) ? resType : -1;
- var plistFile = fileData["plistFile"];
- if (file != null) {
- path += cc.FileUtils.getInstance().fullPathForFilename(file);
- }
-
- if (plistFile != null) {
- plistFile += cc.FileUtils.getInstance().fullPathForFilename(plistFile);
- }
- fileData = null;
- }
-
- if (className == "CCSprite") {
- var sprite = null;
-
- if (resType == 0) {
- var startPos = path.lastIndexOf(".png");
- if (startPos <= -1) {
- continue;
- }
- sprite = cc.Sprite.create(path);
- }
- else if (resType == 1) {
- var startPos = plistFile.lastIndexOf(".plist");
- if (startPos <= -1) {
- continue;
- }
- var startPos = plistFile.lastIndexOf(".", plistFile.length);
- var pngFile = plistFile.substr(0, startPos);
- pngFile = pngFile + ".png";
-
- pngFile.replace(pos, pngFile.length(), ".png");
- cc.SpriteFrameCache.getInstance().addSpriteFrames(plistFile, pngFile);
- sprite = cc.Sprite.createWithSpriteFrameName(path);
- }
- else {
- continue;
- }
-
- var render = cc.ComRender.create(sprite, "CCSprite");
- if (comName != null) {
- render.setName(comName);
- }
-
- gb.addComponent(render);
- }
- else if (className == "CCTMXTiledMap") {
- var tmx = null;
- if (resType == 0) {
- var startPos = path.lastIndexOf(".tmx");
- if (startPos <= -1) {
- continue;
- }
- tmx = cc.TMXTiledMap.create(path);
- }
- else {
- continue;
- }
-
- var render = cc.ComRender.create(tmx, "CCTMXTiledMap");
- if (comName != null) {
- render.setName(comName);
- }
- gb.addComponent(render);
- }
- else if (className == "CCParticleSystemQuad") {
- var startPos = path.lastIndexOf(".plist");
- if (startPos <= -1) {
- continue;
- }
-
- var particle = null;
- if (resType == 0) {
- particle = cc.ParticleSystem.create(path);
- }
- else {
- cc.log("unknown resourcetype on CCParticleSystemQuad!");
- }
-
- particle.setPosition(0, 0);
- var render = cc.ComRender.create(particle, "CCParticleSystemQuad");
- if (comName != null) {
- render.setName(comName);
- }
- gb.addComponent(render);
- }
- else if (className == "CCArmature") {
- if (resType != 0) {
- continue;
- }
- var reDir = path;
- var file_path = "";
- var pos = reDir.lastIndexOf('/');
- if (pos != -1) {
- file_path = reDir.substr(0, pos + 1);
- }
- var size = 0;
- var des = cc.FileUtils.getInstance().getTextFileData(path, "r", size);
- if (!des) {
- cc.log("read json file[%s] error!\n", path);
- continue;
- }
- var jsonDict = JSON.parse(des);
- var armature_data = jsonDict["armature_data"];
- var childrenCount = armature_data.length;
- var subData = armature_data[0];
- var name = subData["name"];
-
- var config_file_path = jsonDict["config_file_path"];
- childrenCount = config_file_path.length;
- for (var i = 0; i < childrenCount; ++i) {
- var plist = config_file_path[i];
- var plistpath = "";
- plistpath += file_path;
- plistpath += plist;
- var root = cc.FileUtils.getInstance().createDictionaryWithContentsOfFile(plistpath);
- var metadata = root["metadata"];
- var textureFileName = metadata["textureFileName"];
-
- var textupath = "";
- textupath += file_path;
- textupath += textureFileName;
- cc.ArmatureDataManager.getInstance().addArmatureFileInfo(textupath, plistpath, path);
- }
-
- var armature = cc.Armature.create(name);
- var render = cc.ComRender.create(armature, "CCArmature");
- if (comName != null) {
- render.setName(comName);
- }
- gb.addComponent(render);
-
- var actionName = subDict["selectedactionname"];
- if (actionName && armature.getAnimation()) {
- armature.getAnimation().play(actionName);
- }
- jsonDict = null;
- subData = null;
- des = null;
- }
- else if (className == "CCComAudio") {
- var audio = null;
- if (resType == 0) {
- audio = cc.ComAudio.create();
- }
- else {
- continue;
- }
- audio.preloadEffect(path);
- gb.addComponent(audio);
- }
- else if (className == "CCComAttribute") {
- var attribute = null;
- if (resType == 0) {
- attribute = cc.ComAttribute.create();
- var size = 0;
- var data = 0;
- data = cc.FileUtils.getInstance().getTextFileData(path, "r", size);
- if (data) {
- attribute.setDict(JSON.parse(data));
- }
- }
- else {
- cc.log("unknown resourcetype on CCComAttribute!");
- continue;
- }
- gb.addComponent(attribute);
- }
- else if (className == "CCBackgroundAudio") {
- var audio = null;
- if (resType == 0) {
- audio = cc.ComAudio.create();
- }
- else {
- continue;
- }
- audio.preloadBackgroundMusic(path);
- audio.setFile(path);
- var bLoop = Boolean(subDict["loop"] || 0);
- audio.setLoop(bLoop);
- gb.addComponent(audio);
- audio.playBackgroundMusic(path, bLoop);
- }
- else if (className == "GUIComponent") {
- var pLayer = cc.UILayer.create();
- pLayer.scheduleUpdate();
- var widget = cc.UIHelper.getInstance().createWidgetFromJsonFile(path);
- pLayer.addWidget(widget);
- var render = cc.ComRender.create(pLayer, "GUIComponent");
- if (comName != null) {
- render.setName(comName);
- }
- gb.addComponent(render);
- }
- subDict = null;
- }
- var gameobjects = inputFiles["gameobjects"];
- for (var i = 0; i < gameobjects.length; i++) {
- var subDict = gameobjects[i];
- if (!subDict) {
- break;
- }
- this.createObject(subDict, gb);
- subDict = null;
- }
-
- return gb;
- }
-
- return null;
- },
-
-
- setPropertyFromJsonDict: function (node, dict) {
- var x = dict["x"] || 0;
- var y = dict["y"] || 0;
- node.setPosition(cc.p(x, y));
-
- var bVisible = Boolean(dict["visible"] || 1);
- node.setVisible(bVisible);
-
- var nTag = dict["objecttag"] || -1;
- node.setTag(nTag);
-
- var nZorder = dict["zorder"] || 0;
- node.setZOrder(nZorder);
-
- var fScaleX = dict["scalex"] || 1;
- var fScaleY = dict["scaley"] || 1;
- node.setScaleX(fScaleX);
- node.setScaleY(fScaleY);
-
- var fRotationZ = dict["rotation"] || 0;
- node.setRotation(fRotationZ);
- },
-
- purgeSceneReader: function () {
- this._instance = null;
- }
-});
-cc.CCSSceneReader._instance = null;
-cc.CCSSceneReader.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.CCSSceneReader();
- }
- return this._instance;
-};
-cc.CCSSceneReader.sceneReaderVersion = function () {
- return "1.0.0.0";
-};
diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js
deleted file mode 100644
index d53dd4f885..0000000000
--- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js
+++ /dev/null
@@ -1,833 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2012 Neofect. All rights reserved.
-
- http://www.cocos2d-x.org
-
- 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.
-
- Created by Jung Sang-Taik on 2012-03-16
- ****************************************************************************/
-
-cc.POSITIONS_CENTRE = 0;
-cc.POSITIONS_TOP = 1;
-cc.POSITIONS_LEFT = 2;
-cc.POSITIONS_RIGHT = 3;
-cc.POSITIONS_BOTTOM = 4;
-cc.POSITIONS_TOPRIGHT = 5;
-cc.POSITIONS_TOPLEFT = 6;
-cc.POSITIONS_BOTTOMRIGHT = 7;
-cc.POSITIONS_BOTTOMLEFT = 8;
-
-/**
- * A 9-slice sprite for cocos2d.
- *
- * 9-slice scaling allows you to specify how scaling is applied
- * to specific areas of a sprite. With 9-slice scaling (3x3 grid),
- * you can ensure that the sprite does not become distorted when
- * scaled.
- *
- * @see http://yannickloriot.com/library/ios/cccontrolextension/Classes/CCScale9Sprite.html
- * @class
- * @extends cc.Sprite
- */
-cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{
- RGBAProtocol: true,
-
- _spriteRect: null,
- _capInsetsInternal: null,
- _positionsAreDirty: false,
-
- _scale9Image: null,
- _topLeft: null,
- _top: null,
- _topRight: null,
- _left: null,
- _centre: null,
- _right: null,
- _bottomLeft: null,
- _bottom: null,
- _bottomRight: null,
-
- _colorUnmodified: null,
- _opacityModifyRGB: false,
-
- _originalSize: null,
- _preferredSize: null,
- _opacity: 0,
- _color: null,
- _capInsets: null,
- _insetLeft: 0,
- _insetTop: 0,
- _insetRight: 0,
- _insetBottom: 0,
-
- _spritesGenerated: false,
- _spriteFrameRotated: false,
-
- _updateCapInset: function () {
- var insets, locInsetLeft = this._insetLeft, locInsetTop = this._insetTop, locInsetRight = this._insetRight;
- var locSpriteRect = this._spriteRect, locInsetBottom = this._insetBottom;
- if (locInsetLeft === 0 && locInsetTop === 0 && locInsetRight === 0 && locInsetBottom === 0) {
- insets = cc.RectZero();
- } else {
- insets = this._spriteFrameRotated ? cc.rect(locInsetBottom, locInsetLeft,
- locSpriteRect.width - locInsetRight - locInsetLeft,
- locSpriteRect.height - locInsetTop - locInsetBottom) :
- cc.rect(locInsetLeft, locInsetTop,
- locSpriteRect.width - locInsetLeft - locInsetRight,
- locSpriteRect.height - locInsetTop - locInsetBottom);
- }
- this.setCapInsets(insets);
- },
-
- _updatePositions: function () {
- // Check that instances are non-NULL
- if (!((this._topLeft) && (this._topRight) && (this._bottomRight) &&
- (this._bottomLeft) && (this._centre))) {
- // if any of the above sprites are NULL, return
- return;
- }
-
- var size = this._contentSize;
- var locTopLeft = this._topLeft, locTopRight = this._topRight, locBottomRight = this._bottomRight;
- var locCenter = this._centre, locCenterContentSize = this._centre.getContentSize();
-
- var sizableWidth = size.width - locTopLeft.getContentSize().width - locTopRight.getContentSize().width;
- var sizableHeight = size.height - locTopLeft.getContentSize().height - locBottomRight.getContentSize().height;
- var horizontalScale = sizableWidth / locCenterContentSize.width;
- var verticalScale = sizableHeight / locCenterContentSize.height;
- var rescaledWidth = locCenterContentSize.width * horizontalScale;
- var rescaledHeight = locCenterContentSize.height * verticalScale;
-
- var locBottomLeft = this._bottomLeft;
- var leftWidth = locBottomLeft.getContentSize().width;
- var bottomHeight = locBottomLeft.getContentSize().height;
-
- if(!cc.Browser.supportWebGL) {
- //browser is in canvas mode, need to manually control rounding to prevent overlapping pixels
- var roundedRescaledWidth = Math.round(rescaledWidth);
- if(rescaledWidth != roundedRescaledWidth) {
- rescaledWidth = roundedRescaledWidth;
- horizontalScale = rescaledWidth/locCenterContentSize.width;
- }
- var roundedRescaledHeight = Math.round(rescaledHeight);
- if(rescaledHeight != roundedRescaledHeight) {
- rescaledHeight = roundedRescaledHeight;
- verticalScale = rescaledHeight/locCenterContentSize.height;
- }
- }
- locCenter.setScaleX(horizontalScale);
- locCenter.setScaleY(verticalScale);
-
- var locLeft = this._left, locRight = this._right, locTop = this._top, locBottom = this._bottom;
- var tempAP = cc.p(0, 0);
- locBottomLeft.setAnchorPoint(tempAP);
- locBottomRight.setAnchorPoint(tempAP);
- locTopLeft.setAnchorPoint(tempAP);
- locTopRight.setAnchorPoint(tempAP);
- locLeft.setAnchorPoint(tempAP);
- locRight.setAnchorPoint(tempAP);
- locTop.setAnchorPoint(tempAP);
- locBottom.setAnchorPoint(tempAP);
- locCenter.setAnchorPoint(tempAP);
-
- // Position corners
- locBottomLeft.setPosition(0, 0);
- locBottomRight.setPosition(leftWidth + rescaledWidth, 0);
- locTopLeft.setPosition(0, bottomHeight + rescaledHeight);
- locTopRight.setPosition(leftWidth + rescaledWidth, bottomHeight + rescaledHeight);
-
- // Scale and position borders
- locLeft.setPosition(0, bottomHeight);
- locLeft.setScaleY(verticalScale);
- locRight.setPosition(leftWidth + rescaledWidth, bottomHeight);
- locRight.setScaleY(verticalScale);
- locBottom.setPosition(leftWidth, 0);
- locBottom.setScaleX(horizontalScale);
- locTop.setPosition(leftWidth, bottomHeight + rescaledHeight);
- locTop.setScaleX(horizontalScale);
-
- // Position centre
- locCenter.setPosition(leftWidth, bottomHeight);
- },
-
- ctor: function () {
- cc.Node.prototype.ctor.call(this);
- this._spriteRect = cc.RectZero();
- this._capInsetsInternal = cc.RectZero();
-
- this._colorUnmodified = cc.white();
- this._originalSize = new cc.Size(0, 0);
- this._preferredSize = new cc.Size(0, 0);
- this._color = cc.white();
- this._opacity = 255;
- this._capInsets = cc.RectZero();
- },
-
- /** Original sprite's size. */
- getOriginalSize: function () {
- return this._originalSize;
- },
-
- //if the preferredSize component is given as -1, it is ignored
- getPreferredSize: function () {
- return this._preferredSize;
- },
- setPreferredSize: function (preferredSize) {
- this.setContentSize(preferredSize);
- this._preferredSize = preferredSize;
- },
-
- /** Opacity: conforms to CCRGBAProtocol protocol */
- getOpacity: function () {
- return this._opacity;
- },
- setOpacity: function (opacity) {
- if(!this._scale9Image){
- return;
- }
- this._opacity = opacity;
- var scaleChildren = this._scale9Image.getChildren();
- for (var i = 0; i < scaleChildren.length; i++) {
- var selChild = scaleChildren[i];
- if (selChild && selChild.RGBAProtocol)
- selChild.setOpacity(opacity);
- }
- },
-
- /** Color: conforms to CCRGBAProtocol protocol */
- getColor: function () {
- return this._color;
- },
- setColor: function (color) {
- if(!this._scale9Image){
- return;
- }
- this._color = color;
- var scaleChildren = this._scale9Image.getChildren();
- for (var i = 0; i < scaleChildren.length; i++) {
- var selChild = scaleChildren[i];
- if (selChild && selChild.RGBAProtocol)
- selChild.setColor(color);
- }
- },
-
- getCapInsets: function () {
- return this._capInsets;
- },
-
- setCapInsets: function (capInsets) {
- if(!this._scale9Image){
- return;
- }
- var contentSize = this._contentSize;
- contentSize = new cc.Size(contentSize.width,contentSize.height);
- this.updateWithBatchNode(this._scale9Image, this._spriteRect, this._spriteFrameRotated, capInsets);
- this.setContentSize(contentSize);
- },
-
- /**
- * Gets the left side inset
- * @returns {number}
- */
- getInsetLeft: function () {
- return this._insetLeft;
- },
-
- /**
- * Sets the left side inset
- * @param {Number} insetLeft
- */
- setInsetLeft: function (insetLeft) {
- this._insetLeft = insetLeft;
- this._updateCapInset();
- },
-
- /**
- * Gets the top side inset
- * @returns {number}
- */
- getInsetTop: function () {
- return this._insetTop;
- },
-
- /**
- * Sets the top side inset
- * @param {Number} insetTop
- */
- setInsetTop: function (insetTop) {
- this._insetTop = insetTop;
- this._updateCapInset();
- },
-
- /**
- * Gets the right side inset
- * @returns {number}
- */
- getInsetRight: function () {
- return this._insetRight;
- },
- /**
- * Sets the right side inset
- * @param {Number} insetRight
- */
- setInsetRight: function (insetRight) {
- this._insetRight = insetRight;
- this._updateCapInset();
- },
-
- /**
- * Gets the bottom side inset
- * @returns {number}
- */
- getInsetBottom: function () {
- return this._insetBottom;
- },
- /**
- * Sets the bottom side inset
- * @param {number} insetBottom
- */
- setInsetBottom: function (insetBottom) {
- this._insetBottom = insetBottom;
- this._updateCapInset();
- },
-
- setContentSize: function (size) {
- cc.Node.prototype.setContentSize.call(this, size);
- this._positionsAreDirty = true;
- },
-
- visit: function () {
- if (this._positionsAreDirty) {
- this._updatePositions();
- this._positionsAreDirty = false;
- }
- cc.Node.prototype.visit.call(this);
- },
-
- init: function () {
- return this.initWithBatchNode(null, cc.RectZero(), false, cc.RectZero());
- },
-
- initWithBatchNode: function (batchNode, rect, rotated, capInsets) {
- if (arguments.length === 3) {
- capInsets = rotated;
- rotated = false;
- }
-
- if (batchNode) {
- this.updateWithBatchNode(batchNode, rect, rotated, capInsets);
- }
- this.setAnchorPoint(cc.p(0.5, 0.5));
- this._positionsAreDirty = true;
- return true;
- },
-
- /**
- * Initializes a 9-slice sprite with a texture file, a delimitation zone and
- * with the specified cap insets.
- * Once the sprite is created, you can then call its "setContentSize:" method
- * to resize the sprite will all it's 9-slice goodness intact.
- * It respects the anchorPoint too.
- *
- * @param file The name of the texture file.
- * @param rect The rectangle that describes the sub-part of the texture that
- * is the whole image. If the shape is the whole texture, set this to the
- * texture's full rect.
- * @param capInsets The values to use for the cap insets.
- */
- initWithFile: function (file, rect, capInsets) {
- if (file instanceof cc.Rect) {
- file = arguments[1];
- capInsets = arguments[0];
- rect = cc.RectZero();
- } else {
- rect = rect || cc.RectZero();
- capInsets = capInsets || cc.RectZero();
- }
-
- cc.Assert(file != null, "Invalid file for sprite");
- var batchnode = cc.SpriteBatchNode.create(file, 9);
- return this.initWithBatchNode(batchnode, rect, false, capInsets);
- },
-
- /**
- * Initializes a 9-slice sprite with an sprite frame and with the specified
- * cap insets.
- * Once the sprite is created, you can then call its "setContentSize:" method
- * to resize the sprite will all it's 9-slice goodness intract.
- * It respects the anchorPoint too.
- *
- * @param spriteFrame The sprite frame object.
- * @param capInsets The values to use for the cap insets.
- */
- initWithSpriteFrame: function (spriteFrame, capInsets) {
- capInsets = capInsets || cc.RectZero();
-
- cc.Assert(spriteFrame != null, "Sprite frame must not be nil");
- var selTexture = spriteFrame.getTexture();
- cc.Assert(selTexture != null, "Texture must be not nil");
-
- if(!spriteFrame.textureLoaded()){
- spriteFrame.addLoadedEventListener(function(sender){
- // the texture is rotated on Canvas render mode, so isRotated always is false.
- var preferredSize = this._preferredSize;
- preferredSize = cc.size(preferredSize.width, preferredSize.height);
- this.updateWithBatchNode(this._scale9Image, sender.getRect(), cc.Browser.supportWebGL ? sender.isRotated() : false, this._capInsets);
- this.setPreferredSize(preferredSize);
- this._positionsAreDirty = true;
- },this);
- }
- var batchNode = cc.SpriteBatchNode.createWithTexture(selTexture, 9);
- // the texture is rotated on Canvas render mode, so isRotated always is false.
- return this.initWithBatchNode(batchNode, spriteFrame.getRect(), cc.Browser.supportWebGL ? spriteFrame.isRotated() : false, capInsets);
- },
-
- /**
- * Initializes a 9-slice sprite with an sprite frame name and with the specified
- * cap insets.
- * Once the sprite is created, you can then call its "setContentSize:" method
- * to resize the sprite will all it's 9-slice goodness intract.
- * It respects the anchorPoint too.
- *
- * @param spriteFrameName The sprite frame name.
- * @param capInsets The values to use for the cap insets.
- */
- initWithSpriteFrameName: function (spriteFrameName, capInsets) {
- capInsets = capInsets || cc.RectZero();
-
- cc.Assert(spriteFrameName != null, "Invalid spriteFrameName for sprite");
- var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName);
- cc.Assert(frame != null, "cc.SpriteFrame must be non-NULL");
- if (frame == null)
- return false;
- return this.initWithSpriteFrame(frame, capInsets);
- },
-
- /**
- * Creates and returns a new sprite object with the specified cap insets.
- * You use this method to add cap insets to a sprite or to change the existing
- * cap insets of a sprite. In both cases, you get back a new image and the
- * original sprite remains untouched.
- *
- * @param capInsets The values to use for the cap insets.
- */
- resizableSpriteWithCapInsets: function (capInsets) {
- var pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.initWithBatchNode(this._scale9Image, this._spriteRect, false, capInsets)) {
- return pReturn;
- }
- return null;
- },
-
- /** sets the premultipliedAlphaOpacity property.
- If set to NO then opacity will be applied as: glColor(R,G,B,opacity);
- If set to YES then oapcity will be applied as: glColor(opacity, opacity, opacity, opacity );
- Textures with premultiplied alpha will have this property by default on YES. Otherwise the default value is NO
- @since v0.8
- */
- setOpacityModifyRGB: function (value) {
- if(!this._scale9Image){
- return;
- }
- this._opacityModifyRGB = value;
- var scaleChildren = this._scale9Image.getChildren();
- if (scaleChildren) {
- for (var i = 0, len = scaleChildren.length; i < len; i++)
- scaleChildren[i].setOpacityModifyRGB(value);
- }
- },
-
- /** returns whether or not the opacity will be applied using glColor(R,G,B,opacity) or glColor(opacity, opacity, opacity, opacity);
- @since v0.8
- */
- isOpacityModifyRGB: function () {
- return this._opacityModifyRGB;
- },
-
- updateWithBatchNode: function (batchNode, rect, rotated, capInsets) {
- var opacity = this.getOpacity();
- var color = this.getColor();
-
- // Release old sprites
- this.removeAllChildren(true);
-
- if (this._scale9Image != batchNode){
- this._scale9Image = batchNode;
- var tmpTexture = batchNode.getTexture();
- if(!tmpTexture.isLoaded()){
- tmpTexture.addLoadedEventListener(function(sender){
- this._positionsAreDirty = true;
- },this);
- }
- }
-
- var locScale9Image = this._scale9Image;
- locScale9Image.removeAllChildren(true);
-
- this._capInsets = capInsets;
- var selTexture = locScale9Image.getTexture();
-
- // If there is no given rect
- if (cc._rectEqualToZero(rect)) {
- // Get the texture size as original
- var textureSize = selTexture.getContentSize();
- rect = cc.rect(0, 0, textureSize.width, textureSize.height);
- }
-
- // Set the given rect's size as original size
- this._spriteRect = rect;
- var rectSize = rect.size;
- this._originalSize.width = rectSize.width;
- this._originalSize.height = rectSize.height;
- var locPreferredSize = this._preferredSize;
- if(locPreferredSize.width === 0 && locPreferredSize.height === 0){
- locPreferredSize.width = rectSize.width;
- locPreferredSize.height = rectSize.height;
- }
-
- var locCapInsetsInternal = this._capInsetsInternal;
- if(!capInsets){
- locCapInsetsInternal.x = capInsets.x;
- locCapInsetsInternal.y = capInsets.y;
- locCapInsetsInternal.width = capInsets.width;
- locCapInsetsInternal.height = capInsets.height;
- }
- var w = rectSize.width;
- var h = rectSize.height;
-
- // If there is no specified center region
- if (cc._rectEqualToZero(locCapInsetsInternal)) {
- // CCLog("... cap insets not specified : using default cap insets ...");
- locCapInsetsInternal.x = w / 3;
- locCapInsetsInternal.y = h / 3;
- locCapInsetsInternal.width = w / 3;
- locCapInsetsInternal.height = h / 3;
- }
-
- var left_w = locCapInsetsInternal.x;
- var center_w = locCapInsetsInternal.width;
- var right_w = w - (left_w + center_w);
-
- var top_h = locCapInsetsInternal.y;
- var center_h = locCapInsetsInternal.height;
- var bottom_h = h - (top_h + center_h);
-
- // calculate rects
- // ... top row
- var x = 0.0;
- var y = 0.0;
-
- // top left
- var lefttopbounds = cc.rect(x, y, left_w, top_h);
-
- // top center
- x += left_w;
- var centertopbounds = cc.rect(x, y, center_w, top_h);
-
- // top right
- x += center_w;
- var righttopbounds = cc.rect(x, y, right_w, top_h);
-
- // ... center row
- x = 0.0;
- y = 0.0;
-
- // center left
- y += top_h;
- var leftcenterbounds = cc.rect(x, y, left_w, center_h);
-
- // center center
- x += left_w;
- var centerbounds = cc.rect(x, y, center_w, center_h);
-
- // center right
- x += center_w;
- var rightcenterbounds = cc.rect(x, y, right_w, center_h);
-
- // ... bottom row
- x = 0.0;
- y = 0.0;
- y += top_h;
- y += center_h;
-
- // bottom left
- var leftbottombounds = cc.rect(x, y, left_w, bottom_h);
-
- // bottom center
- x += left_w;
- var centerbottombounds = cc.rect(x, y, center_w, bottom_h);
-
- // bottom right
- x += center_w;
- var rightbottombounds = cc.rect(x, y, right_w, bottom_h);
-
- var t = cc.AffineTransformMakeIdentity();
- if (!rotated) {
- // CCLog("!rotated");
- t = cc.AffineTransformTranslate(t, rect.x, rect.y);
-
- cc._RectApplyAffineTransformIn(centerbounds, t);
- cc._RectApplyAffineTransformIn(rightbottombounds, t);
- cc._RectApplyAffineTransformIn(leftbottombounds, t);
- cc._RectApplyAffineTransformIn(righttopbounds, t);
- cc._RectApplyAffineTransformIn(lefttopbounds, t);
- cc._RectApplyAffineTransformIn(rightcenterbounds, t);
- cc._RectApplyAffineTransformIn(leftcenterbounds, t);
- cc._RectApplyAffineTransformIn(centerbottombounds, t);
- cc._RectApplyAffineTransformIn(centertopbounds, t);
-
- // Centre
- this._centre = new cc.Sprite();
- this._centre.initWithTexture(selTexture, centerbounds);
- locScale9Image.addChild(this._centre, 0, cc.POSITIONS_CENTRE);
-
- // Top
- this._top = new cc.Sprite();
- this._top.initWithTexture(selTexture, centertopbounds);
- locScale9Image.addChild(this._top, 1, cc.POSITIONS_TOP);
-
- // Bottom
- this._bottom = new cc.Sprite();
- this._bottom.initWithTexture(selTexture, centerbottombounds);
- locScale9Image.addChild(this._bottom, 1, cc.POSITIONS_BOTTOM);
-
- // Left
- this._left = new cc.Sprite();
- this._left.initWithTexture(selTexture, leftcenterbounds);
- locScale9Image.addChild(this._left, 1, cc.POSITIONS_LEFT);
-
- // Right
- this._right = new cc.Sprite();
- this._right.initWithTexture(selTexture, rightcenterbounds);
- locScale9Image.addChild(this._right, 1, cc.POSITIONS_RIGHT);
-
- // Top left
- this._topLeft = new cc.Sprite();
- this._topLeft.initWithTexture(selTexture, lefttopbounds);
- locScale9Image.addChild(this._topLeft, 2, cc.POSITIONS_TOPLEFT);
-
- // Top right
- this._topRight = new cc.Sprite();
- this._topRight.initWithTexture(selTexture, righttopbounds);
- locScale9Image.addChild(this._topRight, 2, cc.POSITIONS_TOPRIGHT);
-
- // Bottom left
- this._bottomLeft = new cc.Sprite();
- this._bottomLeft.initWithTexture(selTexture, leftbottombounds);
- locScale9Image.addChild(this._bottomLeft, 2, cc.POSITIONS_BOTTOMLEFT);
-
- // Bottom right
- this._bottomRight = new cc.Sprite();
- this._bottomRight.initWithTexture(selTexture, rightbottombounds);
- locScale9Image.addChild(this._bottomRight, 2, cc.POSITIONS_BOTTOMRIGHT);
- } else {
- // set up transformation of coordinates
- // to handle the case where the sprite is stored rotated
- // in the spritesheet
- // CCLog("rotated");
- var rotatedcenterbounds = centerbounds;
- var rotatedrightbottombounds = rightbottombounds;
- var rotatedleftbottombounds = leftbottombounds;
- var rotatedrighttopbounds = righttopbounds;
- var rotatedlefttopbounds = lefttopbounds;
- var rotatedrightcenterbounds = rightcenterbounds;
- var rotatedleftcenterbounds = leftcenterbounds;
- var rotatedcenterbottombounds = centerbottombounds;
- var rotatedcentertopbounds = centertopbounds;
-
- t = cc.AffineTransformTranslate(t, rect.height + rect.x, rect.y);
- t = cc.AffineTransformRotate(t, 1.57079633);
-
- centerbounds = cc.RectApplyAffineTransform(centerbounds, t);
- rightbottombounds = cc.RectApplyAffineTransform(rightbottombounds, t);
- leftbottombounds = cc.RectApplyAffineTransform(leftbottombounds, t);
- righttopbounds = cc.RectApplyAffineTransform(righttopbounds, t);
- lefttopbounds = cc.RectApplyAffineTransform(lefttopbounds, t);
- rightcenterbounds = cc.RectApplyAffineTransform(rightcenterbounds, t);
- leftcenterbounds = cc.RectApplyAffineTransform(leftcenterbounds, t);
- centerbottombounds = cc.RectApplyAffineTransform(centerbottombounds, t);
- centertopbounds = cc.RectApplyAffineTransform(centertopbounds, t);
-
- rotatedcenterbounds.x = centerbounds.x;
- rotatedcenterbounds.y = centerbounds.y;
-
- rotatedrightbottombounds.x = rightbottombounds.x;
- rotatedrightbottombounds.y = rightbottombounds.y;
-
- rotatedleftbottombounds.x = leftbottombounds.x;
- rotatedleftbottombounds.y = leftbottombounds.y;
-
- rotatedrighttopbounds.x = righttopbounds.x;
- rotatedrighttopbounds.y = righttopbounds.y;
-
- rotatedlefttopbounds.x = lefttopbounds.x;
- rotatedlefttopbounds.y = lefttopbounds.y;
-
- rotatedrightcenterbounds.x = rightcenterbounds.x;
- rotatedrightcenterbounds.y = rightcenterbounds.y;
-
- rotatedleftcenterbounds.x = leftcenterbounds.x;
- rotatedleftcenterbounds.y = leftcenterbounds.y;
-
- rotatedcenterbottombounds.x = centerbottombounds.x;
- rotatedcenterbottombounds.y = centerbottombounds.y;
-
- rotatedcentertopbounds.x = centertopbounds.x;
- rotatedcentertopbounds.y = centertopbounds.y;
-
- // Centre
- this._centre = new cc.Sprite();
- this._centre.initWithTexture(selTexture, rotatedcenterbounds, true);
- locScale9Image.addChild(this._centre, 0, cc.POSITIONS_CENTRE);
-
- // Top
- this._top = new cc.Sprite();
- this._top.initWithTexture(selTexture, rotatedcentertopbounds, true);
- locScale9Image.addChild(this._top, 1, cc.POSITIONS_TOP);
-
- // Bottom
- this._bottom = new cc.Sprite();
- this._bottom.initWithTexture(selTexture, rotatedcenterbottombounds, true);
- locScale9Image.addChild(this._bottom, 1, cc.POSITIONS_BOTTOM);
-
- // Left
- this._left = new cc.Sprite();
- this._left.initWithTexture(selTexture, rotatedleftcenterbounds, true);
- locScale9Image.addChild(this._left, 1, cc.POSITIONS_LEFT);
-
- // Right
- this._right = new cc.Sprite();
- this._right.initWithTexture(selTexture, rotatedrightcenterbounds, true);
- locScale9Image.addChild(this._right, 1, cc.POSITIONS_RIGHT);
-
- // Top left
- this._topLeft = new cc.Sprite();
- this._topLeft.initWithTexture(selTexture, rotatedlefttopbounds, true);
- locScale9Image.addChild(this._topLeft, 2, cc.POSITIONS_TOPLEFT);
-
- // Top right
- this._topRight = new cc.Sprite();
- this._topRight.initWithTexture(selTexture, rotatedrighttopbounds, true);
- locScale9Image.addChild(this._topRight, 2, cc.POSITIONS_TOPRIGHT);
-
- // Bottom left
- this._bottomLeft = new cc.Sprite();
- this._bottomLeft.initWithTexture(selTexture, rotatedleftbottombounds, true);
- locScale9Image.addChild(this._bottomLeft, 2, cc.POSITIONS_BOTTOMLEFT);
-
- // Bottom right
- this._bottomRight = new cc.Sprite();
- this._bottomRight.initWithTexture(selTexture, rotatedrightbottombounds, true);
- locScale9Image.addChild(this._bottomRight, 2, cc.POSITIONS_BOTTOMRIGHT);
- }
-
- this.setContentSize(rect.size);
- this.addChild(locScale9Image);
-
- if (this._spritesGenerated) {
- // Restore color and opacity
- this.setOpacity(opacity);
- if(color.r !== 255 || color.g !== 255 || color.b !== 255){
- this.setColor(color);
- }
- }
- this._spritesGenerated = true;
- return true;
- },
-
- setSpriteFrame: function (spriteFrame) {
- var batchNode = cc.SpriteBatchNode.createWithTexture(spriteFrame.getTexture(), 9);
- // the texture is rotated on Canvas render mode, so isRotated always is false.
- if(!spriteFrame.textureLoaded()){
- spriteFrame.addLoadedEventListener(function(sender){
- // the texture is rotated on Canvas render mode, so isRotated always is false.
- var preferredSize = this._preferredSize;
- preferredSize = cc.size(preferredSize.width, preferredSize.height);
- this.updateWithBatchNode(this._scale9Image, sender.getRect(), cc.Browser.supportWebGL ? sender.isRotated() : false, this._capInsets);
- this.setPreferredSize(preferredSize);
- this._positionsAreDirty = true;
- },this);
- }
- this.updateWithBatchNode(batchNode, spriteFrame.getRect(), cc.Browser.supportWebGL ? spriteFrame.isRotated() : false, cc.RectZero());
-
- // Reset insets
- this._insetLeft = 0;
- this._insetTop = 0;
- this._insetRight = 0;
- this._insetBottom = 0;
- }
-});
-
-/**
- * Creates a 9-slice sprite with a texture file, a delimitation zone and
- * with the specified cap insets.
- *
- * @see initWithFile:rect:centerRegion:
- */
-cc.Scale9Sprite.create = function (file, rect, capInsets) {
- var pReturn;
- if (arguments.length === 2) {
- if (typeof(file) == "string") {
- pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.initWithFile(file, rect)) {
- return pReturn;
- }
- } else if (file instanceof cc.Rect) {
- pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.initWithFile(file, capInsets)) {
- return pReturn;
- }
- }
- } else if (arguments.length === 3) {
- pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.initWithFile(file, rect, capInsets)) {
- return pReturn;
- }
- } else if (arguments.length === 1) {
- pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.initWithFile(file)) {
- return pReturn;
- }
- } else if (arguments.length === 0) {
- pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.init()) {
- return pReturn;
- }
- }
- return null;
-};
-
-cc.Scale9Sprite.createWithSpriteFrame = function (spriteFrame, capInsets) {
- var pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.initWithSpriteFrame(spriteFrame, capInsets)) {
- return pReturn;
- }
- return null;
-};
-
-cc.Scale9Sprite.createWithSpriteFrameName = function (spriteFrameName, capInsets) {
- cc.Assert(spriteFrameName != null, "spriteFrameName must be non-NULL");
- var pReturn = new cc.Scale9Sprite();
- if (pReturn && pReturn.initWithSpriteFrameName(spriteFrameName, capInsets)) {
- return pReturn;
- }
- return null;
-};
diff --git a/extensions/PluginX/plugins/SocialFacebook.js b/extensions/PluginX/plugins/SocialFacebook.js
deleted file mode 100644
index 34ec7be169..0000000000
--- a/extensions/PluginX/plugins/SocialFacebook.js
+++ /dev/null
@@ -1,31 +0,0 @@
-plugin.SocialFacebook = cc.Class.extend({
-
- /**
- methods of protocol : InterfaceSocial
- */
- init: function () {
- this._shareInfo = {
- 'url': window.location.href
- };
- },
- configDeveloperInfo: function (cpInfo) {
- //invalid on html5
- },
- share: function (shareInfo) {
- var url = shareInfo["SharedURLPath"];
- if(url !== null){
- this._shareInfo.url = url;
- }
-
- cc.Browser.openURL("http://www.facebook.com/sharer/sharer.php?u=" + url);
- },
- setDebugMode: function (debug) {
- //invalid on html5
- },
- getSDKVersion: function () {
- return "unkown";
- },
- getPluginVersion: function () {
- return plugin.Version;
- }
-});
\ No newline at end of file
diff --git a/extensions/PluginX/plugins/SocialQQWeibo.js b/extensions/PluginX/plugins/SocialQQWeibo.js
deleted file mode 100644
index ac05ab5d30..0000000000
--- a/extensions/PluginX/plugins/SocialQQWeibo.js
+++ /dev/null
@@ -1,42 +0,0 @@
-plugin.SocialQQWeibo = cc.Class.extend({
- _shareInfo: null,
-
- /**
- methods of protocol : InterfaceSocial
- */
- init: function () {
- this._shareInfo = {
- 'appkey': 12345678,
- 'title': "Hello, Cocos2d-html5!",
- 'url': window.location.href,
- 'pic': null
- };
- },
- configDeveloperInfo: function (cpInfo) {
- this._shareInfo.appkey = cpInfo["QQWeiboAppKey"];
- },
- share: function (shareInfo) {
- this._shareInfo.title = shareInfo["SharedText"];
- this._shareInfo.pic = shareInfo["SharedImagePath"];
-
- var urlstring = "", value;
- for (var key in this._shareInfo) {
- value = this._shareInfo[key];
- if (value !== null) {
- urlstring += encodeURI(key + "=" + value) + "&";
- }
- }
- urlstring = urlstring.substr(0, urlstring.length - 1);
- cc.Browser.openURL("http://share.v.t.qq.com/index.php?c=share&a=index&" + urlstring);
-
- },
- setDebugMode: function (debug) {
- //invalid on html5
- },
- getSDKVersion: function () {
- return "unkown";
- },
- getPluginVersion: function () {
- return plugin.Version;
- }
-});
\ No newline at end of file
diff --git a/extensions/PluginX/plugins/SocialQzone.js b/extensions/PluginX/plugins/SocialQzone.js
deleted file mode 100644
index e3b35311c0..0000000000
--- a/extensions/PluginX/plugins/SocialQzone.js
+++ /dev/null
@@ -1,45 +0,0 @@
-plugin.SocialQzone = cc.Class.extend({
- _shareInfo: null,
-
- /**
- methods of protocol : InterfaceSocial
- */
- init: function () {
- this._shareInfo = {
- 'desc': "Hello, Cocos2d-html5!",
- 'url': window.location.href,
- 'pics': null,
- 'showcount':1
- };
- },
- configDeveloperInfo: function (cpInfo) {
- //invalid on html5
- },
- share: function (shareInfo) {
- this._shareInfo.desc = shareInfo["SharedText"];
- this._shareInfo.pics = shareInfo["SharedImagePath"];
- var url = shareInfo["SharedURLPath"];
- if(url !== null){
- this._shareInfo.url = url;
- }
-
- var urlstring = "", value;
- for (var key in this._shareInfo) {
- value = this._shareInfo[key];
- if (value) {
- urlstring += encodeURI(key + "=" + value) + "&";
- }
- }
- urlstring = urlstring.substr(0, urlstring.length - 1);
- cc.Browser.openURL("http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?"+urlstring);
- },
- setDebugMode: function (debug) {
- //invalid on html5
- },
- getSDKVersion: function () {
- return "unkown";
- },
- getPluginVersion: function () {
- return plugin.Version;
- }
-});
\ No newline at end of file
diff --git a/extensions/PluginX/plugins/SocialTwitter.js b/extensions/PluginX/plugins/SocialTwitter.js
deleted file mode 100644
index fc8ab38e6b..0000000000
--- a/extensions/PluginX/plugins/SocialTwitter.js
+++ /dev/null
@@ -1,34 +0,0 @@
-plugin.SocialTwitter = cc.Class.extend({
- _shareInfo: null,
-
- /**
- methods of protocol : InterfaceSocial
- */
- init: function () {
- this._shareInfo = {
- 'appkey': 12345678,
- 'title': "Hello, Cocos2d-html5!",
- 'url': window.location.href,
- 'pic': null
- };
- },
- configDeveloperInfo: function (cpInfo) {
- this._shareInfo.appkey = cpInfo["WeiboAppKey"];
- },
- share: function (shareInfo) {
- this._shareInfo.title = shareInfo["SharedText"];
- this._shareInfo.pic = shareInfo["SharedImagePath"];
-
-
- cc.Browser.openURL("http://twitter.com/intent/tweet?text=" + this._shareInfo.title + " " + this._shareInfo.url);
- },
- setDebugMode: function (debug) {
- //invalid on html5
- },
- getSDKVersion: function () {
- return "20130607";
- },
- getPluginVersion: function () {
- return plugin.Version;
- }
-});
\ No newline at end of file
diff --git a/extensions/PluginX/plugins/SocialWeibo.js b/extensions/PluginX/plugins/SocialWeibo.js
deleted file mode 100644
index 210a1bc242..0000000000
--- a/extensions/PluginX/plugins/SocialWeibo.js
+++ /dev/null
@@ -1,41 +0,0 @@
-plugin.SocialWeibo = cc.Class.extend({
- _shareInfo: null,
-
- /**
- methods of protocol : InterfaceSocial
- */
- init: function () {
- this._shareInfo = {
- 'appkey': 12345678,
- 'title': "Hello, Cocos2d-html5!",
- 'url': window.location.href,
- 'pic': null
- };
- },
- configDeveloperInfo: function (cpInfo) {
- this._shareInfo.appkey = cpInfo["WeiboAppKey"];
- },
- share: function (shareInfo) {
- this._shareInfo.title = shareInfo["SharedText"];
- this._shareInfo.pic = shareInfo["SharedImagePath"];
-
- var urlstring = "?", value;
- for (var key in this._shareInfo) {
- value = this._shareInfo[key];
- if (value) {
- urlstring += encodeURI(key + "=" + value) + "&";
- }
- }
- urlstring = urlstring.substr(0, urlstring.length - 1);
- cc.Browser.openURL("http://v.t.sina.com.cn/share/share.php?" + urlstring);
- },
- setDebugMode: function (debug) {
- //invalid on html5
- },
- getSDKVersion: function () {
- return "2.0";
- },
- getPluginVersion: function () {
- return plugin.Version;
- }
-});
\ No newline at end of file
diff --git a/extensions/PluginX/protocols/Config.js b/extensions/PluginX/protocols/Config.js
deleted file mode 100644
index 94f63fc279..0000000000
--- a/extensions/PluginX/protocols/Config.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/****************************************************************************
- Copyright (c) 2012+2013 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-/**
- * @namespace
- */
-var plugin = plugin || {};
-
-plugin.Version = "0.2.0";
-
-/**
- * plugin param
- * @type {Object}
- */
-plugin.PluginParam = function(type, value){
- var paramType = plugin.PluginParam.ParamType,tmpValue;
- switch(type){
- case paramType.TypeInt:
- tmpValue = parseInt(value);
- break;
- case paramType.TypeFloat:
- tmpValue = parseFloat(value);
- break;
- case paramType.TypeBool:
- tmpValue = Boolean(value);
- break;
- case paramType.TypeString:
- tmpValue = String(value);
- break;
- case paramType.TypeStringMap:
- tmpValue = JSON.stringify(value);
- break;
- default:
- tmpValue = value;
- }
- return tmpValue
-};
-
-plugin.PluginParam.ParamType = {
- TypeInt:1,
- TypeFloat:2,
- TypeBool:3,
- TypeString:4,
- TypeStringMap:5
-};
-
-plugin.PluginParam.AdsResultCode = {
- AdsReceived:0,
- FullScreenViewShown:1,
- FullScreenViewDismissed:2,
- PointsSpendSucceed:3,
- PointsSpendFailed:4,
- NetworkError:5,
- UnknownError:6
-};
-
-plugin.PluginParam.PayResultCode = {
- PaySuccess:0,
- PayFail:1,
- PayCancel:2,
- PayTimeOut:3
-};
-
-plugin.PluginParam.ShareResultCode = {
- ShareSuccess:0,
- ShareFail:1,
- ShareCancel:2,
- ShareTimeOut:3
-};
diff --git a/extensions/PluginX/protocols/PluginFactory.js b/extensions/PluginX/protocols/PluginFactory.js
deleted file mode 100644
index bb3e217e87..0000000000
--- a/extensions/PluginX/protocols/PluginFactory.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
- Copyright (c) 2012+2013 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-plugin.PluginType = {
- ADS:["AdSense"],
- ANALYTICS:["AdsGoogle"],
- IAP:[""],
- SOCIAL:["SocialTwitter","SocialFacebook","SocialQzone","SocialQQWeibo","SocialWeibo"]
-};
-
-/**
- * Plugin Factory
- * @extend cc.Class
- * @class
- */
-plugin.PluginFactory = cc.Class.extend({
- /**
- * create the plugin by name
- */
- createPlugin:function (name) {
- if (name == null || name.length == 0) return null;
-
- var ret;
- var obj = new plugin[name]();
- obj.init();
-
- switch (name) {
- case plugin.PluginType.ADS[0]:
- ret = new plugin.ProtocolAds();
- break;
- case plugin.PluginType.ANALYTICS:
- ret = new plugin.ProtocolAnalytics();
- break;
- case plugin.PluginType.IAP:
- ret = new plugin.ProtocolIAP();
- break;
- case plugin.PluginType.SOCIAL[0]:
- case plugin.PluginType.SOCIAL[1]:
- case plugin.PluginType.SOCIAL[2]:
- case plugin.PluginType.SOCIAL[3]:
- case plugin.PluginType.SOCIAL[4]:
- ret = new plugin.ProtocolSocial();
- break;
- default:
- throw "Plugin " + name + " not implements a right protocol";
-
- }
-
- if (ret !== null) {
- ret.setPluginName(name);
- plugin.PluginUtils.initPlugin(ret, obj, name);
- }
- return ret;
- }
-});
-
-/**
- * Get singleton of PluginFactory
- */
-plugin.PluginFactory.getInstance = function () {
- if (!this._instnace) {
- this._instnace = new plugin.PluginFactory();
- }
- return this._instnace;
-};
-
-/**
- * Destory the instance of PluginFactory
- */
-plugin.PluginFactory.purgeFactory = function () {
- if (this._instnace) {
- delete this._instnace;
- }
-};
\ No newline at end of file
diff --git a/extensions/PluginX/protocols/PluginManager.js b/extensions/PluginX/protocols/PluginManager.js
deleted file mode 100644
index e16a30bc1f..0000000000
--- a/extensions/PluginX/protocols/PluginManager.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
- Copyright (c) 2012+2013 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-var plugin = plugin || {};
-
-/**
- * @class plugin.PluginManager
- */
-plugin.PluginManager = cc.Class.extend({
- _pluginsMap:null,
-
- ctor:function(){
- this._pluginsMap = {};
- },
- /**
- * unload the plugin by name
- * @param {String} name
- */
- unloadPlugin:function (name) {
- if (name == null || name.length == 0) return;
- if (this._pluginsMap.hasOwnProperty(name)) {
- delete this._pluginsMap[name];
- }
-
- },
-
- /**
- * load the plugin by name
- * @param {String} name
- * @return {plugin.PluginProtocol||null}
- */
- loadPlugin:function (name) {
- if (name == null || name.length == 0) return null;
-
- var tmpPlugin;
- if (this._pluginsMap.hasOwnProperty(name)) {
- tmpPlugin = this._pluginsMap[name];
- }
- else {
- tmpPlugin = plugin.PluginFactory.getInstance().createPlugin(name);
- this._pluginsMap[name] = tmpPlugin;
- }
-
- return tmpPlugin;
- }
-});
-
-/**
- * Get singleton of PluginManager
- * @return {plugin.PluginManager}
- */
-plugin.PluginManager.getInstance = function () {
- if (!this._instance) {
- this._instance = new plugin.PluginManager();
- }
- return this._instance;
-};
-
-/**
- * Destory the instance of PluginManager
- */
-plugin.PluginManager.end = function () {
- if (this._instance != null) {
- delete this._instance;
- }
-};
\ No newline at end of file
diff --git a/extensions/PluginX/protocols/PluginProtocol.js b/extensions/PluginX/protocols/PluginProtocol.js
deleted file mode 100644
index 5d3354dafd..0000000000
--- a/extensions/PluginX/protocols/PluginProtocol.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
- Copyright (c) 2012+2013 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-/**
- * @class PluginProtocol
- */
-plugin.PluginProtocol = cc.Class.extend({
- _pluginName:null,
-
- setPluginName:function (name) {
- this._pluginName = name;
- },
- getPluginName:function () {
- return this._pluginName;
- },
-
- /**
- * plug-in info methods(name, version, SDK version)
- */
- getPluginVersion:function () {
- var verName;
-
- var data = plugin.PluginUtils.getPluginData(this);
- if (data) {
- var obj = data.obj;
- verName = obj.getPluginVersion();
- } else {
- throw "Plugin " + this.getPluginName() + " not right initilized";
- }
-
- return verName;
- },
-
- /**
- * @method getSDKVersion
- * @return A value converted from C/C++ "const char*"
- */
- getSDKVersion:function () {
- var verName;
-
- var data = plugin.PluginUtils.getPluginData(this);
- if (data) {
- var pOCObj = data.obj;
- verName = pOCObj.getSDKVersion();
- } else {
- throw ("Plugin "+this.getPluginName()+" not right initilized");
- }
-
- return verName;
- },
-
- /**
- * switch debug plug-in on/off
- * @param {Boolean} debug
- */
- setDebugMode:function (debug) {
- /*NSNumber* debug = [NSNumber numberWithBool:isDebugMode];
- plugin.PluginUtils.callOCFunctionWithName_oneParam(this, "setDebugMode", debug);*/
-
- },
-
- /**
- * methods for reflections
- */
- callFuncWithParam:function (funcName, param) {
- },
-
- callStringFuncWithParam:function (funcName, param) {
- },
-
- callIntFuncWithParam:function (funcName, param) {
- },
-
- callBoolFuncWithParam:function (funcName, param) {
- },
-
- callFloatFuncWithParam:function (funcName, param) {
- }
-
-});
\ No newline at end of file
diff --git a/extensions/PluginX/protocols/PluginUtils.js b/extensions/PluginX/protocols/PluginUtils.js
deleted file mode 100644
index 94d066c576..0000000000
--- a/extensions/PluginX/protocols/PluginUtils.js
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
- Copyright (c) 2012+2013 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-
-plugin.PluginData = function (obj, className) {
- this.obj = obj;
- this.className = className;
-};
-
-plugin.PluginUtils = {
- _objMap:{},
- _pluginMap:{},
- initPlugin: function (tmpPlugin, obj, className) {
- var data = new plugin.PluginData(obj,className);
- this.setPluginData(tmpPlugin, data);
- },
-
- getPluginData: function (keyObj) {
- return this._objMap[keyObj._pluginName];
- },
-
- setPluginData: function (plugin, data) {
- this.erasePluginData(plugin);
- this._objMap[data.className] = data;
- this._pluginMap[data.className] = plugin;
- },
-
- erasePluginData: function (keyObj) {
- var data = this._objMap[keyObj];
- if(data){
- var key = data.className;
-
- var pluginIt = this._pluginMap[key];
- if (pluginIt)
- {
- delete this._pluginMap[key];
- }
-
- delete this._objMap[keyObj]
- }
- },
-
- getPluginPtr: function (obj) {
- return this._pluginMap[obj.className];
- },
-
- getObjFromParam: function (param) {
-
- },
-
- createDictFromMap: function (paramMap) {
- return paramMap;
- },
-
- /**
- @brief method don't have return value
- */
- callOCFunctionWithName_oneParam: function (tmpPlugin, funcName, param) {
-
- },
- callOCFunctionWithName: function (tmpPlugin, funcName) {
- },
-
- /**
- @brief method return int value
- */
- callOCIntFunctionWithName_oneParam: function (tmpPlugin, funcName, param) {
- },
- callOCIntFunctionWithName: function (tmpPlugin, funcName) {
- },
-
- /**
- @brief method return float value
- */
- callOCFloatFunctionWithName_oneParam: function (tmpPlugin, funcName, param) {
- },
- callOCFloatFunctionWithName: function (tmpPlugin, funcName) {
- },
-
- /**
- @brief method return bool value
- */
- callOCBoolFunctionWithName_oneParam: function (tmpPlugin, funcName, param) {
- },
- callOCBoolFunctionWithName: function (tmpPlugin, funcName) {
- },
-
- /**
- @brief method return string value
- */
- callOCStringFunctionWithName_oneParam: function (tmpPlugin, funcName, param) {
- },
- callOCStringFunctionWithName: function (tmpPlugin, funcName) {
- },
-
- callRetFunctionWithParam: function (tmpPlugin, funcName, param) {
- },
- callRetFunction: function (tmpPlugin, funcName) {
- }
-};
\ No newline at end of file
diff --git a/extensions/PluginX/protocols/ProtocolSocial.js b/extensions/PluginX/protocols/ProtocolSocial.js
deleted file mode 100644
index 1de0d75bea..0000000000
--- a/extensions/PluginX/protocols/ProtocolSocial.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/****************************************************************************
- Copyright (c) 2012+2013 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-plugin.ShareResultCode = {
- Success: 0,
- Fail: 1,
- Cancel: 2,
- TimeOut: 3
-};
-
-plugin.ShareResultListener = cc.Class.extend({
- onShareResult: function (ret, msg) {
-
- }
-});
-
-/**
- * @class ProtocolSocial
- */
-plugin.ProtocolSocial = plugin.PluginProtocol.extend({
-
- /**
- * share result callback
- * @param {Number} ret
- * @param {String} msg
- */
- onShareResult: function (ret, msg) {
- if (this._listener) {
- this._listener.onShareResult(ret, msg);
- }
- else {
- cc.log("Share result listener of " + this.getPluginName() + " is null!");
- }
- cc.log("Share result of " + this.getPluginName() + " is : " + ret + msg);
- },
-
- /**
- * set the result listener
- * @param {Function} listener The callback object for share result
- */
- setResultListener: function (listener) {
- this._listener = listener;
- },
-
- /**
- * share information
- * @param {Object} info The info of share, contains key:
- * SharedText The text need to share
- * SharedImagePath The full path of image file need to share (optinal)
- * SharedURL url of the site
- */
- share: function (info) {
- if (Object.keys(info).length == 0) {
- if (null != this._listener) {
- this.onShareResult(plugin.ShareResultCode.Fail, "Share info error");
- }
- cc.log("The Share info of " + this.getPluginName() + " is empty!");
- }
- else {
- var data = plugin.PluginUtils.getPluginData(this);
- var obj = data.obj;
- obj.share(info);
- }
- },
-
- /**
- * config the social developer info
- * @param {Object} devInfo This parameter is the info of developer,different plugin have different format
- */
- configDeveloperInfo: function (devInfo) {
- if (Object.keys(devInfo).length == 0) {
- cc.log("The developer info is empty for " + this.getPluginName());
- }
- else {
- var data = plugin.PluginUtils.getPluginData(this);
- var obj = data.obj;
- obj.configDeveloperInfo(devInfo);
- }
- },
-
- setDebugMode:function(value){
- //invalid on html5
- }
-});
diff --git a/extensions/PluginX/samples/HelloSocial/cocos2d.js b/extensions/PluginX/samples/HelloSocial/cocos2d.js
deleted file mode 100644
index 851a010f79..0000000000
--- a/extensions/PluginX/samples/HelloSocial/cocos2d.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
-
- 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.
- ****************************************************************************/
-(function () {
- var d = document;
- var c = {
- COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
- box2d:false,
- chipmunk:false,
- showFPS:true,
- loadExtension:false,
- loadPluginx:true,
- frameRate:60,
- tag:'gameCanvas', //the dom element to run cocos2d on
- engineDir:'../../../../cocos2d/',
- //SingleEngineFile:'',
- appFiles:[
- 'src/resource.js',
- 'src/MySocialManager.js',
- 'src/myApp.js'//add your own files in order here
- ]
- };
-
- if(!d.createElement('canvas').getContext){
- var s = d.createElement('div');
- s.innerHTML = 'Your browser does not support HTML5 canvas! ' +
- 'Google Chrome is a browser that combines a minimal design with sophisticated technology to make the web faster, safer, and easier.Click the logo to download.
' +
- ' ';
- var p = d.getElementById(c.tag).parentNode;
- p.style.background = 'none';
- p.style.border = 'none';
- p.insertBefore(s);
-
- d.body.style.background = '#ffffff';
- return;
- }
-
-
- window.addEventListener('DOMContentLoaded', function () {
- this.removeEventListener('DOMContentLoaded', arguments.callee, false);
- //first load engine file if specified
- var s = d.createElement('script');
- /*********Delete this section if you have packed all files into one*******/
- if (c.SingleEngineFile && !c.engineDir) {
- s.src = c.SingleEngineFile;
- }
- else if (c.engineDir && !c.SingleEngineFile) {
- s.src = c.engineDir + 'platform/jsloader.js';
- }
- else {
- alert('You must specify either the single engine file OR the engine directory in "cocos2d.js"');
- }
- /*********Delete this section if you have packed all files into one*******/
-
- //s.src = 'myTemplate.js'; //IMPORTANT: Un-comment this line if you have packed all files into one
-
- d.body.appendChild(s);
- document.ccConfig = c;
- s.id = 'cocos2d-html5';
- //else if single file specified, load singlefile
- });
-})();
diff --git a/extensions/PluginX/samples/HelloSocial/index.html b/extensions/PluginX/samples/HelloSocial/index.html
deleted file mode 100644
index 6b4cece82c..0000000000
--- a/extensions/PluginX/samples/HelloSocial/index.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- Cocos2d-html5 Hello World test
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/extensions/PluginX/samples/HelloSocial/main.js b/extensions/PluginX/samples/HelloSocial/main.js
deleted file mode 100644
index 3f549e0e22..0000000000
--- a/extensions/PluginX/samples/HelloSocial/main.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
-
- 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.
- ****************************************************************************/
-var cocos2dApp = cc.Application.extend({
- config:document['ccConfig'],
- ctor:function (scene) {
- this._super();
- this.startScene = scene;
- cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
- cc.initDebugSetting();
- cc.setup(this.config['tag']);
- cc.AppController.shareAppController().didFinishLaunchingWithOptions();
- },
- applicationDidFinishLaunching:function () {
- // initialize director
- var director = cc.Director.getInstance();
- var designSize = cc.size(800, 450);
-
- cc.EGLView.getInstance().setDesignResolutionSize(designSize.width, designSize.height, cc.RESOLUTION_POLICY.SHOW_ALL);
-
- // turn on display FPS
- director.setDisplayStats(this.config['showFPS']);
-
- // set FPS. the default value is 1.0/60 if you don't call this
- director.setAnimationInterval(1.0 / this.config['frameRate']);
-
- //load resources
- cc.LoaderScene.preload(g_ressources, function () {
- director.replaceScene(new this.startScene());
- }, this);
-
- return true;
- }
-});
-
-var myApp = new cocos2dApp(MyScene);
\ No newline at end of file
diff --git a/extensions/PluginX/samples/HelloSocial/res/CloseNormal.png b/extensions/PluginX/samples/HelloSocial/res/CloseNormal.png
deleted file mode 100755
index 8ff9369dc9..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/CloseNormal.png and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/res/CloseSelected.png b/extensions/PluginX/samples/HelloSocial/res/CloseSelected.png
deleted file mode 100755
index f75c4179a5..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/CloseSelected.png and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/res/background.png b/extensions/PluginX/samples/HelloSocial/res/background.png
deleted file mode 100755
index b2e4ae6ce8..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/background.png and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/res/facebook.gif b/extensions/PluginX/samples/HelloSocial/res/facebook.gif
deleted file mode 100644
index 2e622c197d..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/facebook.gif and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/res/qqweibo.gif b/extensions/PluginX/samples/HelloSocial/res/qqweibo.gif
deleted file mode 100644
index bf50564745..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/qqweibo.gif and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/res/qzone.gif b/extensions/PluginX/samples/HelloSocial/res/qzone.gif
deleted file mode 100644
index 2b44da927b..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/qzone.gif and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/res/snweibo.gif b/extensions/PluginX/samples/HelloSocial/res/snweibo.gif
deleted file mode 100644
index b6f19eabbb..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/snweibo.gif and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/res/twitter.gif b/extensions/PluginX/samples/HelloSocial/res/twitter.gif
deleted file mode 100644
index 72b0f30838..0000000000
Binary files a/extensions/PluginX/samples/HelloSocial/res/twitter.gif and /dev/null differ
diff --git a/extensions/PluginX/samples/HelloSocial/src/MySocialManager.js b/extensions/PluginX/samples/HelloSocial/src/MySocialManager.js
deleted file mode 100644
index 44ef5c6c71..0000000000
--- a/extensions/PluginX/samples/HelloSocial/src/MySocialManager.js
+++ /dev/null
@@ -1,120 +0,0 @@
-var MyShareMode = {
- NoneMode:0,
- SNWeibo:1,
- QQWeibo:2,
- QZone:3,
- Twitter:4,
- Facebook:5
-};
-
-
-var MyShareResult = plugin.ShareResultListener.extend({
- onShareResult: function (ret, msg) {
- var shareStatus = "Share " + (ret == plugin.ShareResultCode.Success) ? " Successed" : " Failed";
- cc.log(msg + shareStatus);
- }
-});
-
-var MySocialManager = cc.Class.extend({
- _twitter:null,
- _snweibo:null,
- _qqweibo:null,
- _qzone:null,
- _facebook:null,
- _listener:null,
- ctor:function () {
- window.test = this;
- },
- unloadSocialPlugin:function () {
- if (this._twitter) {
- plugin.PluginManager.getInstance().unloadPlugin("SocialTwitter");
- this._twitter = null;
- }
-
- if (this._weibo) {
- plugin.PluginManager.getInstance().unloadPlugin("SocialWeibo");
- this._weibo = null;
- }
- },
- loadSocialPlugin:function () {
- if (this._listener == null) {
- this._listener = new MyShareResult();
- }
-
- this._snweibo = plugin.PluginManager.getInstance().loadPlugin("SocialWeibo");
- if (this._snweibo) {
- var weiboInfo = {};
- weiboInfo["WeiboAppKey"] = "3787440247";
-
- if (Object.keys(weiboInfo).length == 0) {
- cc.log("Developer info is empty. PLZ fill your weibo info in weiboInfo");
- }
-
- this._snweibo.setDebugMode(true);
- this._snweibo.configDeveloperInfo(weiboInfo);
- this._snweibo.setResultListener(this._listener);
- }
-
- this._qqweibo = plugin.PluginManager.getInstance().loadPlugin("SocialQQWeibo");
- if (this._qqweibo) {
- var qqweiboInfo = {};
- qqweiboInfo["QQWeiboAppKey"] = "b3410a01f51da238afdc92ea6e2c267a";
-
- if (Object.keys(qqweiboInfo).length == 0) {
- cc.log("Developer info is empty. PLZ fill your weibo info in qqweiboInfo");
- }
-
- this._qqweibo.setDebugMode(true);
- this._qqweibo.configDeveloperInfo(qqweiboInfo);
- this._qqweibo.setResultListener(this._listener);
- }
-
- this._qzone = plugin.PluginManager.getInstance().loadPlugin("SocialQzone");
- this._twitter = plugin.PluginManager.getInstance().loadPlugin("SocialTwitter");
- this._facebook = plugin.PluginManager.getInstance().loadPlugin("SocialFacebook");
-
- window.test = this;
-
- },
- shareByMode:function (info, mode) {
- var share = null;
- switch (mode) {
- case MyShareMode.SNWeibo:
- share = this._snweibo;
- break;
- case MyShareMode.QQWeibo:
- share = this._qqweibo;
- break;
- case MyShareMode.QZone:
- share = this._qzone;
- break;
- case MyShareMode.Twitter:
- share = this._twitter;
- break;
- case MyShareMode.Facebook:
- share = this._facebook;
- break;
- default:
- break;
- }
-
-
- if (share) {
- share.share(info);
- }
- }
-});
-
-MySocialManager.getInstance = function () {
- if (!this._instance) {
- this._instance = new MySocialManager();
- }
- return this._instance;
-};
-
-MySocialManager.purgeManager = function () {
- if (this._instance) {
- this._instance = null;
- delete this._instance;
- }
-};
\ No newline at end of file
diff --git a/extensions/PluginX/samples/HelloSocial/src/myApp.js b/extensions/PluginX/samples/HelloSocial/src/myApp.js
deleted file mode 100644
index 3cf18075ce..0000000000
--- a/extensions/PluginX/samples/HelloSocial/src/myApp.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
- 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.
- ****************************************************************************/
-
-var TAG_SHARE_BY_SNWEIBO = 100;
-var TAG_SHARE_BY_QQWEIBO = 101;
-var TAG_SHARE_BY_QZONE = 102;
-var TAG_SHARE_BY_TWWITER = 103;
-var TAG_SHARE_BY_FACEBOOK = 104;
-
-var EventMenuItem = function (id, tag) {
- this.id = id;
- this.tag = tag;
-};
-
-var s_EventMenuItem = [
- new EventMenuItem(s_snweibo, TAG_SHARE_BY_SNWEIBO),
- new EventMenuItem(s_qqweibo, TAG_SHARE_BY_QQWEIBO),
- new EventMenuItem(s_qzone, TAG_SHARE_BY_QZONE),
- new EventMenuItem(s_twitter, TAG_SHARE_BY_TWWITER),
- new EventMenuItem(s_facebook, TAG_SHARE_BY_FACEBOOK)
-];
-
-var MyLayer = cc.Layer.extend({
- init: function () {
- this._super();
-
-
- var size = cc.Director.getInstance().getVisibleSize();
-
- var bg = cc.Sprite.create(s_Background);
- bg.setPosition(cc.p(size.width / 2, size.height / 2));
- this.addChild(bg);
-
- var eglView = cc.EGLView.getInstance();
- var posBR = cc.p(eglView.getVisibleOrigin().x + eglView.getVisibleSize().width, eglView.getVisibleOrigin().y);
- var posBC = cc.p(eglView.getVisibleOrigin().x + eglView.getVisibleSize().width / 2, eglView.getVisibleOrigin().y);
- var posTL = cc.p(eglView.getVisibleOrigin().x, eglView.getVisibleOrigin().y + eglView.getVisibleSize().height);
-
- var closeItem = cc.MenuItemImage.create(
- s_CloseNormal,
- s_CloseSelected,
- this.menuCloseCallback,
- this);
- closeItem.setPosition(cc.p(posBR.x - 20, posBR.y + 20));
-
- // create menu, it's an autorelease object
- var pMenu = cc.Menu.create(closeItem);
- pMenu.setPosition(cc.p(0, 0));
- this.addChild(pMenu, 1);
-
- var posStep = cc.p(150, -150);
- var beginPos = cc.pAdd(posTL, cc.pMult(posStep, 0.5));
- var line = 0;
- var row = 0;
- for (var i = 0; i < s_EventMenuItem.length; i++) {
- var menuItem = cc.MenuItemImage.create(s_EventMenuItem[i].id, s_EventMenuItem[i].id,
- this.eventMenuCallback, this);
- pMenu.addChild(menuItem, 0, s_EventMenuItem[i].tag);
-
- var pos = cc.pAdd(beginPos, cc.p(posStep.x * row, posStep.y * line));
- var itemSize = menuItem.getContentSize();
- if ((pos.x + itemSize.width / 2) > posBR.x) {
- line += 1;
- row = 0;
- pos = cc.pAdd(beginPos, cc.p(posStep.x * row, posStep.y * line));
- }
- row += 1;
- menuItem.setPosition(pos);
- }
-
- var label = cc.LabelTTF.create("Reload all plugins", "Arial", 24);
- var menuItem = cc.MenuItemLabel.create(label, this.reloadPluginMenuCallback, this);
- menuItem.setAnchorPoint(cc.p(0.5, 0));
- pMenu.addChild(menuItem, 0);
- menuItem.setPosition(posBC);
- },
- //a selector callback
- menuCloseCallback: function (sender) {
- MySocialManager.getInstance().unloadSocialPlugin();
- MySocialManager.getInstance().loadSocialPlugin();
- },
- eventMenuCallback: function (sender) {
- var info = {};
- info["SharedText"] = "Share message : HelloSocial!";
- info["SharedImagePath"] = "http://www.cocos2d-x.org/images/banner-left.png";
- info["SharedURLPath"] = "http://www.cocos2d-x.org";
-
- var mode = sender.getTag() - TAG_SHARE_BY_SNWEIBO + 1;
- MySocialManager.getInstance().shareByMode(info, mode);
- },
- reloadPluginMenuCallback: function (sender) {
- MySocialManager.purgeManager();
- }
-});
-
-var MyScene = cc.Scene.extend({
- onEnter: function () {
- this._super();
- var layer = new MyLayer();
- this.addChild(layer);
- layer.init();
- }
-});
diff --git a/extensions/PluginX/samples/HelloSocial/src/resource.js b/extensions/PluginX/samples/HelloSocial/src/resource.js
deleted file mode 100644
index e2b1500aa3..0000000000
--- a/extensions/PluginX/samples/HelloSocial/src/resource.js
+++ /dev/null
@@ -1,19 +0,0 @@
-var s_CloseNormal = "res/CloseNormal.png";
-var s_CloseSelected = "res/CloseSelected.png";
-var s_Background = "res/Background.png";
-var s_qzone = "res/qzone.gif";
-var s_snweibo = "res/snweibo.gif";
-var s_qqweibo = "res/qqweibo.gif";
-var s_facebook = "res/facebook.gif";
-var s_twitter = "res/twitter.gif";
-
-var g_ressources = [
- {src:s_CloseNormal},
- {src:s_CloseSelected},
- {src:s_Background},
- {src:s_qzone},
- {src:s_facebook},
- {src:s_twitter},
- {src:s_qqweibo},
- {src:s_snweibo}
-];
\ No newline at end of file
diff --git a/extensions/CCBReader/CCBAnimationManager.js b/extensions/ccb-reader/CCBAnimationManager.js
similarity index 62%
rename from extensions/CCBReader/CCBAnimationManager.js
rename to extensions/ccb-reader/CCBAnimationManager.js
index 0180bc60c0..54ab341f0c 100644
--- a/extensions/CCBReader/CCBAnimationManager.js
+++ b/extensions/ccb-reader/CCBAnimationManager.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -24,43 +24,48 @@
THE SOFTWARE.
****************************************************************************/
+(function () {
+
+var _pos = cc.p();
+
cc.BuilderAnimationManagerDelegate = cc.Class.extend({
- completedAnimationSequenceNamed:function (name) {}
+ completedAnimationSequenceNamed: function (name) {
+ }
});
cc.BuilderAnimationManager = cc.Class.extend({
- _sequences:null,
- _nodeSequences:null,
- _baseValues:null,
- _autoPlaySequenceId:0,
-
- _rootNode:null,
- _owner:null,
- _rootContainerSize:null,
-
- _delegate:null,
- _runningSequence:null,
-
- _documentOutletNames:null,
- _documentOutletNodes:null,
- _documentCallbackNames:null,
- _documentCallbackNodes:null,
- _documentCallbackControlEvents:null,
- _documentControllerName:"",
- _lastCompletedSequenceName:"",
- _keyframeCallbacks:null,
- _keyframeCallFuncs:null,
-
- _animationCompleteCallbackFunc:null,
- _target:null,
- _jsControlled:false,
-
- ctor:function () {
+ _sequences: null,
+ _nodeSequences: null,
+ _baseValues: null,
+ _autoPlaySequenceId: 0,
+
+ _rootNode: null,
+ _owner: null,
+ _rootContainerSize: null,
+
+ _delegate: null,
+ _runningSequence: null,
+
+ _documentOutletNames: null,
+ _documentOutletNodes: null,
+ _documentCallbackNames: null,
+ _documentCallbackNodes: null,
+ _documentCallbackControlEvents: null,
+ _documentControllerName: "",
+ _lastCompletedSequenceName: "",
+ _keyframeCallbacks: null,
+ _keyframeCallFuncs: null,
+
+ _animationCompleteCallbackFunc: null,
+ _target: null,
+ _jsControlled: false,
+
+ ctor: function () {
this._rootContainerSize = cc.size(0, 0);
this.init();
},
- init:function () {
+ init: function () {
this._sequences = [];
this._nodeSequences = new cc._Dictionary();
this._baseValues = new cc._Dictionary();
@@ -77,122 +82,122 @@ cc.BuilderAnimationManager = cc.Class.extend({
return true;
},
- getSequences:function () {
+ getSequences: function () {
return this._sequences;
},
- setSequences:function(seqs){
+ setSequences: function (seqs) {
this._sequences = seqs;
},
- getAutoPlaySequenceId:function () {
+ getAutoPlaySequenceId: function () {
return this._autoPlaySequenceId;
},
- setAutoPlaySequenceId:function (autoPlaySequenceId) {
+ setAutoPlaySequenceId: function (autoPlaySequenceId) {
this._autoPlaySequenceId = autoPlaySequenceId;
},
- getRootNode:function () {
+ getRootNode: function () {
return this._rootNode;
},
- setRootNode:function (rootNode) {
+ setRootNode: function (rootNode) {
this._rootNode = rootNode;
},
- getOwner:function () {
+ getOwner: function () {
return this._owner;
},
- setOwner:function (owner) {
+ setOwner: function (owner) {
this._owner = owner;
},
- addDocumentCallbackNode:function(node){
+ addDocumentCallbackNode: function (node) {
this._documentCallbackNodes.push(node);
},
- addDocumentCallbackName:function(name){
+ addDocumentCallbackName: function (name) {
this._documentCallbackNames.push(name);
},
- addDocumentCallbackControlEvents:function(controlEvents){
+ addDocumentCallbackControlEvents: function (controlEvents) {
this._documentCallbackControlEvents.push(controlEvents);
},
- addDocumentOutletNode:function(node){
+ addDocumentOutletNode: function (node) {
this._documentOutletNodes.push(node);
},
- addDocumentOutletName:function(name){
+ addDocumentOutletName: function (name) {
this._documentOutletNames.push(name);
},
- setDocumentControllerName:function(name){
+ setDocumentControllerName: function (name) {
this._documentControllerName = name;
},
- getDocumentControllerName:function(){
+ getDocumentControllerName: function () {
return this._documentControllerName;
},
- getDocumentCallbackNames:function(){
+ getDocumentCallbackNames: function () {
return this._documentCallbackNames;
},
- getDocumentCallbackNodes:function(){
+ getDocumentCallbackNodes: function () {
return this._documentCallbackNodes;
},
- getDocumentCallbackControlEvents:function(){
+ getDocumentCallbackControlEvents: function () {
return this._documentCallbackControlEvents;
},
- getDocumentOutletNames:function(){
+ getDocumentOutletNames: function () {
return this._documentOutletNames;
},
- getDocumentOutletNodes:function(){
+ getDocumentOutletNodes: function () {
return this._documentOutletNodes;
},
- getLastCompletedSequenceName:function(){
+ getLastCompletedSequenceName: function () {
return this._lastCompletedSequenceName;
},
- getKeyframeCallbacks:function(){
+ getKeyframeCallbacks: function () {
return this._keyframeCallbacks;
},
- getRootContainerSize:function () {
+ getRootContainerSize: function () {
return this._rootContainerSize;
},
- setRootContainerSize:function (rootContainerSize) {
+ setRootContainerSize: function (rootContainerSize) {
this._rootContainerSize = cc.size(rootContainerSize.width, rootContainerSize.height);
},
- getDelegate:function () {
+ getDelegate: function () {
return this._delegate;
},
- setDelegate:function (delegate) {
+ setDelegate: function (delegate) {
this._delegate = delegate;
},
- getRunningSequenceName:function () {
- if(this._runningSequence)
+ getRunningSequenceName: function () {
+ if (this._runningSequence)
return this._runningSequence.getName();
return null;
},
- getContainerSize:function (node) {
+ getContainerSize: function (node) {
if (node)
return node.getContentSize();
else
return this._rootContainerSize;
},
- addNode:function (node, seq) {
+ addNode: function (node, seq) {
this._nodeSequences.setObject(seq, node);
},
- setBaseValue:function (value, node, propName) {
+ setBaseValue: function (value, node, propName) {
var props = this._baseValues.objectForKey(node);
if (!props) {
props = new cc._Dictionary();
@@ -201,11 +206,11 @@ cc.BuilderAnimationManager = cc.Class.extend({
props.setObject(value, propName);
},
- moveAnimationsFromNode:function(fromNode,toNode){
+ moveAnimationsFromNode: function (fromNode, toNode) {
// Move base values
var locBaseValues = this._baseValues;
var baseValue = locBaseValues.objectForKey(fromNode);
- if(baseValue != null) {
+ if (baseValue !== null) {
locBaseValues.setObject(baseValue, toNode);
locBaseValues.removeObjectForKey(fromNode);
}
@@ -213,13 +218,13 @@ cc.BuilderAnimationManager = cc.Class.extend({
// Move seqs
var locNodeSequences = this._nodeSequences;
var seqs = locNodeSequences.objectForKey(fromNode);
- if(seqs != null) {
+ if (seqs != null) {
locNodeSequences.setObject(seqs, toNode);
locNodeSequences.removeObjectForKey(fromNode);
}
},
- getActionForCallbackChannel:function(channel) {
+ getActionForCallbackChannel: function (channel) {
var lastKeyframeTime = 0;
var actions = [];
@@ -230,51 +235,49 @@ cc.BuilderAnimationManager = cc.Class.extend({
var keyframe = keyframes[i];
var timeSinceLastKeyframe = keyframe.getTime() - lastKeyframeTime;
lastKeyframeTime = keyframe.getTime();
- if(timeSinceLastKeyframe > 0) {
- actions.push(cc.DelayTime.create(timeSinceLastKeyframe));
+ if (timeSinceLastKeyframe > 0) {
+ actions.push(cc.delayTime(timeSinceLastKeyframe));
}
var keyVal = keyframe.getValue();
var selectorName = keyVal[0];
var selectorTarget = keyVal[1];
- if(this._jsControlled) {
+ if (this._jsControlled) {
var callbackName = selectorTarget + ":" + selectorName; //add number to the stream
var callback = this._keyframeCallFuncs[callbackName];
- if(callback != null)
+ if (callback != null)
actions.push(callback);
} else {
var target;
- if(selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT)
+ if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT)
target = this._rootNode;
- else if (selectorTarget == CCB_TARGETTYPE_OWNER)
+ else if (selectorTarget === CCB_TARGETTYPE_OWNER)
target = this._owner;
- if(target != null) {
- if(selectorName.length > 0) {
+ if (target != null) {
+ if (selectorName.length > 0) {
var selCallFunc = 0;
- var targetAsCCBSelectorResolver = target;
-
- if(target.onResolveCCBCCCallFuncSelector != null)
- selCallFunc = targetAsCCBSelectorResolver.onResolveCCBCCCallFuncSelector(target, selectorName);
- if(selCallFunc == 0)
+ if (target.onResolveCCBCCCallFuncSelector != null)
+ selCallFunc = target.onResolveCCBCCCallFuncSelector(target, selectorName);
+ if (selCallFunc === 0)
cc.log("Skipping selector '" + selectorName + "' since no CCBSelectorResolver is present.");
else
- actions.push(cc.CallFunc.create(selCallFunc,target));
+ actions.push(cc.callFunc(selCallFunc, target));
} else {
cc.log("Unexpected empty selector.");
}
}
}
}
- if(actions.length < 1)
+ if (actions.length < 1)
return null;
- return cc.Sequence.create(actions);
+ return cc.sequence(actions);
},
- getActionForSoundChannel:function(channel) {
+ getActionForSoundChannel: function (channel) {
var lastKeyframeTime = 0;
var actions = [];
@@ -285,8 +288,8 @@ cc.BuilderAnimationManager = cc.Class.extend({
var keyframe = keyframes[i];
var timeSinceLastKeyframe = keyframe.getTime() - lastKeyframeTime;
lastKeyframeTime = keyframe.getTime();
- if(timeSinceLastKeyframe > 0) {
- actions.push(cc.DelayTime.create(timeSinceLastKeyframe));
+ if (timeSinceLastKeyframe > 0) {
+ actions.push(cc.delayTime(timeSinceLastKeyframe));
}
var keyVal = keyframe.getValue();
@@ -295,29 +298,29 @@ cc.BuilderAnimationManager = cc.Class.extend({
actions.push(cc.BuilderSoundEffect.create(soundFile, pitch, pan, gain));
}
- if(actions.length < 1)
+ if (actions.length < 1)
return null;
- return cc.Sequence.create(actions);
+ return cc.sequence(actions);
},
- runAnimationsForSequenceNamed:function(name){
+ runAnimationsForSequenceNamed: function (name) {
this.runAnimationsForSequenceIdTweenDuration(this._getSequenceId(name), 0);
},
- runAnimationsForSequenceNamedTweenDuration:function(name, tweenDuration){
- this.runAnimationsForSequenceIdTweenDuration(this._getSequenceId(name), tweenDuration);
+ runAnimationsForSequenceNamedTweenDuration: function (name, tweenDuration) {
+ this.runAnimationsForSequenceIdTweenDuration(this._getSequenceId(name), tweenDuration);
},
- runAnimationsForSequenceIdTweenDuration:function(nSeqId, tweenDuration){
+ runAnimationsForSequenceIdTweenDuration: function (nSeqId, tweenDuration) {
+ if (nSeqId === -1)
+ throw new Error("cc.BuilderAnimationManager.runAnimationsForSequenceIdTweenDuration(): Sequence id should not be -1");
tweenDuration = tweenDuration || 0;
- cc.Assert(nSeqId != -1, "Sequence id couldn't be found");
-
this._rootNode.stopAllActions();
var allKeys = this._nodeSequences.allKeys();
- for(var i = 0,len = allKeys.length ; i< len;i++){
+ for (var i = 0, len = allKeys.length; i < len; i++) {
var node = allKeys[i];
node.stopAllActions();
@@ -325,27 +328,27 @@ cc.BuilderAnimationManager = cc.Class.extend({
var seqNodeProps = seqs.objectForKey(nSeqId);
var j;
var seqNodePropNames = [];
- if(seqNodeProps){
+ if (seqNodeProps) {
var propKeys = seqNodeProps.allKeys();
- for(j = 0; j < propKeys.length; j++){
+ for (j = 0; j < propKeys.length; j++) {
var propName = propKeys[j];
var seqProp = seqNodeProps.objectForKey(propName);
seqNodePropNames.push(propName);
- this._setFirstFrame(node, seqProp,tweenDuration);
- this._runAction(node,seqProp,tweenDuration);
+ this._setFirstFrame(node, seqProp, tweenDuration);
+ this._runAction(node, seqProp, tweenDuration);
}
}
var nodeBaseValues = this._baseValues.objectForKey(node);
- if(nodeBaseValues){
+ if (nodeBaseValues) {
var baseKeys = nodeBaseValues.allKeys();
- for(j = 0; j < baseKeys.length;j++){
- var selBaseKey = baseKeys[j];
- if(seqNodePropNames.indexOf(selBaseKey) == -1){
+ for (j = 0; j < baseKeys.length; j++) {
+ var selBaseKey = baseKeys[j];
+ if (seqNodePropNames.indexOf(selBaseKey) === -1) {
var value = nodeBaseValues.objectForKey(selBaseKey);
- if(value != null)
- this._setAnimatedProperty(selBaseKey,node, value, tweenDuration);
+ if (value != null)
+ this._setAnimatedProperty(selBaseKey, node, value, tweenDuration);
}
}
}
@@ -353,8 +356,8 @@ cc.BuilderAnimationManager = cc.Class.extend({
// Make callback at end of sequence
var seq = this._getSequence(nSeqId);
- var completeAction = cc.Sequence.create(cc.DelayTime.create(seq.getDuration() + tweenDuration),
- cc.CallFunc.create(this._sequenceCompleted,this));
+ var completeAction = cc.sequence(cc.delayTime(seq.getDuration() + tweenDuration),
+ cc.callFunc(this._sequenceCompleted, this));
this._rootNode.runAction(completeAction);
// Playback callbacks and sounds
@@ -378,10 +381,10 @@ cc.BuilderAnimationManager = cc.Class.extend({
this._runningSequence = this._getSequence(nSeqId);
},
- runAnimations:function (name, tweenDuration) {
+ runAnimations: function (name, tweenDuration) {
tweenDuration = tweenDuration || 0;
var nSeqId;
- if(typeof(name) === "string")
+ if (cc.isString(name))
nSeqId = this._getSequenceId(name);
else
nSeqId = name;
@@ -389,29 +392,29 @@ cc.BuilderAnimationManager = cc.Class.extend({
this.runAnimationsForSequenceIdTweenDuration(nSeqId, tweenDuration);
},
- setAnimationCompletedCallback:function(target,callbackFunc){
+ setAnimationCompletedCallback: function (target, callbackFunc) {
this._target = target;
this._animationCompleteCallbackFunc = callbackFunc;
},
- setCompletedAnimationCallback:function(target,callbackFunc){
- this.setAnimationCompletedCallback(target,callbackFunc);
+ setCompletedAnimationCallback: function (target, callbackFunc) {
+ this.setAnimationCompletedCallback(target, callbackFunc);
},
- setCallFunc:function(callFunc, callbackNamed) {
+ setCallFunc: function (callFunc, callbackNamed) {
this._keyframeCallFuncs[callbackNamed] = callFunc;
},
- debug:function () {
+ debug: function () {
},
- _getBaseValue:function (node, propName) {
+ _getBaseValue: function (node, propName) {
var props = this._baseValues.objectForKey(node);
if (props)
return props.objectForKey(propName);
return null;
},
- _getSequenceId:function (sequenceName) {
+ _getSequenceId: function (sequenceName) {
var element = null;
var locSequences = this._sequences;
for (var i = 0, len = locSequences.length; i < len; i++) {
@@ -422,7 +425,7 @@ cc.BuilderAnimationManager = cc.Class.extend({
return -1;
},
- _getSequence:function (sequenceId) {
+ _getSequence: function (sequenceId) {
var element = null;
var locSequences = this._sequences;
for (var i = 0, len = locSequences.length; i < len; i++) {
@@ -433,9 +436,9 @@ cc.BuilderAnimationManager = cc.Class.extend({
return null;
},
- _getAction:function (keyframe0, keyframe1, propName, node) {
+ _getAction: function (keyframe0, keyframe1, propName, node) {
var duration = keyframe1.getTime() - (keyframe0 ? keyframe0.getTime() : 0);
- var getArr,type,getValueArr, x, y;
+ var getArr, type, getValueArr, x, y;
if (propName === "rotation") {
return cc.BuilderRotateTo.create(duration, keyframe1.getValue());
@@ -444,21 +447,21 @@ cc.BuilderAnimationManager = cc.Class.extend({
} else if (propName === "rotationY") {
return cc.BuilderRotateYTo.create(duration, keyframe1.getValue());
} else if (propName === "opacity") {
- return cc.FadeTo.create(duration, keyframe1.getValue());
+ return cc.fadeTo(duration, keyframe1.getValue());
} else if (propName === "color") {
- var selColor = keyframe1.getValue().getColor();
- return cc.TintTo.create(duration, selColor.r, selColor.g, selColor.b);
+ var selColor = keyframe1.getValue();
+ return cc.tintTo(duration, selColor.r, selColor.g, selColor.b);
} else if (propName === "visible") {
var isVisible = keyframe1.getValue();
if (isVisible) {
- return cc.Sequence.create(cc.DelayTime.create(duration), cc.Show.create());
+ return cc.sequence(cc.delayTime(duration), cc.show());
} else {
- return cc.Sequence.create(cc.DelayTime.create(duration), cc.Hide.create());
+ return cc.sequence(cc.delayTime(duration), cc.hide());
}
} else if (propName === "displayFrame") {
- return cc.Sequence.create(cc.DelayTime.create(duration), cc.BuilderSetSpriteFrame.create(keyframe1.getValue()));
- } else if(propName === "position"){
- getArr = this._getBaseValue(node,propName);
+ return cc.sequence(cc.delayTime(duration), cc.BuilderSetSpriteFrame.create(keyframe1.getValue()));
+ } else if (propName === "position") {
+ getArr = this._getBaseValue(node, propName);
type = getArr[2];
//get relative position
@@ -468,11 +471,11 @@ cc.BuilderAnimationManager = cc.Class.extend({
var containerSize = this.getContainerSize(node.getParent());
- var absPos = cc._getAbsolutePosition(x,y, type,containerSize,propName);
+ var absPos = cc.getAbsolutePosition(x, y, type, containerSize, propName);
- return cc.MoveTo.create(duration,absPos);
- } else if( propName === "scale"){
- getArr = this._getBaseValue(node,propName);
+ return cc.moveTo(duration, absPos);
+ } else if (propName === "scale") {
+ getArr = this._getBaseValue(node, propName);
type = getArr[2];
//get relative position
@@ -480,28 +483,28 @@ cc.BuilderAnimationManager = cc.Class.extend({
x = getValueArr[0];
y = getValueArr[1];
- if(type === CCB_SCALETYPE_MULTIPLY_RESOLUTION){
+ if (type === CCB_SCALETYPE_MULTIPLY_RESOLUTION) {
//TODO need to test
var resolutionScale = cc.BuilderReader.getResolutionScale();
x *= resolutionScale;
y *= resolutionScale;
}
- return cc.ScaleTo.create(duration,x,y);
- } else if( propName === "skew") {
+ return cc.scaleTo(duration, x, y);
+ } else if (propName === "skew") {
//get relative position
getValueArr = keyframe1.getValue();
x = getValueArr[0];
y = getValueArr[1];
- return cc.SkewTo.create(duration,x,y);
+ return cc.skewTo(duration, x, y);
} else {
cc.log("BuilderReader: Failed to create animation for property: " + propName);
}
return null;
},
- _setAnimatedProperty:function (propName, node, value, tweenDuration) {
- if(tweenDuration > 0){
+ _setAnimatedProperty: function (propName, node, value, tweenDuration) {
+ if (tweenDuration > 0) {
// Create a fake keyframe to generate the action from
var kf1 = new cc.BuilderKeyframe();
kf1.setValue(value);
@@ -513,59 +516,66 @@ cc.BuilderAnimationManager = cc.Class.extend({
node.runAction(tweenAction);
} else {
// Just set the value
- var getArr, nType, x,y;
- if(propName === "position"){
- getArr = this._getBaseValue(node,propName);
+ var getArr, nType, x, y;
+ if (propName === "position") {
+ getArr = this._getBaseValue(node, propName);
nType = getArr[2];
x = value[0];
y = value[1];
- node.setPosition(cc._getAbsolutePosition(x,y,nType, this.getContainerSize(node.getParent()),propName));
- }else if(propName === "scale"){
- getArr = this._getBaseValue(node,propName);
+ cc.getAbsolutePosition(x, y, nType, this.getContainerSize(node.getParent()), propName, _pos);
+ node._position.x = _pos.x;
+ node._position.y = _pos.y;
+ } else if (propName === "scale") {
+ getArr = this._getBaseValue(node, propName);
nType = getArr[2];
x = value[0];
y = value[1];
- cc.setRelativeScale(node,x,y,nType,propName);
- } else if( propName === "skew") {
+ cc.setRelativeScale(node, x, y, nType, propName);
+ } else if (propName === "skew") {
x = value[0];
y = value[1];
- node.setSkewX(x);
- node.setSkewY(y);
- }else {
+ node._skewX = x;
+ node._skewY = y;
+ } else {
// [node setValue:value forKey:name];
// TODO only handle rotation, opacity, displayFrame, color
- if(propName === "rotation"){
+ if (propName === "rotation") {
node.setRotation(value);
- } else if(propName === "opacity"){
- node.setOpacity(value);
- } else if(propName === "displayFrame"){
- node.setDisplayFrame(value);
- } else if(propName === "color"){
- var ccColor3B = value.getColor();
- if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){
- node.setColor(ccColor3B);
+ } else if (propName === "rotationX") {
+ node._rotationX = value;
+ } else if (propName === "rotationY") {
+ node._rotationY = value;
+ } else if (propName === "opacity") {
+ node._realOpacity = value;
+ } else if (propName === "displayFrame") {
+ node.setSpriteFrame(value);
+ } else if (propName === "color") {
+ if (value.r !== 255 || value.g !== 255 || value.b !== 255) {
+ node.setColor(value);
}
- } else if( propName === "visible"){
+ } else if (propName === "visible") {
value = value || false;
node.setVisible(value);
} else {
- cc.log("unsupported property name is "+ propName);
- cc.Assert(false, "unsupported property now");
+ cc.log("unsupported property name is " + propName);
+ return;
}
}
+ node.setNodeDirty();
}
},
- _setFirstFrame:function (node, seqProp, tweenDuration) {
+ _setFirstFrame: function (node, seqProp, tweenDuration) {
var keyframes = seqProp.getKeyframes();
if (keyframes.length === 0) {
// Use base value (no animation)
var baseValue = this._getBaseValue(node, seqProp.getName());
- cc.Assert(baseValue, "No baseValue found for property");
+ if (!baseValue)
+ cc.log("cc.BuilderAnimationManager._setFirstFrame(): No baseValue found for property");
this._setAnimatedProperty(seqProp.getName(), node, baseValue, tweenDuration);
} else {
// Use first keyframe
@@ -574,40 +584,40 @@ cc.BuilderAnimationManager = cc.Class.extend({
}
},
- _getEaseAction:function (action, easingType, easingOpt) {
- if (easingType === CCB_KEYFRAME_EASING_LINEAR || easingType === CCB_KEYFRAME_EASING_INSTANT ) {
+ _getEaseAction: function (action, easingType, easingOpt) {
+ if (easingType === CCB_KEYFRAME_EASING_LINEAR || easingType === CCB_KEYFRAME_EASING_INSTANT) {
return action;
} else if (easingType === CCB_KEYFRAME_EASING_CUBIC_IN) {
- return cc.EaseIn.create(action, easingOpt);
+ return action.easing(cc.easeIn(easingOpt));
} else if (easingType === CCB_KEYFRAME_EASING_CUBIC_OUT) {
- return cc.EaseOut.create(action, easingOpt);
+ return action.easing(cc.easeOut(easingOpt));
} else if (easingType === CCB_KEYFRAME_EASING_CUBIC_INOUT) {
- return cc.EaseInOut.create(action, easingOpt);
+ return action.easing(cc.easeInOut(easingOpt));
} else if (easingType === CCB_KEYFRAME_EASING_BACK_IN) {
- return cc.EaseBackIn.create(action);
+ return action.easing(cc.easeBackIn());
} else if (easingType === CCB_KEYFRAME_EASING_BACK_OUT) {
- return cc.EaseBackOut.create(action);
+ return action.easing(cc.easeBackOut());
} else if (easingType === CCB_KEYFRAME_EASING_BACK_INOUT) {
- return cc.EaseBackInOut.create(action);
+ return action.easing(cc.easeBackInOut());
} else if (easingType === CCB_KEYFRAME_EASING_BOUNCE_IN) {
- return cc.EaseBounceIn.create(action);
+ return action.easing(cc.easeBounceIn());
} else if (easingType === CCB_KEYFRAME_EASING_BOUNCE_OUT) {
- return cc.EaseBounceOut.create(action);
+ return action.easing(cc.easeBounceOut());
} else if (easingType === CCB_KEYFRAME_EASING_BOUNCE_INOUT) {
- return cc.EaseBounceInOut.create(action);
+ return action.easing(cc.easeBounceInOut());
} else if (easingType === CCB_KEYFRAME_EASING_ELASTIC_IN) {
- return cc.EaseElasticIn.create(action, easingOpt);
+ return action.easing(cc.easeElasticIn(easingOpt));
} else if (easingType === CCB_KEYFRAME_EASING_ELASTIC_OUT) {
- return cc.EaseElasticOut.create(action, easingOpt);
+ return action.easing(cc.easeElasticOut(easingOpt));
} else if (easingType === CCB_KEYFRAME_EASING_ELASTIC_INOUT) {
- return cc.EaseElasticInOut.create(action, easingOpt);
+ return action.easing(cc.easeElasticInOut(easingOpt));
} else {
- cc.log("BuilderReader: Unkown easing type " + easingType);
+ cc.log("BuilderReader: Unknown easing type " + easingType);
return action;
}
},
- _runAction:function (node, seqProp, tweenDuration) {
+ _runAction: function (node, seqProp, tweenDuration) {
var keyframes = seqProp.getKeyframes();
var numKeyframes = keyframes.length;
@@ -619,12 +629,12 @@ cc.BuilderAnimationManager = cc.Class.extend({
var timeFirst = keyframeFirst.getTime() + tweenDuration;
if (timeFirst > 0) {
- actions.push(cc.DelayTime.create(timeFirst));
+ actions.push(cc.delayTime(timeFirst));
}
for (var i = 0; i < numKeyframes - 1; ++i) {
var kf0 = keyframes[i];
- var kf1 = keyframes[(i+1)];
+ var kf1 = keyframes[(i + 1)];
var action = this._getAction(kf0, kf1, seqProp.getName(), node);
if (action) {
@@ -634,30 +644,29 @@ cc.BuilderAnimationManager = cc.Class.extend({
}
}
- var seq = cc.Sequence.create(actions);
- node.runAction(seq);
+ node.runAction(cc.sequence(actions));
}
},
- _sequenceCompleted:function () {
+ _sequenceCompleted: function () {
var locRunningSequence = this._runningSequence;
var locRunningName = locRunningSequence.getName();
- if(this._lastCompletedSequenceName != locRunningSequence.getName()){
+ if (this._lastCompletedSequenceName != locRunningSequence.getName()) {
this._lastCompletedSequenceName = locRunningSequence.getName();
}
var nextSeqId = locRunningSequence.getChainedSequenceId();
this._runningSequence = null;
- if (nextSeqId != -1)
+ if (nextSeqId !== -1)
this.runAnimations(nextSeqId, 0);
if (this._delegate)
this._delegate.completedAnimationSequenceNamed(locRunningName);
- if(this._target && this._animationCompleteCallbackFunc){
+ if (this._target && this._animationCompleteCallbackFunc) {
this._animationCompleteCallbackFunc.call(this._target);
}
}
@@ -665,14 +674,14 @@ cc.BuilderAnimationManager = cc.Class.extend({
cc.BuilderSetSpriteFrame = cc.ActionInstant.extend({
- _spriteFrame:null,
+ _spriteFrame: null,
- initWithSpriteFrame:function (spriteFrame) {
+ initWithSpriteFrame: function (spriteFrame) {
this._spriteFrame = spriteFrame;
return true;
},
- update:function (time) {
- this._target.setDisplayFrame(this._spriteFrame);
+ update: function (time) {
+ this.target.setSpriteFrame(this._spriteFrame);
}
});
@@ -689,11 +698,11 @@ cc.BuilderSetSpriteFrame.create = function (spriteFrame) {
// cc.BuilderRotateTo
//
cc.BuilderRotateTo = cc.ActionInterval.extend({
- _startAngle:0,
- _dstAngle:0,
- _diffAngle:0,
+ _startAngle: 0,
+ _dstAngle: 0,
+ _diffAngle: 0,
- initWithDuration:function (duration, angle) {
+ initWithDuration: function (duration, angle) {
if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) {
this._dstAngle = angle;
return true;
@@ -701,13 +710,13 @@ cc.BuilderRotateTo = cc.ActionInterval.extend({
return false;
}
},
- update:function (time) {
- this._target.setRotation(this._startAngle + (this._diffAngle * time));
+ update: function (time) {
+ this.target.setRotation(this._startAngle + (this._diffAngle * time));
},
- startWithTarget:function (node) {
+ startWithTarget: function (node) {
cc.ActionInterval.prototype.startWithTarget.call(this, node);
- this._startAngle = this._target.getRotation();
+ this._startAngle = this.target.getRotation();
this._diffAngle = this._dstAngle - this._startAngle;
}
});
@@ -729,8 +738,7 @@ cc.BuilderRotateXTo = cc.ActionInterval.extend({
});
cc.BuilderRotateXTo.create = function (duration, angle) {
- cc.Assert(false, "rotationX not implemented in cocos2d-html5");
- return null;
+ throw new Error("rotationX has not been implemented in cocos2d-html5");
};
//
@@ -741,27 +749,26 @@ cc.BuilderRotateYTo = cc.ActionInterval.extend({
});
cc.BuilderRotateYTo.create = function (duration, angle) {
- cc.Assert(false, "rotationY not implemented in cocos2d-html5");
- return null;
+ throw new Error("rotationY has not been implemented in cocos2d-html5");
};
//
// cc.BuilderSoundEffect
//
cc.BuilderSoundEffect = cc.ActionInstant.extend({
- init:function(file) {
+ init: function (file) {
this._file = file;
return true;
},
- update:function(dt) {
- cc.AudioEngine.getInstance().playEffect(this._file);
+ update: function (dt) {
+ cc.audioEngine.playEffect(this._file);
}
});
cc.BuilderSoundEffect.create = function (file, pitch, pan, gain) {
var ret = new cc.BuilderSoundEffect();
if (ret && ret.init(file)) {
- return ret;
+ return ret;
}
return null;
};
-
+})();
diff --git a/extensions/CCBReader/CCBKeyframe.js b/extensions/ccb-reader/CCBKeyframe.js
similarity index 95%
rename from extensions/CCBReader/CCBKeyframe.js
rename to extensions/ccb-reader/CCBKeyframe.js
index 57da466e85..c3eb7afaeb 100644
--- a/extensions/CCBReader/CCBKeyframe.js
+++ b/extensions/ccb-reader/CCBKeyframe.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
diff --git a/extensions/CCBReader/CCBReader.js b/extensions/ccb-reader/CCBReader.js
similarity index 71%
rename from extensions/CCBReader/CCBReader.js
rename to extensions/ccb-reader/CCBReader.js
index c8c02c74b2..0baa27b4ca 100644
--- a/extensions/CCBReader/CCBReader.js
+++ b/extensions/ccb-reader/CCBReader.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -102,65 +102,49 @@ var CCB_SIZETYPE_MULTIPLY_RESOLUTION = 5;
var CCB_SCALETYPE_ABSOLUTE = 0;
var CCB_SCALETYPE_MULTIPLY_RESOLUTION = 1;
-var _ccbGlobalContext = _ccbGlobalContext || window;
-
-cc.BuilderFile = cc.Node.extend({
- _ccbFileNode:null,
-
- getCCBFileNode:function () {
- return this._ccbFileNode;
- },
- setCCBFileNode:function (node) {
- this._ccbFileNode = node;
- }
-});
-
-cc.BuilderFile.create = function () {
- return new cc.BuilderFile();
-};
-
/**
* Parse CCBI file which is generated by CocosBuilder
*/
cc.BuilderReader = cc.Class.extend({
- _jsControlled:false,
- _data:null,
- _ccbRootPath:"",
+ _jsControlled: false,
+ _data: null,
+ _ccbRootPath: "",
- _bytes:0,
- _currentByte:0,
- _currentBit:0,
+ _bytes: 0,
+ _currentByte: 0,
+ _currentBit: 0,
- _stringCache:null,
- _loadedSpriteSheets:null,
+ _stringCache: null,
+ _loadedSpriteSheets: null,
- _owner:null,
- _animationManager:null,
- _animationManagers:null,
- _animatedProps:null,
+ _owner: null,
+ _animationManager: null,
+ _animationManagers: null,
+ _animatedProps: null,
- _ccNodeLoaderLibrary:null,
- _ccNodeLoaderListener:null,
- _ccbMemberVariableAssigner:null,
- _ccbSelectorResolver:null,
+ _ccNodeLoaderLibrary: null,
+ _ccNodeLoaderListener: null,
+ _ccbMemberVariableAssigner: null,
+ _ccbSelectorResolver: null,
- _ownerOutletNames:null,
- _ownerOutletNodes:null,
- _nodesWithAnimationManagers:null,
- _animationManagerForNodes:null,
+ _ownerOutletNames: null,
+ _ownerOutletNodes: null,
+ _nodesWithAnimationManagers: null,
+ _animationManagerForNodes: null,
- _ownerCallbackNames:null,
- _ownerCallbackNodes:null,
+ _ownerCallbackNames: null,
+ _ownerCallbackNodes: null,
+ _ownerCallbackEvents: null,
- _readNodeGraphFromData:false,
+ _readNodeGraphFromData: false,
- ctor:function (ccNodeLoaderLibrary, ccbMemberVariableAssigner, ccbSelectorResolver, ccNodeLoaderListener) {
+ ctor: function (ccNodeLoaderLibrary, ccbMemberVariableAssigner, ccbSelectorResolver, ccNodeLoaderListener) {
this._stringCache = [];
this._loadedSpriteSheets = [];
this._currentBit = -1;
this._currentByte = -1;
- if (arguments.length != 0) {
+ if (arguments.length !== 0) {
if (ccNodeLoaderLibrary instanceof cc.BuilderReader) {
var ccbReader = ccNodeLoaderLibrary;
@@ -174,6 +158,7 @@ cc.BuilderReader = cc.Class.extend({
this._ownerCallbackNames = ccbReader._ownerCallbackNames;
this._ownerCallbackNodes = ccbReader._ownerCallbackNodes;
+ this._ownerCallbackEvents = ccbReader._ownerCallbackEvents;
this._ownerOutletNames = ccbReader._ownerOutletNames;
this._ownerOutletNodes = ccbReader._ownerOutletNodes;
this._ccbRootPath = ccbReader._ccbRootPath;
@@ -186,15 +171,15 @@ cc.BuilderReader = cc.Class.extend({
}
},
- getCCBRootPath:function () {
+ getCCBRootPath: function () {
return this._ccbRootPath;
},
- setCCBRootPath:function (rootPath) {
+ setCCBRootPath: function (rootPath) {
this._ccbRootPath = rootPath;
},
- initWithData:function (data, owner) {
+ initWithData: function (data, owner) {
//setup action manager
this._animationManager = new cc.BuilderAnimationManager();
@@ -208,26 +193,64 @@ cc.BuilderReader = cc.Class.extend({
this._owner = owner;
//setup resolution scale and container size
- this._animationManager.setRootContainerSize(cc.Director.getInstance().getWinSize());
+ this._animationManager.setRootContainerSize(cc.director.getWinSize());
return true;
},
- readNodeGraphFromFile:function (ccbFileName, owner, parentSize, animationManager) {
+ _loadBinarySync: function (url) {
+ var self = this;
+ var req = this.getXMLHttpRequest();
+ var errInfo = "load " + url + " failed!";
+ req.open('GET', url, false);
+ var arrayInfo = null;
+ if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
+ req.setRequestHeader("Accept-Charset", "x-user-defined");
+ req.send(null);
+ if (req.status !== 200) {
+ cc.log(errInfo);
+ return null;
+ }
+
+ var fileContents = cc._convertResponseBodyToText(req["responseBody"]);
+ if (fileContents) {
+ arrayInfo = this._stringConvertToArray(fileContents);
+ this._fileDataCache[url] = arrayInfo;
+ }
+ } else {
+ if (req.overrideMimeType)
+ req.overrideMimeType('text\/plain; charset=x-user-defined');
+ req.send(null);
+ if (req.status !== 200) {
+ cc.log(errInfo);
+ return null;
+ }
+
+ arrayInfo = this._stringConvertToArray(req.responseText);
+ this._fileDataCache[url] = arrayInfo;
+ }
+ return arrayInfo;
+ },
+
+ readNodeGraphFromFile: function (ccbFileName, owner, parentSize, animationManager) {
if (parentSize == null) {
- parentSize = cc.Director.getInstance().getWinSize();
+ parentSize = cc.director.getWinSize();
} else if (parentSize instanceof cc.BuilderAnimationManager) {
animationManager = parentSize;
- parentSize = cc.Director.getInstance().getWinSize();
+ parentSize = cc.director.getWinSize();
+ }
+
+ var data = cc.loader.getRes(ccbFileName);
+ if (!data) {
+ var realUrl = cc.loader.getUrl(ccbFileName);
+ data = cc.loader.loadBinarySync(realUrl);
+ cc.loader.cache[ccbFileName] = data;
}
- var fileUtils = cc.FileUtils.getInstance();
- var path = fileUtils.fullPathFromRelativePath(ccbFileName);
- var data = fileUtils.getByteArrayFromFile(path);
return this.readNodeGraphFromData(data, owner, parentSize, animationManager);
},
- readNodeGraphFromData:function (data, owner, parentSize) {
+ readNodeGraphFromData: function (data, owner, parentSize) {
this.initWithData(data, owner);
var locAnimationManager = this._animationManager;
locAnimationManager.setRootContainerSize(parentSize);
@@ -237,11 +260,12 @@ cc.BuilderReader = cc.Class.extend({
this._ownerOutletNodes = [];
this._ownerCallbackNames = [];
this._ownerCallbackNodes = [];
+ this._ownerCallbackEvents = [];
this._animationManagers = new cc._Dictionary();
var nodeGraph = this.readFileWithCleanUp(true);
- if (nodeGraph && locAnimationManager.getAutoPlaySequenceId() != -1) {
+ if (nodeGraph && locAnimationManager.getAutoPlaySequenceId() !== -1) {
//auto play animations
locAnimationManager.runAnimations(locAnimationManager.getAutoPlaySequenceId(), 0);
}
@@ -264,50 +288,68 @@ cc.BuilderReader = cc.Class.extend({
return nodeGraph;
},
- createSceneWithNodeGraphFromFile:function (ccbFileName, owner, parentSize, animationManager) {
+ createSceneWithNodeGraphFromFile: function (ccbFileName, owner, parentSize, animationManager) {
var node = this.readNodeGraphFromFile(ccbFileName, owner, parentSize, animationManager);
- var scene = cc.Scene.create();
+ var scene = new cc.Scene();
scene.addChild(node);
return scene;
},
- getCCBMemberVariableAssigner:function () {
+ getCCBMemberVariableAssigner: function () {
return this._ccbMemberVariableAssigner;
},
- getCCBSelectorResolver:function () {
+ getCCBSelectorResolver: function () {
return this._ccbSelectorResolver;
},
- getAnimationManager:function () {
+ getAnimationManager: function () {
return this._animationManager;
},
- setAnimationManager:function (animationManager) {
+ setAnimationManager: function (animationManager) {
this._animationManager = animationManager;
},
- getAnimatedProperties:function () {
+ getAnimatedProperties: function () {
return this._animatedProps;
},
- getLoadedSpriteSheet:function () {
+ getLoadedSpriteSheet: function () {
return this._loadedSpriteSheets;
},
- getOwner:function () {
+ getOwner: function () {
return this._owner;
},
- readInt:function (signed) {
+ readInt: function (signed) {
var numBits = 0;
- while (!this._getBit()) {
+ var data = this._data[this._currentByte];
+ var bit = !!(data & (1 << this._currentBit++));
+ while (!bit) {
numBits++;
+ bit = !!(data & (1 << this._currentBit++));
+ if (this._currentBit >= 8) {
+ this._currentBit = 0;
+ this._currentByte++;
+ data = this._data[this._currentByte];
+ if (this._currentByte > this._data.length)
+ throw new Error("out of the data bound");
+ }
}
var current = 0;
for (var a = numBits - 1; a >= 0; a--) {
- if (this._getBit()) {
+ bit = !!(data & (1 << this._currentBit++));
+ if (this._currentBit >= 8) {
+ this._currentBit = 0;
+ this._currentByte++;
+ data = this._data[this._currentByte];
+ if (this._currentByte > this._data.length)
+ throw new Error("out of the data bound");
+ }
+ if (bit) {
current |= 1 << a;
}
}
@@ -325,23 +367,26 @@ cc.BuilderReader = cc.Class.extend({
num = current - 1;
}
- this._alignBits();
+ if (this._currentBit) {
+ this._currentBit = 0;
+ this._currentByte++;
+ }
return num;
},
- readByte:function () {
+ readByte: function () {
var byteValue = this._data[this._currentByte];
this._currentByte++;
return byteValue;
},
- readBool:function () {
- return (0 != this.readByte());
+ readBool: function () {
+ return !!this._data[this._currentByte++];
},
- readFloat:function () {
- var type = this.readByte();
+ readFloat: function () {
+ var type = this._data[this._currentByte++];
switch (type) {
case CCB_FLOAT0:
@@ -364,10 +409,12 @@ cc.BuilderReader = cc.Class.extend({
}
},
- _decodeFloat:function (precisionBits, exponentBits) {
+ _decodeFloat: function (precisionBits, exponentBits) {
var length = precisionBits + exponentBits + 1;
var size = length >> 3;
- this._checkSize(length);
+ if (this._currentByte + size >= this._data.length) {
+ throw new Error("Index out of bound");
+ }
var bias = Math.pow(2, exponentBits - 1) - 1;
var signal = this._readBitsOnly(precisionBits + exponentBits, 1, size);
@@ -376,7 +423,7 @@ cc.BuilderReader = cc.Class.extend({
var divisor = 2;
var curByte = 0; //length + (-precisionBits >> 3) - 1;
do {
- var byteValue = this._readByteOnly(++curByte, size);
+ var byteValue = this._data[this._currentByte + size - (++curByte) - 1];
var startBit = precisionBits % 8 || 8;
var mask = 1 << startBit;
while (mask >>= 1) {
@@ -389,107 +436,107 @@ cc.BuilderReader = cc.Class.extend({
this._currentByte += size;
- return exponent == (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity
+ return exponent === (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity
: (1 + signal * -2) * (exponent || significand ? !exponent ? Math.pow(2, -bias + 1) * significand
: Math.pow(2, exponent - bias) * (1 + significand) : 0);
},
- _readBitsOnly:function (start, length, size) {
+ _readBitsOnly: function (start, length, size) {
var offsetLeft = (start + length) % 8;
var offsetRight = start % 8;
var curByte = size - (start >> 3) - 1;
var lastByte = size + (-(start + length) >> 3);
var diff = curByte - lastByte;
- var sum = (this._readByteOnly(curByte, size) >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1);
+ var sum = (this._data[this._currentByte + size - curByte - 1] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1);
if (diff && offsetLeft) {
- sum += (this._readByteOnly(lastByte++, size) & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight;
+ sum += (this._data[this._currentByte + size - lastByte - 1] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight;
+ lastByte++;
}
while (diff) {
- sum += this._shl(this._readByteOnly(lastByte++, size), (diff-- << 3) - offsetRight);
+ sum += this._shl(this._data[this._currentByte + size - lastByte - 1], (diff-- << 3) - offsetRight);
+ lastByte++;
}
return sum;
},
- _readByteOnly:function (i, size) {
- return this._data[this._currentByte + size - i - 1];
- },
-
- _shl:function (a, b) {
- for (++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1);
+ _shl: function (a, b) {
+ for (++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) === 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1);
return a;
},
- _checkSize:function (neededBits) {
- if (!(this._currentByte + Math.ceil(neededBits / 8) < this._data.length)) {
- throw new Error("Index out of bound");
- }
- },
-
- readCachedString:function () {
+ readCachedString: function () {
return this._stringCache[this.readInt(false)];
},
- isJSControlled:function () {
+ isJSControlled: function () {
return this._jsControlled;
},
- getOwnerCallbackNames:function () {
+ getOwnerCallbackNames: function () {
return this._ownerCallbackNames;
},
- getOwnerCallbackNodes:function () {
+ getOwnerCallbackNodes: function () {
return this._ownerCallbackNodes;
},
- getOwnerOutletNames:function () {
+ getOwnerCallbackControlEvents: function () {
+ return this._ownerCallbackEvents;
+ },
+
+ getOwnerOutletNames: function () {
return this._ownerOutletNames;
},
- getOwnerOutletNodes:function () {
+ getOwnerOutletNodes: function () {
return this._ownerOutletNodes;
},
- getNodesWithAnimationManagers:function () {
+ getNodesWithAnimationManagers: function () {
return this._nodesWithAnimationManagers;
},
- getAnimationManagersForNodes:function () {
+ getAnimationManagersForNodes: function () {
return this._animationManagerForNodes;
},
- getAnimationManagers:function () {
+ getAnimationManagers: function () {
return this._animationManagers;
},
- setAnimationManagers:function (animationManagers) {
+ setAnimationManagers: function (animationManagers) {
this._animationManagers = animationManagers;
},
- addOwnerCallbackName:function (name) {
- this._ownerCallbackNames.push(name)
+ addOwnerCallbackName: function (name) {
+ this._ownerCallbackNames.push(name);
},
- addOwnerCallbackNode:function (node) {
+ addOwnerCallbackNode: function (node) {
this._ownerCallbackNodes.push(node);
},
- addDocumentCallbackName:function (name) {
+ addOwnerCallbackControlEvents: function (event) {
+ this._ownerCallbackEvents.push(event);
+ },
+
+ addDocumentCallbackName: function (name) {
this._animationManager.addDocumentCallbackName(name);
},
- addDocumentCallbackNode:function (node) {
+ addDocumentCallbackNode: function (node) {
this._animationManager.addDocumentCallbackNode(node);
},
- addDocumentCallbackControlEvents:function(controlEvents){
+ addDocumentCallbackControlEvents: function (controlEvents) {
this._animationManager.addDocumentCallbackControlEvents(controlEvents);
},
- readFileWithCleanUp:function (cleanUp) {
+ readFileWithCleanUp: function (cleanUp) {
if (!this._readHeader())
return null;
if (!this._readStringCache())
@@ -505,26 +552,26 @@ cc.BuilderReader = cc.Class.extend({
return node;
},
- addOwnerOutletName: function(name){
- this._ownerOutletNames.push(name);
+ addOwnerOutletName: function (name) {
+ this._ownerOutletNames.push(name);
},
- addOwnerOutletNode: function(node){
- if(node == null)
+ addOwnerOutletNode: function (node) {
+ if (node == null)
return;
this._ownerOutletNodes.push(node);
},
- _cleanUpNodeGraph:function (node) {
- node.setUserObject(null);
+ _cleanUpNodeGraph: function (node) {
+ node.userObject = null;
var getChildren = node.getChildren();
for (var i = 0, len = getChildren.length; i < len; i++) {
this._cleanUpNodeGraph(getChildren[i]);
}
},
- _readCallbackKeyframesForSeq:function(seq) {
+ _readCallbackKeyframesForSeq: function (seq) {
var numKeyframes = this.readInt(false);
if (!numKeyframes)
@@ -537,14 +584,14 @@ cc.BuilderReader = cc.Class.extend({
var callbackName = this.readCachedString();
var callbackType = this.readInt(false);
- var value = [ callbackName, callbackType];
+ var value = [callbackName, callbackType];
var keyframe = new cc.BuilderKeyframe();
keyframe.setTime(time);
keyframe.setValue(value);
- if(locJsControlled)
- locAnimationManager.getKeyframeCallbacks().push(callbackType+":"+callbackName);
+ if (locJsControlled)
+ locAnimationManager.getKeyframeCallbacks().push(callbackType + ":" + callbackName);
locKeyframes.push(keyframe);
}
@@ -555,7 +602,7 @@ cc.BuilderReader = cc.Class.extend({
return true;
},
- _readSoundKeyframesForSeq:function(seq) {
+ _readSoundKeyframesForSeq: function (seq) {
var numKeyframes = this.readInt(false);
if (!numKeyframes)
@@ -570,7 +617,7 @@ cc.BuilderReader = cc.Class.extend({
var pan = this.readFloat();
var gain = this.readFloat();
- var value = [soundFile, pitch, pan, gain];
+ var value = [soundFile, pitch, pan, gain];
var keyframe = new cc.BuilderKeyframe();
keyframe.setTime(time);
keyframe.setValue(value);
@@ -582,7 +629,7 @@ cc.BuilderReader = cc.Class.extend({
seq.setSoundChannel(channel);
return true;
},
- _readSequences:function () {
+ _readSequences: function () {
var sequences = this._animationManager.getSequences();
var numSeqs = this.readInt(false);
for (var i = 0; i < numSeqs; i++) {
@@ -603,7 +650,7 @@ cc.BuilderReader = cc.Class.extend({
return true;
},
- readKeyframe:function (type) {
+ readKeyframe: function (type) {
var keyframe = new cc.BuilderKeyframe();
keyframe.setTime(this.readFloat());
var easingType = this.readInt(false);
@@ -622,34 +669,33 @@ cc.BuilderReader = cc.Class.extend({
keyframe.setEasingType(easingType);
keyframe.setEasingOpt(easingOpt);
- if (type == CCB_PROPTYPE_CHECK) {
- value = this.readBool();
- } else if (type == CCB_PROPTYPE_BYTE) {
- value = this.readByte();
- } else if (type == CCB_PROPTYPE_COLOR3) {
- var c = cc.c3(this.readByte(), this.readByte(), this.readByte());
- value = cc.Color3BWapper.create(c);
- } else if (type == CCB_PROPTYPE_FLOATXY) {
+ if (type === CCB_PROPTYPE_CHECK) {
+ value = !!this._data[this._currentByte++];
+ } else if (type === CCB_PROPTYPE_BYTE) {
+ value = this._data[this._currentByte++];
+ } else if (type === CCB_PROPTYPE_COLOR3) {
+ value = cc.color(this._data[this._currentByte++], this._data[this._currentByte++], this._data[this._currentByte++]);
+ } else if (type === CCB_PROPTYPE_FLOATXY) {
value = [this.readFloat(), this.readFloat()];
- } else if (type == CCB_PROPTYPE_DEGREES) {
+ } else if (type === CCB_PROPTYPE_DEGREES) {
value = this.readFloat();
- } else if (type == CCB_PROPTYPE_SCALELOCK || type == CCB_PROPTYPE_POSITION || type == CCB_PROPTYPE_FLOATXY) {
+ } else if (type === CCB_PROPTYPE_SCALELOCK || type === CCB_PROPTYPE_POSITION || type === CCB_PROPTYPE_FLOATXY) {
value = [this.readFloat(), this.readFloat()];
- } else if (type == CCB_PROPTYPE_SPRITEFRAME) {
+ } else if (type === CCB_PROPTYPE_SPRITEFRAME) {
var spriteSheet = this.readCachedString();
var spriteFile = this.readCachedString();
- if (spriteSheet == "") {
+ if (spriteSheet === "") {
spriteFile = this._ccbRootPath + spriteFile;
- var texture = cc.TextureCache.getInstance().addImage(spriteFile);
+ var texture = cc.textureCache.addImage(spriteFile);
var locContentSize = texture.getContentSize();
var bounds = cc.rect(0, 0, locContentSize.width, locContentSize.height);
- value = cc.SpriteFrame.createWithTexture(texture, bounds);
+ value = new cc.SpriteFrame(texture, bounds);
} else {
spriteSheet = this._ccbRootPath + spriteSheet;
- var frameCache = cc.SpriteFrameCache.getInstance();
+ var frameCache = cc.spriteFrameCache;
// Load the sprite sheet only if it is not loaded
- if (this._loadedSpriteSheets.indexOf(spriteSheet) == -1) {
+ if (this._loadedSpriteSheets.indexOf(spriteSheet) === -1) {
frameCache.addSpriteFrames(spriteSheet);
this._loadedSpriteSheets.push(spriteSheet);
}
@@ -660,57 +706,56 @@ cc.BuilderReader = cc.Class.extend({
return keyframe;
},
- _readHeader:function () {
+ _readHeader: function () {
/* If no bytes loaded, don't crash about it. */
- if (this._data == null) {
+ if (!this._data)
return false;
- }
/* Read magic bytes */
var magicBytes = this._readStringFromBytes(this._currentByte, 4, true);
this._currentByte += 4;
- if (magicBytes != 'ccbi') {
+ if (magicBytes !== 'ccbi') {
return false;
}
/* Read version. */
var version = this.readInt(false);
- if (version != CCB_VERSION) {
+ if (version !== CCB_VERSION) {
cc.log("WARNING! Incompatible ccbi file version (file: " + version + " reader: " + CCB_VERSION + ")");
return false;
}
- this._jsControlled = this.readBool();
+ this._jsControlled = !!this._data[this._currentByte++];
this._animationManager._jsControlled = this._jsControlled;
// no need to set if it is "jscontrolled". It is obvious.
return true;
},
- _readStringFromBytes:function (startIndex, strLen, reverse) {
+ _readStringFromBytes: function (startIndex, strLen, reverse) {
reverse = reverse || false;
var strValue = "";
- var i, locData = this._data, locCurrentByte = this._currentByte;
+ var i, locData = this._data;
if (reverse) {
for (i = strLen - 1; i >= 0; i--)
- strValue += String.fromCharCode(locData[locCurrentByte + i]);
+ strValue += String.fromCharCode(locData[startIndex + i]);
} else {
for (i = 0; i < strLen; i++)
- strValue += String.fromCharCode(locData[locCurrentByte + i]);
+ strValue += String.fromCharCode(locData[startIndex + i]);
}
return strValue;
},
- _readStringCache:function () {
+ _readStringCache: function () {
var numStrings = this.readInt(false);
for (var i = 0; i < numStrings; i++)
this._readStringCacheEntry();
return true;
},
- _readStringCacheEntry:function () {
- var b0 = this.readByte();
- var b1 = this.readByte();
+ _readStringCacheEntry: function () {
+ var b0 = this._data[this._currentByte++];
+ var b1 = this._data[this._currentByte++];
var numBytes = b0 << 8 | b1;
@@ -726,7 +771,7 @@ cc.BuilderReader = cc.Class.extend({
this._stringCache.push(str);
},
- _readNodeGraph:function (parent) {
+ _readNodeGraph: function (parent) {
/* Read class name. */
var className = this.readCachedString();
@@ -736,7 +781,7 @@ cc.BuilderReader = cc.Class.extend({
var memberVarAssignmentType = this.readInt(false);
var memberVarAssignmentName;
- if (memberVarAssignmentType != CCB_TARGETTYPE_NONE) {
+ if (memberVarAssignmentType !== CCB_TARGETTYPE_NONE) {
memberVarAssignmentName = this.readCachedString();
}
@@ -752,7 +797,7 @@ cc.BuilderReader = cc.Class.extend({
if (!locActionManager.getRootNode())
locActionManager.setRootNode(node);
- if (locJsControlled && node == locActionManager.getRootNode()) {
+ if (locJsControlled && node === locActionManager.getRootNode()) {
locActionManager.setDocumentControllerName(jsControlledName);
}
@@ -792,9 +837,9 @@ cc.BuilderReader = cc.Class.extend({
ccNodeLoader.parseProperties(node, parent, this);
//handle sub ccb files(remove middle node)
- var isCCBFileNode = node instanceof cc.BuilderFile;
+ var isCCBFileNode = !!node.ccbFileNode;
if (isCCBFileNode) {
- var embeddedNode = node.getCCBFileNode();
+ var embeddedNode = node.ccbFileNode;
embeddedNode.setPosition(node.getPosition());
embeddedNode.setRotation(node.getRotation());
embeddedNode.setScaleX(node.getScaleX());
@@ -804,11 +849,11 @@ cc.BuilderReader = cc.Class.extend({
//embeddedNode.ignoreAnchorPointForPosition(node.isIgnoreAnchorPointForPosition());
locActionManager.moveAnimationsFromNode(node, embeddedNode);
- node.setCCBFileNode(null);
+ node.ccbFileNode = null;
node = embeddedNode;
}
var target = null, locMemberAssigner = null;
- if (memberVarAssignmentType != CCB_TARGETTYPE_NONE) {
+ if (memberVarAssignmentType !== CCB_TARGETTYPE_NONE) {
if (!locJsControlled) {
if (memberVarAssignmentType === CCB_TARGETTYPE_DOCUMENTROOT) {
target = locActionManager.getRootNode();
@@ -816,19 +861,19 @@ cc.BuilderReader = cc.Class.extend({
target = this._owner;
}
- if (target != null) {
+ if (!target) {
var assigned = false;
- if (target != null && (target.onAssignCCBMemberVariable)) {
+ if (target.onAssignCCBMemberVariable)
assigned = target.onAssignCCBMemberVariable(target, memberVarAssignmentName, node);
- }
+
locMemberAssigner = this._ccbMemberVariableAssigner;
if (!assigned && locMemberAssigner != null && locMemberAssigner.onAssignCCBMemberVariable) {
locMemberAssigner.onAssignCCBMemberVariable(target, memberVarAssignmentName, node);
}
}
} else {
- if (memberVarAssignmentType == CCB_TARGETTYPE_DOCUMENTROOT) {
+ if (memberVarAssignmentType === CCB_TARGETTYPE_DOCUMENTROOT) {
locActionManager.addDocumentOutletName(memberVarAssignmentName);
locActionManager.addDocumentOutletNode(node);
} else {
@@ -841,16 +886,16 @@ cc.BuilderReader = cc.Class.extend({
// Assign custom properties.
if (ccNodeLoader.getCustomProperties().length > 0) {
var customAssigned = false;
- if(!locJsControlled) {
+ if (!locJsControlled) {
target = node;
- if(target != null && target.onAssignCCBCustomProperty != null) {
+ if (target != null && target.onAssignCCBCustomProperty != null) {
var customProperties = ccNodeLoader.getCustomProperties();
var customPropKeys = customProperties.allKeys();
- for(i = 0;i < customPropKeys.length;i++){
+ for (i = 0; i < customPropKeys.length; i++) {
var customPropValue = customProperties.objectForKey(customPropKeys[i]);
customAssigned = target.onAssignCCBCustomProperty(target, customPropKeys[i], customPropValue);
locMemberAssigner = this._ccbMemberVariableAssigner;
- if(!customAssigned && (locMemberAssigner != null) && (locMemberAssigner.onAssignCCBCustomProperty != null))
+ if (!customAssigned && (locMemberAssigner != null) && (locMemberAssigner.onAssignCCBCustomProperty != null))
customAssigned = locMemberAssigner.onAssignCCBCustomProperty(target, customPropKeys[i], customPropValue);
}
}
@@ -880,32 +925,12 @@ cc.BuilderReader = cc.Class.extend({
return node;
},
- _getBit:function () {
- var bit = (this._data[this._currentByte] & (1 << this._currentBit)) != 0;
-
- this._currentBit++;
-
- if (this._currentBit >= 8) {
- this._currentBit = 0;
- this._currentByte++;
- }
-
- return bit;
- },
-
- _alignBits:function () {
- if (this._currentBit) {
- this._currentBit = 0;
- this._currentByte++;
- }
- },
-
- _readUTF8:function () {
+ _readUTF8: function () {
}
});
cc.BuilderReader._ccbResolutionScale = 1;
-cc.BuilderReader.setResolutionScale = function(scale){
+cc.BuilderReader.setResolutionScale = function (scale) {
cc.BuilderReader._ccbResolutionScale = scale;
};
@@ -918,16 +943,20 @@ cc.BuilderReader.loadAsScene = function (ccbFilePath, owner, parentSize, ccbRoot
var getNode = cc.BuilderReader.load(ccbFilePath, owner, parentSize, ccbRootPath);
- var scene = cc.Scene.create();
+ var scene = new cc.Scene();
scene.addChild(getNode);
return scene;
};
+cc.BuilderReader._controllerClassCache = {};
+cc.BuilderReader.registerController = function (controllerName, controller) {
+ cc.BuilderReader._controllerClassCache[controllerName] = cc.Class.extend(controller);
+};
cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
ccbRootPath = ccbRootPath || cc.BuilderReader.getResourcePath();
var reader = new cc.BuilderReader(cc.NodeLoaderLibrary.newDefaultCCNodeLoaderLibrary());
reader.setCCBRootPath(ccbRootPath);
- if((ccbFilePath.length < 5)||(ccbFilePath.toLowerCase().lastIndexOf(".ccbi") != ccbFilePath.length - 5))
+ if ((ccbFilePath.length < 5) || (ccbFilePath.toLowerCase().lastIndexOf(".ccbi") !== ccbFilePath.length - 5))
ccbFilePath = ccbFilePath + ".ccbi";
var node = reader.readNodeGraphFromFile(ccbFilePath, owner, parentSize);
@@ -938,11 +967,13 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
// Callbacks
var ownerCallbackNames = reader.getOwnerCallbackNames();
var ownerCallbackNodes = reader.getOwnerCallbackNodes();
+ var ownerCallbackControlEvents = reader.getOwnerCallbackControlEvents();
for (i = 0; i < ownerCallbackNames.length; i++) {
callbackName = ownerCallbackNames[i];
callbackNode = ownerCallbackNodes[i];
- if(callbackNode instanceof cc.ControlButton)
- callbackNode.addTargetWithActionForControlEvents(owner, owner[callbackName], 255); //register all type of events
+ callbackControlEvents = ownerCallbackControlEvents[i];
+ if (callbackNode instanceof cc.ControlButton)
+ callbackNode.addTargetWithActionForControlEvents(owner, owner[callbackName], callbackControlEvents); //register all type of events
else
callbackNode.setCallback(owner[callbackName], owner);
}
@@ -959,8 +990,10 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
var nodesWithAnimationManagers = reader.getNodesWithAnimationManagers();
var animationManagersForNodes = reader.getAnimationManagersForNodes();
- if(!nodesWithAnimationManagers || !animationManagersForNodes)
+ if (!nodesWithAnimationManagers || !animationManagersForNodes)
return node;
+
+ var controllerClassCache = cc.BuilderReader._controllerClassCache;
// Attach animation managers to nodes and assign root node callbacks and member variables
for (i = 0; i < nodesWithAnimationManagers.length; i++) {
var innerNode = nodesWithAnimationManagers[i];
@@ -969,20 +1002,14 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
var j;
innerNode.animationManager = animationManager;
- var documentControllerName = animationManager.getDocumentControllerName();
- if (!documentControllerName) continue;
-
- // Create a document controller
- var controller;
- if(documentControllerName.indexOf(".") > -1){
- var controllerNameArr = documentControllerName.split(".");
- controller = _ccbGlobalContext[controllerNameArr[0]];
- for(var ni = 1, niLen = controllerNameArr.length - 1; ni < niLen; ni++)
- controller = controller[controllerNameArr[ni]];
- controller = new controller[controllerNameArr[controllerNameArr.length - 1]]();
- }else
- controller = new _ccbGlobalContext[documentControllerName]();
- controller.controllerName = documentControllerName;
+ var controllerName = animationManager.getDocumentControllerName();
+ if (!controllerName) continue;
+
+ // Create a controller
+ var controllerClass = controllerClassCache[controllerName];
+ if (!controllerClass) throw new Error("Can not find controller : " + controllerName);
+ var controller = new controllerClass();
+ controller.controllerName = controllerName;
innerNode.controller = controller;
controller.rootNode = innerNode;
@@ -995,7 +1022,7 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
callbackName = documentCallbackNames[j];
callbackNode = documentCallbackNodes[j];
callbackControlEvents = documentCallbackControlEvents[j];
- if(callbackNode instanceof cc.ControlButton)
+ if (callbackNode instanceof cc.ControlButton)
callbackNode.addTargetWithActionForControlEvents(controller, controller[callbackName], callbackControlEvents); //register all type of events
else
callbackNode.setCallback(controller[callbackName], controller);
@@ -1011,7 +1038,7 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
controller[outletName] = outletNode;
}
- if (controller.onDidLoadFromCCB && typeof(controller.onDidLoadFromCCB) == "function")
+ if (controller.onDidLoadFromCCB && cc.isFunction(controller.onDidLoadFromCCB))
controller.onDidLoadFromCCB();
// Setup timeline callbacks
@@ -1021,14 +1048,17 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) {
var callbackType = callbackSplit[0];
var kfCallbackName = callbackSplit[1];
- if (callbackType == 1){ // Document callback
- animationManager.setCallFunc(cc.CallFunc.create(controller[kfCallbackName], controller), keyframeCallbacks[j]);
+ if (callbackType == 1) { // Document callback
+ animationManager.setCallFunc(cc.callFunc(controller[kfCallbackName], controller), keyframeCallbacks[j]);
} else if (callbackType == 2 && owner) {// Owner callback
- animationManager.setCallFunc(cc.CallFunc.create(owner[kfCallbackName], owner), keyframeCallbacks[j]);
+ animationManager.setCallFunc(cc.callFunc(owner[kfCallbackName], owner), keyframeCallbacks[j]);
}
}
}
+ //auto play animations
+ animationManager.runAnimations(animationManager.getAutoPlaySequenceId(), 0);
+
return node;
};
@@ -1043,7 +1073,7 @@ cc.BuilderReader.getResourcePath = function () {
cc.BuilderReader.lastPathComponent = function (pathStr) {
var slashPos = pathStr.lastIndexOf("/");
- if (slashPos != -1) {
+ if (slashPos !== -1) {
return pathStr.substring(slashPos + 1, pathStr.length - slashPos);
}
return pathStr;
@@ -1051,7 +1081,7 @@ cc.BuilderReader.lastPathComponent = function (pathStr) {
cc.BuilderReader.deletePathExtension = function (pathStr) {
var dotPos = pathStr.lastIndexOf(".");
- if (dotPos != -1) {
+ if (dotPos !== -1) {
return pathStr.substring(0, dotPos);
}
return pathStr;
@@ -1063,7 +1093,7 @@ cc.BuilderReader.toLowerCase = function (sourceStr) {
cc.BuilderReader.endsWith = function (sourceStr, ending) {
if (sourceStr.length >= ending.length)
- return (sourceStr.lastIndexOf(ending) == 0);
+ return (sourceStr.lastIndexOf(ending) === 0);
else
return false;
};
@@ -1072,3 +1102,4 @@ cc.BuilderReader.concat = function (stringA, stringB) {
return stringA + stringB;
};
+cc.loader.register(["ccbi"], cc._binaryLoader);
diff --git a/extensions/CCBReader/CCBReaderUtil.js b/extensions/ccb-reader/CCBReaderUtil.js
similarity index 78%
rename from extensions/CCBReader/CCBReaderUtil.js
rename to extensions/ccb-reader/CCBReaderUtil.js
index ec327c8533..0de9c4fa30 100644
--- a/extensions/CCBReader/CCBReaderUtil.js
+++ b/extensions/ccb-reader/CCBReaderUtil.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -25,17 +25,22 @@
****************************************************************************/
cc.NodeLoaderListener = cc.Class.extend({
- onNodeLoaded:function(node,nodeLoader){}
+ onNodeLoaded: function (node, nodeLoader) {
+ }
});
cc.BuilderSelectorResolver = cc.Class.extend({
- onResolveCCBCCMenuItemSelector:function(target, selectorName){},
- onResolveCCBCCCallFuncSelector:function(target, selectorName){},
- onResolveCCBCCControlSelector:function(target,selectorName){}
+ onResolveCCBCCMenuItemSelector: function (target, selectorName) {
+ },
+ onResolveCCBCCCallFuncSelector: function (target, selectorName) {
+ },
+ onResolveCCBCCControlSelector: function (target, selectorName) {
+ }
});
cc.BuilderScriptOwnerProtocol = cc.Class.extend({
- createNew:function(){}
+ createNew: function () {
+ }
});
cc.BuilderMemberVariableAssigner = cc.Class.extend({
@@ -47,7 +52,9 @@ cc.BuilderMemberVariableAssigner = cc.Class.extend({
* @param {cc.Node} node The member variable.
* @return {Boolean} Whether the assignment was successful.
*/
- onAssignCCBMemberVariable:function(target,memberVariableName, node){ return false;},
+ onAssignCCBMemberVariable: function (target, memberVariableName, node) {
+ return false;
+ },
/**
* The callback function of assigning custom properties.
@@ -57,5 +64,7 @@ cc.BuilderMemberVariableAssigner = cc.Class.extend({
* @param {*} value The value of the property.
* @return {Boolean} Whether the assignment was successful.
*/
- onAssignCCBCustomProperty:function(target, memberVariableName, value){ return false; }
+ onAssignCCBCustomProperty: function (target, memberVariableName, value) {
+ return false;
+ }
});
diff --git a/extensions/CCBReader/CCBRelativePositioning.js b/extensions/ccb-reader/CCBRelativePositioning.js
similarity index 58%
rename from extensions/CCBReader/CCBRelativePositioning.js
rename to extensions/ccb-reader/CCBRelativePositioning.js
index c23351eadd..ed0d29a255 100644
--- a/extensions/CCBReader/CCBRelativePositioning.js
+++ b/extensions/ccb-reader/CCBRelativePositioning.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -24,40 +24,15 @@
THE SOFTWARE.
****************************************************************************/
-cc.getAbsolutePosition = function(pt, type, containerSize, propName){
- var absPt = cc.p(0,0);
- if(type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT)
- absPt = pt;
- else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_LEFT){
- absPt.x = pt.x;
- absPt.y = containerSize.height - pt.y;
- } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT){
- absPt.x = containerSize.width - pt.x;
- absPt.y = containerSize.height - pt.y;
- } else if (type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT) {
- absPt.x = containerSize.width - pt.x;
- absPt.y = pt.y;
- } else if (type === CCB_POSITIONTYPE_PERCENT) {
- absPt.x = (containerSize.width * pt.x / 100.0);
- absPt.y = (containerSize.height * pt.y / 100.0);
- } else if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) {
- var resolutionScale = cc.BuilderReader.getResolutionScale();
- absPt.x = pt.x * resolutionScale;
- absPt.y = pt.y * resolutionScale;
- }
-
- return absPt;
-};
-
-cc._getAbsolutePosition = function(x, y, type, containerSize, propName){
- var absPt = cc.p(0,0);
- if(type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT){
+cc.getAbsolutePosition = function (x, y, type, containerSize, propName, out) {
+ var absPt = out || cc.p(0, 0);
+ if (type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT) {
absPt.x = x;
absPt.y = y;
- } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_LEFT){
+ } else if (type === CCB_POSITIONTYPE_RELATIVE_TOP_LEFT) {
absPt.x = x;
absPt.y = containerSize.height - y;
- } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT){
+ } else if (type === CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT) {
absPt.x = containerSize.width - x;
absPt.y = containerSize.height - y;
} else if (type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT) {
@@ -74,8 +49,9 @@ cc._getAbsolutePosition = function(x, y, type, containerSize, propName){
return absPt;
};
-cc.setRelativeScale = function(node,scaleX, scaleY, type, propName){
- cc.Assert(node, "pNode should not be null");
+cc.setRelativeScale = function (node, scaleX, scaleY, type, propName) {
+ if (!node)
+ throw new Error("cc.setRelativeScale(): node should be non-null");
if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) {
var resolutionScale = cc.BuilderReader.getResolutionScale();
@@ -84,6 +60,5 @@ cc.setRelativeScale = function(node,scaleX, scaleY, type, propName){
scaleY *= resolutionScale;
}
- node.setScaleX(scaleX);
- node.setScaleY(scaleY);
-};
\ No newline at end of file
+ node.setScale(scaleX, scaleY);
+};
diff --git a/extensions/CCBReader/CCBSequence.js b/extensions/ccb-reader/CCBSequence.js
similarity index 97%
rename from extensions/CCBReader/CCBSequence.js
rename to extensions/ccb-reader/CCBSequence.js
index b991c48e4b..a1bc0e2734 100644
--- a/extensions/CCBReader/CCBSequence.js
+++ b/extensions/ccb-reader/CCBSequence.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
diff --git a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollInterface.js b/extensions/ccb-reader/CCBValue.js
similarity index 66%
rename from extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollInterface.js
rename to extensions/ccb-reader/CCBValue.js
index f14ad8e473..dee4c7ba71 100644
--- a/extensions/CocoStudio/GUI/UIWidgets/ScrollWidget/UIScrollInterface.js
+++ b/extensions/ccb-reader/CCBValue.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,17 +24,37 @@
THE SOFTWARE.
****************************************************************************/
-cc.UIScrollInterface = cc.Class.extend({
- handlePressLogic:function(touchPoint){
+cc.INT_VALUE = 0;
- },
- handleMoveLogic:function(touchPoint){
+cc.FLOAT_VALUE = 1;
- },
- handleReleaseLogic:function(touchPoint){
+cc.POINTER_VALUE = 2;
+
+cc.BOOL_VALUE = 3;
+cc.UNSIGNEDCHAR_VALUE = 4;
+
+cc.BuilderValue = cc.Class.extend({
+ _value: null,
+ _type: 0,
+
+ getIntValue: function () {
+ },
+ getFloatValue: function () {
+ },
+ getBoolValue: function () {
+ },
+ getByteValue: function () {
+ },
+ getPointer: function () {
},
- interceptTouchEvent:function( handleState, sender, touchPoint){
+ getValue: function () {
+ return this._value;
}
-});
\ No newline at end of file
+});
+
+cc.BuilderValue.create = function (value) {
+ return new cc.BuilderValue();
+};
+
diff --git a/extensions/CCBReader/CCControlLoader.js b/extensions/ccb-reader/CCControlLoader.js
similarity index 62%
rename from extensions/CCBReader/CCControlLoader.js
rename to extensions/ccb-reader/CCControlLoader.js
index 4ebbec628e..3b1a5d6518 100644
--- a/extensions/CCBReader/CCControlLoader.js
+++ b/extensions/ccb-reader/CCControlLoader.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -27,12 +27,14 @@
var PROPERTY_CCBFILE = "ccbFile";
cc.BuilderFileLoader = cc.NodeLoader.extend({
- _createCCNode:function (parent, ccbReader) {
- return cc.BuilderFile.create();
+ _createCCNode: function (parent, ccbReader) {
+ var node = new cc.Node();
+ node.ccbFileNode = null;
+ return node;
},
- onHandlePropTypeCCBFile:function (node, parent, propertyName, ccbFileNode, ccbReader) {
- if (propertyName == PROPERTY_CCBFILE) {
- node.setCCBFileNode(ccbFileNode);
+ onHandlePropTypeCCBFile: function (node, parent, propertyName, ccbFileNode, ccbReader) {
+ if (propertyName === PROPERTY_CCBFILE) {
+ node.ccbFileNode = ccbFileNode;
} else {
cc.NodeLoader.prototype.onHandlePropTypeCCBFile.call(this, node, parent, propertyName, ccbFileNode, ccbReader);
}
@@ -48,19 +50,19 @@ var PROPERTY_SELECTED = "selected";
var PROPERTY_CCCONTROL = "ccControl";
cc.ControlLoader = cc.NodeLoader.extend({
- _createCCNode:function (parent, ccbReander) {
+ _createCCNode: function (parent, ccbReander) {
},
- onHandlePropTypeBlockCCControl:function (node, parent, propertyName, blockCCControlData, ccbReader) {
- if (propertyName == PROPERTY_CCCONTROL) {
+ onHandlePropTypeBlockCCControl: function (node, parent, propertyName, blockCCControlData, ccbReader) {
+ if (propertyName === PROPERTY_CCCONTROL) {
node.addTargetWithActionForControlEvents(blockCCControlData.target, blockCCControlData.selCCControlHandler, blockCCControlData.controlEvents);
} else {
cc.NodeLoader.prototype.onHandlePropTypeBlockCCControl.call(this, node, parent, propertyName, blockCCControlData, ccbReader);
}
},
- onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
- if (propertyName == PROPERTY_ENABLED) {
+ onHandlePropTypeCheck: function (node, parent, propertyName, check, ccbReader) {
+ if (propertyName === PROPERTY_ENABLED) {
node.setEnabled(check);
- } else if (propertyName == PROPERTY_SELECTED) {
+ } else if (propertyName === PROPERTY_SELECTED) {
node.setSelected(check);
} else {
cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
@@ -88,74 +90,74 @@ var PROPERTY_BACKGROUNDSPRITEFRAME_HIGHLIGHTED = "backgroundSpriteFrame|2";
var PROPERTY_BACKGROUNDSPRITEFRAME_DISABLED = "backgroundSpriteFrame|3";
cc.ControlButtonLoader = cc.ControlLoader.extend({
- _createCCNode:function (parent, ccbReader) {
- return cc.ControlButton.create();
+ _createCCNode: function (parent, ccbReader) {
+ return new cc.ControlButton();
},
- onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
- if (propertyName == PROPERTY_ZOOMONTOUCHDOWN) {
- node.setZoomOnTouchDown(check);
+ onHandlePropTypeCheck: function (node, parent, propertyName, check, ccbReader) {
+ if (propertyName === PROPERTY_ZOOMONTOUCHDOWN) {
+ node.zoomOnTouchDown = check;
} else {
cc.ControlLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
}
},
- onHandlePropTypeString:function (node, parent, propertyName, stringValue, ccbReader) {
- if (propertyName == PROPERTY_TITLE_NORMAL) {
+ onHandlePropTypeString: function (node, parent, propertyName, stringValue, ccbReader) {
+ if (propertyName === PROPERTY_TITLE_NORMAL) {
node.setTitleForState(stringValue, cc.CONTROL_STATE_NORMAL);
- } else if (propertyName == PROPERTY_TITLE_HIGHLIGHTED) {
+ } else if (propertyName === PROPERTY_TITLE_HIGHLIGHTED) {
node.setTitleForState(stringValue, cc.CONTROL_STATE_HIGHLIGHTED);
- } else if (propertyName == PROPERTY_TITLE_DISABLED) {
+ } else if (propertyName === PROPERTY_TITLE_DISABLED) {
node.setTitleForState(stringValue, cc.CONTROL_STATE_DISABLED);
} else {
cc.ControlLoader.prototype.onHandlePropTypeString.call(this, node, parent, propertyName, stringValue, ccbReader);
}
},
- onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) {
- if (propertyName == PROPERTY_TITLETTF_NORMAL) {
+ onHandlePropTypeFontTTF: function (node, parent, propertyName, fontTTF, ccbReader) {
+ if (propertyName === PROPERTY_TITLETTF_NORMAL) {
node.setTitleTTFForState(fontTTF, cc.CONTROL_STATE_NORMAL);
- } else if (propertyName == PROPERTY_TITLETTF_HIGHLIGHTED) {
+ } else if (propertyName === PROPERTY_TITLETTF_HIGHLIGHTED) {
node.setTitleTTFForState(fontTTF, cc.CONTROL_STATE_HIGHLIGHTED);
- } else if (propertyName == PROPERTY_TITLETTF_DISABLED) {
+ } else if (propertyName === PROPERTY_TITLETTF_DISABLED) {
node.setTitleTTFForState(fontTTF, cc.CONTROL_STATE_DISABLED);
} else {
cc.ControlLoader.prototype.onHandlePropTypeFontTTF.call(this, node, parent, propertyName, fontTTF, ccbReader);
}
},
- onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) {
- if (propertyName == PROPERTY_TITLETTFSIZE_NORMAL) {
+ onHandlePropTypeFloatScale: function (node, parent, propertyName, floatScale, ccbReader) {
+ if (propertyName === PROPERTY_TITLETTFSIZE_NORMAL) {
node.setTitleTTFSizeForState(floatScale, cc.CONTROL_STATE_NORMAL);
- } else if (propertyName == PROPERTY_TITLETTFSIZE_HIGHLIGHTED) {
+ } else if (propertyName === PROPERTY_TITLETTFSIZE_HIGHLIGHTED) {
node.setTitleTTFSizeForState(floatScale, cc.CONTROL_STATE_HIGHLIGHTED);
- } else if (propertyName == PROPERTY_TITLETTFSIZE_DISABLED) {
+ } else if (propertyName === PROPERTY_TITLETTFSIZE_DISABLED) {
node.setTitleTTFSizeForState(floatScale, cc.CONTROL_STATE_DISABLED);
} else {
cc.ControlLoader.prototype.onHandlePropTypeFloatScale.call(this, node, parent, propertyName, floatScale, ccbReader);
}
},
- onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) {
- if (propertyName == PROPERTY_LABELANCHORPOINT) {
+ onHandlePropTypePoint: function (node, parent, propertyName, point, ccbReader) {
+ if (propertyName === PROPERTY_LABELANCHORPOINT) {
node.setLabelAnchorPoint(point);
} else {
cc.ControlLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader);
}
},
- onHandlePropTypeSize:function (node, parent, propertyName, size, ccbReader) {
- if (propertyName == PROPERTY_PREFEREDSIZE) {
+ onHandlePropTypeSize: function (node, parent, propertyName, size, ccbReader) {
+ if (propertyName === PROPERTY_PREFEREDSIZE) {
node.setPreferredSize(size);
} else {
cc.ControlLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader);
}
},
- onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) {
- if (propertyName == PROPERTY_BACKGROUNDSPRITEFRAME_NORMAL) {
+ onHandlePropTypeSpriteFrame: function (node, parent, propertyName, spriteFrame, ccbReader) {
+ if (propertyName === PROPERTY_BACKGROUNDSPRITEFRAME_NORMAL) {
if (spriteFrame != null) {
node.setBackgroundSpriteFrameForState(spriteFrame, cc.CONTROL_STATE_NORMAL);
}
- } else if (propertyName == PROPERTY_BACKGROUNDSPRITEFRAME_HIGHLIGHTED) {
+ } else if (propertyName === PROPERTY_BACKGROUNDSPRITEFRAME_HIGHLIGHTED) {
if (spriteFrame != null) {
node.setBackgroundSpriteFrameForState(spriteFrame, cc.CONTROL_STATE_HIGHLIGHTED);
}
- } else if (propertyName == PROPERTY_BACKGROUNDSPRITEFRAME_DISABLED) {
+ } else if (propertyName === PROPERTY_BACKGROUNDSPRITEFRAME_DISABLED) {
if (spriteFrame != null) {
node.setBackgroundSpriteFrameForState(spriteFrame, cc.CONTROL_STATE_DISABLED);
}
@@ -163,12 +165,12 @@ cc.ControlButtonLoader = cc.ControlLoader.extend({
cc.ControlLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame, ccbReader);
}
},
- onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
- if (propertyName == PROPERTY_TITLECOLOR_NORMAL) {
+ onHandlePropTypeColor3: function (node, parent, propertyName, ccColor3B, ccbReader) {
+ if (propertyName === PROPERTY_TITLECOLOR_NORMAL) {
node.setTitleColorForState(ccColor3B, cc.CONTROL_STATE_NORMAL);
- } else if (propertyName == PROPERTY_TITLECOLOR_HIGHLIGHTED) {
+ } else if (propertyName === PROPERTY_TITLECOLOR_HIGHLIGHTED) {
node.setTitleColorForState(ccColor3B, cc.CONTROL_STATE_HIGHLIGHTED);
- } else if (propertyName == PROPERTY_TITLECOLOR_DISABLED) {
+ } else if (propertyName === PROPERTY_TITLECOLOR_DISABLED) {
node.setTitleColorForState(ccColor3B, cc.CONTROL_STATE_DISABLED);
} else {
cc.ControlLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
@@ -187,44 +189,44 @@ var PROPERTY_BOUNCES = "bounces";
var PROPERTY_SCALE = "scale";
cc.ScrollViewLoader = cc.NodeLoader.extend({
- _createCCNode:function (parent, ccbReader) {
- return cc.ScrollView.create();
+ _createCCNode: function (parent, ccbReader) {
+ return new cc.ScrollView();
},
- onHandlePropTypeSize:function(node,parent,propertyName,size,ccbReader){
- if(propertyName == PROPERTY_CONTENTSIZE){
+ onHandlePropTypeSize: function (node, parent, propertyName, size, ccbReader) {
+ if (propertyName === PROPERTY_CONTENTSIZE) {
node.setViewSize(size);
- }else{
- cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node,parent,propertyName.size,ccbReader);
+ } else {
+ cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader);
}
},
- onHandlePropTypeCCBFile:function (node, parent, propertyName, ccbFileNode, ccbReader) {
- if (propertyName == PROPERTY_CONTAINER) {
+ onHandlePropTypeCCBFile: function (node, parent, propertyName, ccbFileNode, ccbReader) {
+ if (propertyName === PROPERTY_CONTAINER) {
node.setContainer(ccbFileNode);
node.updateInset();
} else {
cc.NodeLoader.prototype.onHandlePropTypeCCBFile.call(this, node, parent, propertyName, ccbFileNode, ccbReader);
}
},
- onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
- if (propertyName == PROPERTY_CLIPSTOBOUNDS) {
+ onHandlePropTypeCheck: function (node, parent, propertyName, check, ccbReader) {
+ if (propertyName === PROPERTY_CLIPSTOBOUNDS) {
node.setClippingToBounds(check);
- } else if (propertyName == PROPERTY_BOUNCES) {
+ } else if (propertyName === PROPERTY_BOUNCES) {
node.setBounceable(check);
} else {
cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader);
}
},
- onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) {
- if (propertyName == PROPERTY_SCALE) {
+ onHandlePropTypeFloat: function (node, parent, propertyName, floatValue, ccbReader) {
+ if (propertyName === PROPERTY_SCALE) {
node.setScale(floatValue);
} else {
cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue, ccbReader);
}
},
- onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) {
- if (propertyName == PROPERTY_DIRECTION) {
+ onHandlePropTypeIntegerLabeled: function (node, parent, propertyName, integerLabeled, ccbReader) {
+ if (propertyName === PROPERTY_DIRECTION) {
node.setDirection(integerLabeled);
} else {
cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader);
@@ -242,72 +244,76 @@ var PROPERTY_COLOR = "color";
var PROPERTY_OPACITY = "opacity";
var PROPERTY_BLENDFUNC = "blendFunc";
var PROPERTY_INSETLEFT = "insetLeft";
-var PROPERTY_INSETTOP = "insetTop" ;
+var PROPERTY_INSETTOP = "insetTop";
var PROPERTY_INSETRIGHT = "insetRight";
var PROPERTY_INSETBOTTOM = "insetBottom";
cc.Scale9SpriteLoader = cc.NodeLoader.extend({
- _createCCNode:function(parent,ccbReader){
- return cc.Scale9Sprite.create();
+ _createCCNode: function (parent, ccbReader) {
+ var sprite = new cc.Scale9Sprite();
+
+ sprite.setAnchorPoint(0, 0);
+
+ return sprite;
},
- onHandlePropTypeColor3:function(node, parent, propertyName, ccColor3B,ccbReader){
- if(propertyName == PROPERTY_COLOR) {
- if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){
+ onHandlePropTypeColor3: function (node, parent, propertyName, ccColor3B, ccbReader) {
+ if (propertyName === PROPERTY_COLOR) {
+ if (ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255) {
node.setColor(ccColor3B);
}
} else {
- cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B,ccbReader);
+ cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
}
},
- onHandlePropTypeByte:function(node, parent, propertyName, byteValue,ccbReader){
- if(propertyName == PROPERTY_OPACITY) {
+ onHandlePropTypeByte: function (node, parent, propertyName, byteValue, ccbReader) {
+ if (propertyName === PROPERTY_OPACITY) {
node.setOpacity(byteValue);
} else {
- cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue,ccbReader);
+ cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader);
}
},
- onHandlePropTypeBlendFunc:function(node, parent, propertyName, ccBlendFunc,ccbReader){
- if(propertyName == PROPERTY_BLENDFUNC) {
+ onHandlePropTypeBlendFunc: function (node, parent, propertyName, ccBlendFunc, ccbReader) {
+ if (propertyName === PROPERTY_BLENDFUNC) {
// TODO Not exported by CocosBuilder yet!
// node.setBlendFunc(ccBlendFunc);
} else {
- cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc,ccbReader);
+ cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader);
}
},
- onHandlePropTypeSpriteFrame:function(node, parent, propertyName, spriteFrame,ccbReader){
- if(propertyName == PROPERTY_SPRITEFRAME) {
+ onHandlePropTypeSpriteFrame: function (node, parent, propertyName, spriteFrame, ccbReader) {
+ if (propertyName === PROPERTY_SPRITEFRAME) {
node.setSpriteFrame(spriteFrame);
} else {
- cc.NodeLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame,ccbReader);
+ cc.NodeLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame, ccbReader);
}
},
- onHandlePropTypeSize:function(node, parent, propertyName, size,ccbReader){
- if(propertyName == PROPERTY_CONTENTSIZE) {
+ onHandlePropTypeSize: function (node, parent, propertyName, size, ccbReader) {
+ if (propertyName === PROPERTY_CONTENTSIZE) {
//node.setContentSize(size);
- } else if(propertyName == PROPERTY_PREFEREDSIZE) {
+ } else if (propertyName === PROPERTY_PREFEREDSIZE) {
node.setPreferredSize(size);
} else {
- cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size,ccbReader);
+ cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader);
}
},
- onHandlePropTypeFloat:function(node, parent, propertyName, floatValue,ccbReader){
- if(propertyName == PROPERTY_INSETLEFT) {
+ onHandlePropTypeFloat: function (node, parent, propertyName, floatValue, ccbReader) {
+ if (propertyName === PROPERTY_INSETLEFT) {
node.setInsetLeft(floatValue);
- } else if(propertyName == PROPERTY_INSETTOP) {
+ } else if (propertyName === PROPERTY_INSETTOP) {
node.setInsetTop(floatValue);
- } else if(propertyName == PROPERTY_INSETRIGHT) {
+ } else if (propertyName === PROPERTY_INSETRIGHT) {
node.setInsetRight(floatValue);
- } else if(propertyName == PROPERTY_INSETBOTTOM) {
+ } else if (propertyName === PROPERTY_INSETBOTTOM) {
node.setInsetBottom(floatValue);
} else {
- cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue,ccbReader);
+ cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue, ccbReader);
}
}
});
-cc.Scale9SpriteLoader.loader = function(){
- return new cc.Scale9SpriteLoader();
+cc.Scale9SpriteLoader.loader = function () {
+ return new cc.Scale9SpriteLoader();
};
diff --git a/extensions/CCBReader/CCNodeLoader.js b/extensions/ccb-reader/CCNodeLoader.js
similarity index 64%
rename from extensions/CCBReader/CCNodeLoader.js
rename to extensions/ccb-reader/CCNodeLoader.js
index 2bdbb32ddc..afa434b4d2 100644
--- a/extensions/CCBReader/CCNodeLoader.js
+++ b/extensions/ccb-reader/CCNodeLoader.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -36,12 +36,10 @@ var PROPERTY_VISIBLE = "visible";
var ASSERT_FAIL_UNEXPECTED_PROPERTY = function (propertyName) {
cc.log("Unexpected property: '" + propertyName + "'!");
- cc.Assert(false, "Unexpected property: '" + propertyName + "'!");
};
var ASSERT_FAIL_UNEXPECTED_PROPERTYTYPE = function (propertyName) {
cc.log("Unexpected property type: '" + propertyName + "'!");
- cc.Assert(false, "Unexpected property type: '" + propertyName + "'!");
};
function BlockData(selMenuHander, target) {
@@ -56,19 +54,30 @@ function BlockCCControlData(selCCControlHandler, target, controlEvents) {
}
cc.NodeLoader = cc.Class.extend({
- _customProperties:null,
+ _customProperties: null,
+ _pt: null,
+ _size: null,
+ _arr2: null,
- ctor:function(){
+ ctor: function () {
this._customProperties = new cc._Dictionary();
+ this._pt = cc.p();
+ this._size = cc.size();
+ this._arr2 = new Array(2);
+ this._blockControlData = {
+ selCCControlHandler: null,
+ target: null,
+ controlEvents: null
+ };
},
- loadCCNode:function (parent, ccbReader) {
+ loadCCNode: function (parent, ccbReader) {
return this._createCCNode(parent, ccbReader);
//this.parseProperties(node, parent, ccbReader);
//return node;
},
- parseProperties:function (node, parent, ccbReader) {
+ parseProperties: function (node, parent, ccbReader) {
var numRegularProps = ccbReader.readInt(false);
var numExturaProps = ccbReader.readInt(false);
var propertyCount = numRegularProps + numExturaProps;
@@ -81,26 +90,26 @@ cc.NodeLoader = cc.Class.extend({
// Check if the property can be set for this platform
var setProp = false;
- var platform = ccbReader.readByte();
- if ((platform === CCB_PLATFORM_ALL) ||(platform === CCB_PLATFORM_IOS) ||(platform === CCB_PLATFORM_MAC) )
+ var platform = ccbReader._data[ccbReader._currentByte++];
+ if ((platform === CCB_PLATFORM_ALL) || (platform === CCB_PLATFORM_IOS) || (platform === CCB_PLATFORM_MAC))
setProp = true;
//forward properties for sub ccb files
- if(node instanceof cc.BuilderFile){
- if(node.getCCBFileNode() && isExtraProp){
- node = node.getCCBFileNode();
+ if (isExtraProp) {
+ if (node.ccbFileNode) {
+ node = node.ccbFileNode;
//skip properties that doesn't have a value to override
- var getExtraPropsNames = node.getUserObject();
- setProp = cc.ArrayContainsObject(getExtraPropsNames,propertyName);
- }
- } else if(isExtraProp && node == ccbReader.getAnimationManager().getRootNode()){
- var extraPropsNames = node.getUserObject();
- if(!extraPropsNames){
- extraPropsNames = [];
- node.setUserObject(extraPropsNames);
+ var getExtraPropsNames = node.userObject;
+ setProp = getExtraPropsNames.indexOf(propertyName) !== -1;
+ } else if (node === ccbReader._animationManager.getRootNode()) {
+ var extraPropsNames = node.userObject;
+ if (!extraPropsNames) {
+ extraPropsNames = [];
+ node.userObject = extraPropsNames;
+ }
+ extraPropsNames.push(propertyName);
}
- extraPropsNames.push(propertyName);
- }
+ }
switch (type) {
case CCB_PROPTYPE_POSITION:
@@ -236,9 +245,9 @@ cc.NodeLoader = cc.Class.extend({
}
case CCB_PROPTYPE_COLOR3:
{
- var color3B = this.parsePropTypeColor3(node, parent, ccbReader, propertyName);
+ var color = this.parsePropTypeColor3(node, parent, ccbReader, propertyName);
if (setProp) {
- this.onHandlePropTypeColor3(node, parent, propertyName, color3B, ccbReader);
+ this.onHandlePropTypeColor3(node, parent, propertyName, color, ccbReader);
}
break;
}
@@ -329,53 +338,52 @@ cc.NodeLoader = cc.Class.extend({
}
},
- getCustomProperties:function(){
+ getCustomProperties: function () {
return this._customProperties;
},
- _createCCNode:function (parent, ccbReader) {
- return cc.Node.create();
+ _createCCNode: function (parent, ccbReader) {
+ return new cc.Node();
},
- parsePropTypePosition:function (node, parent, ccbReader, propertyName) {
+ parsePropTypePosition: function (node, parent, ccbReader, propertyName) {
var x = ccbReader.readFloat();
var y = ccbReader.readFloat();
var type = ccbReader.readInt(false);
- var containerSize = ccbReader.getAnimationManager().getContainerSize(parent);
- var pt = cc._getAbsolutePosition(x,y,type,containerSize,propertyName);
- node.setPosition(cc.getAbsolutePosition(pt,type,containerSize,propertyName)); //different to -x node.setPosition(pt);
+ // var containerSize = ccbReader._animationManager.getContainerSize(parent);
+ var containerSize = parent ? parent._contentSize : ccbReader._animationManager._rootContainerSize;
+ cc.getAbsolutePosition(x, y, type, containerSize, propertyName, this._pt);
+ node.setPosition(this._pt);
- if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
- var baseValue = [x,y,type];
- ccbReader.getAnimationManager().setBaseValue(baseValue,node,propertyName);
+ if (ccbReader._animatedProps.indexOf(propertyName) > -1) {
+ var baseValue = [x, y, type];
+ ccbReader._animationManager.setBaseValue(baseValue, node, propertyName);
}
-
- return pt;
+ return this._pt;
},
- parsePropTypePoint:function (node, parent, ccbReader) {
- var x = ccbReader.readFloat();
- var y = ccbReader.readFloat();
-
- return new cc.Point(x, y);
+ parsePropTypePoint: function (node, parent, ccbReader) {
+ this._pt.x = ccbReader.readFloat();
+ this._pt.y = ccbReader.readFloat();
+ return this._pt;
},
- parsePropTypePointLock:function (node, parent, ccbReader) {
- var x = ccbReader.readFloat();
- var y = ccbReader.readFloat();
-
- return new cc.Point(x, y);
+ parsePropTypePointLock: function (node, parent, ccbReader) {
+ this._pt.x = ccbReader.readFloat();
+ this._pt.y = ccbReader.readFloat();
+ return this._pt;
},
- parsePropTypeSize:function (node, parent, ccbReader) {
+ parsePropTypeSize: function (node, parent, ccbReader) {
var width = ccbReader.readFloat();
var height = ccbReader.readFloat();
var type = ccbReader.readInt(false);
- var containerSize = ccbReader.getAnimationManager().getContainerSize(parent);
+ // var containerSize = ccbReader._animationManager.getContainerSize(parent);
+ var containerSize = parent ? parent._contentSize : ccbReader._animationManager._rootContainerSize;
switch (type) {
case CCB_SIZETYPE_ABSOLUTE:
@@ -404,109 +412,112 @@ cc.NodeLoader = cc.Class.extend({
cc.log("Unknown CCB type.");
break;
}
-
- return new cc.Size(width, height);
+ this._size.width = width;
+ this._size.height = height;
+ return this._size;
},
- parsePropTypeScaleLock:function (node, parent, ccbReader, propertyName) {
+ parsePropTypeScaleLock: function (node, parent, ccbReader, propertyName) {
var x = ccbReader.readFloat();
var y = ccbReader.readFloat();
var type = ccbReader.readInt(false);
- cc.setRelativeScale(node,x,y,type,propertyName);
+ // cc.setRelativeScale(node, x, y, type, propertyName);
- if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
- ccbReader.getAnimationManager().setBaseValue([x,y,type],node,propertyName);
+ if (ccbReader._animatedProps.indexOf(propertyName) > -1) {
+ ccbReader._animationManager.setBaseValue([x, y, type], node, propertyName);
}
- if (type == CCB_SCALETYPE_MULTIPLY_RESOLUTION) {
- x *= cc.BuilderReader.getResolutionScale();
- y *= cc.BuilderReader.getResolutionScale();
+ if (type === CCB_SCALETYPE_MULTIPLY_RESOLUTION) {
+ var resolutionScale = cc.BuilderReader.getResolutionScale();
+ x *= resolutionScale;
+ y *= resolutionScale;
}
-
- return [x, y];
+ this._pt.x = x;
+ this._pt.y = y;
+ return this._pt;
},
- parsePropTypeFloat:function (node, parent, ccbReader) {
+ parsePropTypeFloat: function (node, parent, ccbReader) {
return ccbReader.readFloat();
},
- parsePropTypeDegrees:function (node, parent, ccbReader, propertyName) {
- var ret = ccbReader.readFloat();
- if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
- ccbReader.getAnimationManager().setBaseValue(ret,node, propertyName);
+ parsePropTypeDegrees: function (node, parent, ccbReader, propertyName) {
+ var degrees = ccbReader.readFloat();
+ if (ccbReader._animatedProps.indexOf(propertyName) > -1) {
+ ccbReader._animationManager.setBaseValue(degrees, node, propertyName);
}
- return ret;
+ return degrees;
},
- parsePropTypeFloatScale:function (node, parent, ccbReader) {
+ parsePropTypeFloatScale: function (node, parent, ccbReader) {
var f = ccbReader.readFloat();
var type = ccbReader.readInt(false);
- if (type == CCB_SCALETYPE_MULTIPLY_RESOLUTION) {
+ if (type === CCB_SCALETYPE_MULTIPLY_RESOLUTION) {
f *= cc.BuilderReader.getResolutionScale();
}
return f;
},
- parsePropTypeInteger:function (node, parent, ccbReader) {
+ parsePropTypeInteger: function (node, parent, ccbReader) {
return ccbReader.readInt(true);
},
- parsePropTypeIntegerLabeled:function (node, parent, ccbReader) {
+ parsePropTypeIntegerLabeled: function (node, parent, ccbReader) {
return ccbReader.readInt(true);
},
- parsePropTypeFloatVar:function (node, parent, ccbReader) {
- var f = ccbReader.readFloat();
- var fVar = ccbReader.readFloat();
- return [f, fVar];
+ parsePropTypeFloatVar: function (node, parent, ccbReader) {
+ this._arr2[0] = ccbReader.readFloat();
+ this._arr2[1] = ccbReader.readFloat();
+ return this._arr2;
},
- parsePropTypeCheck:function (node, parent, ccbReader, propertyName) {
- var ret = ccbReader.readBool();
- if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
- ccbReader.getAnimationManager().setBaseValue(ret,node, propertyName);
+ parsePropTypeCheck: function (node, parent, ccbReader, propertyName) {
+ var check = !!ccbReader._data[ccbReader._currentByte++];
+ if (ccbReader._animatedProps.indexOf(propertyName) > -1) {
+ ccbReader._animationManager.setBaseValue(check, node, propertyName);
}
- return ret;
+ return check;
},
- parsePropTypeSpriteFrame:function (node, parent, ccbReader, propertyName) {
+ parsePropTypeSpriteFrame: function (node, parent, ccbReader, propertyName) {
var spriteSheet = ccbReader.readCachedString();
- var spriteFile = ccbReader.readCachedString();
+ var spriteFile = ccbReader.readCachedString();
var spriteFrame;
- if(spriteFile != null && spriteFile.length != 0){
- if(spriteSheet.length == 0){
- spriteFile = ccbReader.getCCBRootPath() + spriteFile;
- var texture = cc.TextureCache.getInstance().addImage(spriteFile);
+ if (spriteFile) {
+ if (spriteSheet.length === 0) {
+ spriteFile = ccbReader._ccbRootPath + spriteFile;
+ var texture = cc.textureCache.addImage(spriteFile);
var locContentSize = texture.getContentSize();
var bounds = cc.rect(0, 0, locContentSize.width, locContentSize.height);
- spriteFrame = cc.SpriteFrame.createWithTexture(texture, bounds);
+ spriteFrame = new cc.SpriteFrame(texture, bounds);
} else {
- var frameCache = cc.SpriteFrameCache.getInstance();
- spriteSheet = ccbReader.getCCBRootPath() + spriteSheet;
+ var frameCache = cc.spriteFrameCache;
+ spriteSheet = ccbReader._ccbRootPath + spriteSheet;
//load the sprite sheet only if it is not loaded
- if(ccbReader.getLoadedSpriteSheet().indexOf(spriteSheet) == -1){
+ if (ccbReader._loadedSpriteSheets.indexOf(spriteSheet) === -1) {
frameCache.addSpriteFrames(spriteSheet);
- ccbReader.getLoadedSpriteSheet().push(spriteSheet);
+ ccbReader._loadedSpriteSheets.push(spriteSheet);
}
spriteFrame = frameCache.getSpriteFrame(spriteFile);
}
- if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
- ccbReader.getAnimationManager().setBaseValue(spriteFrame,node,propertyName);
+ if (ccbReader._animatedProps.indexOf(propertyName) > -1) {
+ ccbReader._animationManager.setBaseValue(spriteFrame, node, propertyName);
}
}
return spriteFrame;
},
- parsePropTypeAnimation:function (node, parent, ccbReader) {
- var animationFile = ccbReader.getCCBRootPath() + ccbReader.readCachedString();
+ parsePropTypeAnimation: function (node, parent, ccbReader) {
+ var animationFile = ccbReader._ccbRootPath + ccbReader.readCachedString();
var animation = ccbReader.readCachedString();
var ccAnimation = null;
@@ -519,8 +530,8 @@ cc.NodeLoader = cc.Class.extend({
animation = cc.BuilderReader.lastPathComponent(animation);
animationFile = cc.BuilderReader.lastPathComponent(animationFile);
- if (animation != null && animation != "") {
- var animationCache = cc.AnimationCache.getInstance();
+ if (animation) {
+ var animationCache = cc.animationCache;
animationCache.addAnimations(animationFile);
ccAnimation = animationCache.getAnimation(animation);
@@ -528,77 +539,79 @@ cc.NodeLoader = cc.Class.extend({
return ccAnimation;
},
- parsePropTypeTexture:function (node, parent, ccbReader) {
- var spriteFile = ccbReader.getCCBRootPath() + ccbReader.readCachedString();
+ parsePropTypeTexture: function (node, parent, ccbReader) {
+ var spriteFile = ccbReader._ccbRootPath + ccbReader.readCachedString();
- if(spriteFile != "")
- return cc.TextureCache.getInstance().addImage(spriteFile);
+ if (spriteFile)
+ return cc.textureCache.addImage(spriteFile);
return null;
},
- parsePropTypeByte:function (node, parent, ccbReader, propertyName) {
- var ret = ccbReader.readByte();
- if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
- ccbReader.getAnimationManager().setBaseValue(ret,node, propertyName);
+ parsePropTypeByte: function (node, parent, ccbReader, propertyName) {
+ var ret = ccbReader._data[ccbReader._currentByte++];
+ if (ccbReader._animatedProps.indexOf(propertyName) > -1) {
+ ccbReader._animationManager.setBaseValue(ret, node, propertyName);
}
return ret;
},
- parsePropTypeColor3:function (node, parent, ccbReader, propertyName) {
- var red = ccbReader.readByte();
- var green = ccbReader.readByte();
- var blue = ccbReader.readByte();
- var color = {r:red, g:green, b:blue };
- if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){
- ccbReader.getAnimationManager().setBaseValue(cc.Color3BWapper.create(color),node, propertyName);
+ parsePropTypeColor3: function (node, parent, ccbReader, propertyName) {
+ var red = ccbReader._data[ccbReader._currentByte++];
+ var green = ccbReader._data[ccbReader._currentByte++];
+ var blue = ccbReader._data[ccbReader._currentByte++];
+ var color = cc.color(red, green, blue);
+ if (ccbReader._animatedProps.indexOf(propertyName) > -1) {
+ ccbReader._animationManager.setBaseValue(color, node, propertyName);
}
return color;
},
- parsePropTypeColor4FVar:function (node, parent, ccbReader) {
- var red = ccbReader.readFloat();
- var green = ccbReader.readFloat();
- var blue = ccbReader.readFloat();
+ parsePropTypeColor4FVar: function (node, parent, ccbReader) {
+ //TODO Color4F doesn't supports on HTML5
+ var red = 0 | (ccbReader.readFloat() * 255);
+ var green = 0 | (ccbReader.readFloat() * 255);
+ var blue = 0 | (ccbReader.readFloat() * 255);
var alpha = ccbReader.readFloat();
- var redVar = ccbReader.readFloat();
- var greenVar = ccbReader.readFloat();
- var blueVar = ccbReader.readFloat();
+ alpha = alpha <= 1 ? (0 | (alpha * 255)) : alpha;
+ var redVar = 0 | (ccbReader.readFloat() * 255);
+ var greenVar = 0 | (ccbReader.readFloat() * 255);
+ var blueVar = 0 | (ccbReader.readFloat() * 255);
var alphaVar = ccbReader.readFloat();
+ alphaVar = alphaVar <= 1 ? (0 | (alphaVar * 255)) : alphaVar;
- var colors = [];
- colors[0] = {r:red, g:green, b:blue, a:alpha};
- colors[1] = {r:redVar, g:greenVar, b:blueVar, a:alphaVar};
+ this._arr2[0] = {r: red, g: green, b: blue, a: alpha};
+ this._arr2[1] = {r: redVar, g: greenVar, b: blueVar, a: alphaVar};
- return colors;
+ return this._arr2;
},
- parsePropTypeFlip:function (node, parent, ccbReader) {
- var flipX = ccbReader.readBool();
- var flipY = ccbReader.readBool();
+ parsePropTypeFlip: function (node, parent, ccbReader) {
+ this._arr2[0] = !!ccbReader._data[ccbReader._currentByte++];
+ this._arr2[1] = !!ccbReader._data[ccbReader._currentByte++];
- return [flipX, flipY];
+ return this._arr2;
},
- parsePropTypeBlendFunc:function (node, parent, ccbReader) {
+ parsePropTypeBlendFunc: function (node, parent, ccbReader) {
var source = ccbReader.readInt(false);
var destination = ccbReader.readInt(false);
return new cc.BlendFunc(source, destination);
},
- parsePropTypeFntFile:function (node, parent, ccbReader) {
+ parsePropTypeFntFile: function (node, parent, ccbReader) {
return ccbReader.readCachedString();
},
- parsePropTypeString:function (node, parent, ccbReader) {
+ parsePropTypeString: function (node, parent, ccbReader) {
return ccbReader.readCachedString();
},
- parsePropTypeText:function (node, parent, ccbReader) {
+ parsePropTypeText: function (node, parent, ccbReader) {
return ccbReader.readCachedString();
},
- parsePropTypeFontTTF:function (node, parent, ccbReader) {
+ parsePropTypeFontTTF: function (node, parent, ccbReader) {
return ccbReader.readCachedString();
//var ttfEnding = ".ttf";
@@ -606,41 +619,41 @@ cc.NodeLoader = cc.Class.extend({
/* If the fontTTF comes with the ".ttf" extension, prepend the absolute path.
* System fonts come without the ".ttf" extension and do not need the path prepended. */
/*if (cc.CCBReader.endsWith(fontTTF.toLowerCase(), ttfEnding)) {
- fontTTF = ccbReader.getCCBRootPath() + fontTTF;
- }*/
+ fontTTF = ccbReader.getCCBRootPath() + fontTTF;
+ }*/
},
- parsePropTypeBlock:function (node, parent, ccbReader) {
+ parsePropTypeBlock: function (node, parent, ccbReader) {
var selectorName = ccbReader.readCachedString();
var selectorTarget = ccbReader.readInt(false);
if (selectorTarget !== CCB_TARGETTYPE_NONE) {
var target = null;
- if(!ccbReader.isJSControlled()) {
+ if (!ccbReader._jsControlled) {
if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT) {
- target = ccbReader.getAnimationManager().getRootNode();
+ target = ccbReader._animationManager._rootNode;
} else if (selectorTarget === CCB_TARGETTYPE_OWNER) {
- target = ccbReader.getOwner();
+ target = ccbReader._owner;
}
- if (target != null) {
+ if (target !== null) {
if (selectorName.length > 0) {
var selMenuHandler = 0;
//var targetAsCCBSelectorResolver = target;
- if (target != null && target.onResolveCCBCCMenuItemSelector)
+ if (target.onResolveCCBCCMenuItemSelector)
selMenuHandler = target.onResolveCCBCCMenuItemSelector(target, selectorName);
- if (selMenuHandler == 0) {
- var ccbSelectorResolver = ccbReader.getCCBSelectorResolver();
- if (ccbSelectorResolver != null)
+ if (selMenuHandler === 0) {
+ var ccbSelectorResolver = ccbReader._ccbSelectorResolver;
+ if (ccbSelectorResolver)
selMenuHandler = ccbSelectorResolver.onResolveCCBCCMenuItemSelector(target, selectorName);
}
- if (selMenuHandler == 0) {
- cc.log("Skipping selector '" +selectorName+ "' since no CCBSelectorResolver is present.");
+ if (selMenuHandler === 0) {
+ cc.log("Skipping selector '" + selectorName + "' since no CCBSelectorResolver is present.");
} else {
- return new BlockData(selMenuHandler,target);
+ return new BlockData(selMenuHandler, target);
}
} else {
cc.log("Unexpected empty selector.");
@@ -649,51 +662,55 @@ cc.NodeLoader = cc.Class.extend({
cc.log("Unexpected NULL target for selector.");
}
} else {
- if(selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT){
+ if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT) {
ccbReader.addDocumentCallbackNode(node);
ccbReader.addDocumentCallbackName(selectorName);
ccbReader.addDocumentCallbackControlEvents(0);
} else {
ccbReader.addOwnerCallbackNode(node);
ccbReader.addOwnerCallbackName(selectorName);
+ ccbReader.addOwnerCallbackControlEvents(0);
}
}
}
return null;
},
- parsePropTypeBlockCCControl:function (node, parent, ccbReader) {
+ parsePropTypeBlockCCControl: function (node, parent, ccbReader) {
var selectorName = ccbReader.readCachedString();
var selectorTarget = ccbReader.readInt(false);
var controlEvents = ccbReader.readInt(false);
if (selectorTarget !== CCB_TARGETTYPE_NONE) {
- if(!ccbReader.isJSControlled()){
+ if (!ccbReader._jsControlled) {
var target = null;
- if (selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT) {
- target = ccbReader.getAnimationManager().getRootNode();
- } else if (selectorTarget == CCB_TARGETTYPE_OWNER) {
- target = ccbReader.getOwner();
+ if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT) {
+ target = ccbReader._animationManager._rootNode;
+ } else if (selectorTarget === CCB_TARGETTYPE_OWNER) {
+ target = ccbReader._owner;
}
- if (target != null) {
+ if (target !== null) {
if (selectorName.length > 0) {
var selCCControlHandler = 0;
- if (target != null && target.onResolveCCBCCControlSelector) {
+ if (target.onResolveCCBCCControlSelector) {
selCCControlHandler = target.onResolveCCBCCControlSelector(target, selectorName);
}
- if (selCCControlHandler == 0) {
- var ccbSelectorResolver = ccbReader.getCCBSelectorResolver();
+ if (selCCControlHandler === 0) {
+ var ccbSelectorResolver = ccbReader._ccbSelectorResolver;
if (ccbSelectorResolver != null) {
selCCControlHandler = ccbSelectorResolver.onResolveCCBCCControlSelector(target, selectorName);
}
}
- if (selCCControlHandler == 0) {
+ if (selCCControlHandler === 0) {
cc.log("Skipping selector '" + selectorName + "' since no CCBSelectorResolver is present.");
} else {
- return new BlockCCControlData(selCCControlHandler,target,controlEvents);
+ this._blockControlData.selCCControlHandler = selCCControlHandler;
+ this._blockControlData.target = target;
+ this._blockControlData.controlEvents = controlEvents;
+ return this._blockControlData;
}
} else {
cc.log("Unexpected empty selector.");
@@ -702,56 +719,58 @@ cc.NodeLoader = cc.Class.extend({
cc.log("Unexpected NULL target for selector.");
}
} else {
- if(selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT){
+ if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT) {
ccbReader.addDocumentCallbackNode(node);
ccbReader.addDocumentCallbackName(selectorName);
ccbReader.addDocumentCallbackControlEvents(controlEvents);
} else {
ccbReader.addOwnerCallbackNode(node);
ccbReader.addOwnerCallbackName(selectorName);
+ ccbReader.addOwnerCallbackControlEvents(controlEvents);
}
}
}
return null;
},
- parsePropTypeCCBFile:function (node, parent, ccbReader) {
- var ccbFileName = ccbReader.getCCBRootPath() + ccbReader.readCachedString();
+ parsePropTypeCCBFile: function (node, parent, ccbReader) {
+ var ccbFileName = ccbReader._ccbRootPath + ccbReader.readCachedString();
/* Change path extension to .ccbi. */
var ccbFileWithoutPathExtension = cc.BuilderReader.deletePathExtension(ccbFileName);
ccbFileName = ccbFileWithoutPathExtension + ".ccbi";
- //load sub file
- var fileUtils = cc.FileUtils.getInstance();
- var path = fileUtils.fullPathFromRelativePath(ccbFileName);
var myCCBReader = new cc.BuilderReader(ccbReader);
- var size ;
- var bytes = fileUtils.getByteArrayFromFile(path,"rb", size);
+ var bytes = cc.loader.getRes(ccbFileName);
+ if (!bytes) {
+ var realUrl = cc.loader.getUrl(ccbFileName);
+ realUrl = hlddz.convertToDownloadURL(realUrl);
+ bytes = cc.loader.loadBinarySync(realUrl);
+ cc.loader.cache[ccbFileName] = bytes;
+ }
- myCCBReader.initWithData(bytes,ccbReader.getOwner());
- myCCBReader.getAnimationManager().setRootContainerSize(parent.getContentSize());
- myCCBReader.setAnimationManagers(ccbReader.getAnimationManagers());
+ myCCBReader.initWithData(bytes, ccbReader._owner);
+ myCCBReader._animationManager.setRootContainerSize(parent._contentSize);
+ myCCBReader.setAnimationManagers(ccbReader._animationManagers);
- myCCBReader.getAnimationManager().setOwner(ccbReader.getOwner());
+ myCCBReader._animationManager.setOwner(ccbReader._owner);
var ccbFileNode = myCCBReader.readFileWithCleanUp(false);
+ ccbReader.setAnimationManagers(myCCBReader._animationManagers);
- ccbReader.setAnimationManagers(myCCBReader.getAnimationManagers());
-
- if(ccbFileNode && myCCBReader.getAnimationManager().getAutoPlaySequenceId() != -1)
- myCCBReader.getAnimationManager().runAnimations(myCCBReader.getAnimationManager().getAutoPlaySequenceId(),0);
+ if (ccbFileNode && myCCBReader._animationManager._autoPlaySequenceId !== -1)
+ myCCBReader._animationManager.runAnimations(myCCBReader._animationManager._autoPlaySequenceId, 0);
return ccbFileNode;
},
- parsePropTypeFloatXY:function(node, parent, ccbReader){
- var x = ccbReader.readFloat();
- var y = ccbReader.readFloat();
- return [x,y];
+ parsePropTypeFloatXY: function (node, parent, ccbReader) {
+ this._pt.x = ccbReader.readFloat();
+ this._pt.y = ccbReader.readFloat();
+ return this._pt;
},
- onHandlePropTypePosition:function (node, parent, propertyName, position, ccbReader) {
+ onHandlePropTypePosition: function (node, parent, propertyName, position, ccbReader) {
if (propertyName === PROPERTY_POSITION) {
node.setPosition(position);
} else {
@@ -759,7 +778,7 @@ cc.NodeLoader = cc.Class.extend({
}
},
- onHandlePropTypePoint:function (node, parent, propertyName, position, ccbReader) {
+ onHandlePropTypePoint: function (node, parent, propertyName, position, ccbReader) {
if (propertyName === PROPERTY_ANCHORPOINT) {
node.setAnchorPoint(position);
} else {
@@ -767,11 +786,11 @@ cc.NodeLoader = cc.Class.extend({
}
},
- onHandlePropTypePointLock:function (node, parent, propertyName, pointLock, ccbReader) {
+ onHandlePropTypePointLock: function (node, parent, propertyName, pointLock, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeSize:function (node, parent, propertyName, sizeValue, ccbReader) {
+ onHandlePropTypeSize: function (node, parent, propertyName, sizeValue, ccbReader) {
if (propertyName === PROPERTY_CONTENTSIZE) {
node.setContentSize(sizeValue);
} else {
@@ -779,35 +798,34 @@ cc.NodeLoader = cc.Class.extend({
}
},
- onHandlePropTypeScaleLock:function (node, parent, propertyName, scaleLock, ccbReader) {
+ onHandlePropTypeScaleLock: function (node, parent, propertyName, scaleLock, ccbReader) {
if (propertyName === PROPERTY_SCALE) {
- node.setScaleX(scaleLock[0]);
- node.setScaleY(scaleLock[1]);
+ node.setScale(scaleLock.x, scaleLock.y);
} else {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
}
},
onHandlePropTypeFloatXY: function (node, parent, propertyName, xy, ccbReader) {
if (propertyName === PROPERTY_SKEW) {
- node.setSkewX(xy[0]);
- node.setSkewY(xy[1]);
+ node._skewX = xy.x;
+ node._skewY = xy.y;
} else {
var nameX = propertyName + "X";
var nameY = propertyName + "Y";
if (!node[nameX] || !node[nameY])
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
//TODO throw an error when source code was confused
- node[nameX](xy[0]);
- node[nameY](xy[1]);
+ node[nameX](xy.x);
+ node[nameY](xy.y);
}
},
- onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) {
+ onHandlePropTypeFloat: function (node, parent, propertyName, floatValue, ccbReader) {
//ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
// It may be a custom property, add it to custom property dictionary.
this._customProperties.setObject(floatValue, propertyName);
},
- onHandlePropTypeDegrees:function (node, parent, propertyName, degrees, ccbReader) {
+ onHandlePropTypeDegrees: function (node, parent, propertyName, degrees, ccbReader) {
if (propertyName === PROPERTY_ROTATION) {
node.setRotation(degrees);
} else {
@@ -815,83 +833,83 @@ cc.NodeLoader = cc.Class.extend({
}
},
- onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) {
+ onHandlePropTypeFloatScale: function (node, parent, propertyName, floatScale, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeInteger:function (node, parent, propertyName, integer, ccbReader) {
+ onHandlePropTypeInteger: function (node, parent, propertyName, integer, ccbReader) {
if (propertyName === PROPERTY_TAG) {
- node.setTag(integer);
+ node.tag = integer;
} else {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
}
},
- onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) {
+ onHandlePropTypeIntegerLabeled: function (node, parent, propertyName, integerLabeled, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeFloatVar:function (node, parent, propertyName, floatVar, ccbReader) {
+ onHandlePropTypeFloatVar: function (node, parent, propertyName, floatVar, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
+ onHandlePropTypeCheck: function (node, parent, propertyName, check, ccbReader) {
if (propertyName === PROPERTY_VISIBLE) {
- node.setVisible(check);
+ node._visible = check;
} else if (propertyName === PROPERTY_IGNOREANCHORPOINTFORPOSITION) {
- node.ignoreAnchorPointForPosition(check);
+ node._ignoreAnchorPointForPosition = check;
} else {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
}
},
- onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) {
+ onHandlePropTypeSpriteFrame: function (node, parent, propertyName, spriteFrame, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeAnimation:function (node, parent, propertyName, ccAnimation, ccbReader) {
+ onHandlePropTypeAnimation: function (node, parent, propertyName, ccAnimation, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeTexture:function (node, parent, propertyName, ccTexture2D, ccbReader) {
+ onHandlePropTypeTexture: function (node, parent, propertyName, ccTexture2D, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) {
+ onHandlePropTypeByte: function (node, parent, propertyName, byteValue, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
+ onHandlePropTypeColor3: function (node, parent, propertyName, ccColor3B, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeColor4FVar:function (node, parent, propertyName, ccColor4FVar, ccbReader) {
+ onHandlePropTypeColor4FVar: function (node, parent, propertyName, ccColor4FVar, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeFlip:function (node, parent, propertyName, flip, ccbReader) {
+ onHandlePropTypeFlip: function (node, parent, propertyName, flip, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) {
+ onHandlePropTypeBlendFunc: function (node, parent, propertyName, ccBlendFunc, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeFntFile:function (node, parent, propertyName, fntFile, ccbReader) {
+ onHandlePropTypeFntFile: function (node, parent, propertyName, fntFile, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeString:function (node, parent, propertyName, strValue, ccbReader) {
+ onHandlePropTypeString: function (node, parent, propertyName, strValue, ccbReader) {
//ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
// It may be a custom property, add it to custom property dictionary.
this._customProperties.setObject(strValue, propertyName);
},
- onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) {
+ onHandlePropTypeText: function (node, parent, propertyName, textValue, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) {
+ onHandlePropTypeFontTTF: function (node, parent, propertyName, fontTTF, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeBlock:function (node, parent, propertyName, blockData, ccbReader) {
+ onHandlePropTypeBlock: function (node, parent, propertyName, blockData, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeBlockCCControl:function (node, parent, propertyName, blockCCControlData, ccbReader) {
+ onHandlePropTypeBlockCCControl: function (node, parent, propertyName, blockCCControlData, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
},
- onHandlePropTypeCCBFile:function (node, parent, propertyName, ccbFileNode, ccbReader) {
+ onHandlePropTypeCCBFile: function (node, parent, propertyName, ccbFileNode, ccbReader) {
ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName);
}
});
diff --git a/extensions/CCBReader/CCNodeLoaderLibrary.js b/extensions/ccb-reader/CCNodeLoaderLibrary.js
similarity index 95%
rename from extensions/CCBReader/CCNodeLoaderLibrary.js
rename to extensions/ccb-reader/CCNodeLoaderLibrary.js
index cff3b6996b..487dc7b2fe 100644
--- a/extensions/CCBReader/CCNodeLoaderLibrary.js
+++ b/extensions/ccb-reader/CCNodeLoaderLibrary.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -53,13 +53,13 @@ cc.NodeLoaderLibrary = cc.Class.extend({
},
unregisterCCNodeLoader:function(className){
- if(this._ccNodeLoaders.hasOwnProperty(className)){
+ if(this._ccNodeLoaders[className]){
delete this._ccNodeLoaders[className];
}
},
getCCNodeLoader:function(className){
- if(this._ccNodeLoaders.hasOwnProperty(className))
+ if(this._ccNodeLoaders[className])
return this._ccNodeLoaders[className];
return null;
},
diff --git a/extensions/CCBReader/CCSpriteLoader.js b/extensions/ccb-reader/CCSpriteLoader.js
similarity index 96%
rename from extensions/CCBReader/CCSpriteLoader.js
rename to extensions/ccb-reader/CCSpriteLoader.js
index cdf95d96c0..857b2bb025 100644
--- a/extensions/CCBReader/CCSpriteLoader.js
+++ b/extensions/ccb-reader/CCSpriteLoader.js
@@ -1,7 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -32,7 +32,7 @@ var PROPERTY_BLENDFUNC = "blendFunc";
cc.SpriteLoader = cc.NodeLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.Sprite.create();
+ return new cc.Sprite();
},
onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
@@ -61,7 +61,7 @@ cc.SpriteLoader = cc.NodeLoader.extend({
onHandlePropTypeSpriteFrame:function (node, parent, propertyName, ccSpriteFrame, ccbReader) {
if (propertyName === PROPERTY_DISPLAYFRAME) {
if(ccSpriteFrame)
- node.setDisplayFrame(ccSpriteFrame);
+ node.setSpriteFrame(ccSpriteFrame);
else
cc.log("ERROR: SpriteFrame is null");
} else {
@@ -93,18 +93,23 @@ var PROPERTY_IS_KEYBOARD_ENABLED = "isKeyboardEnabled";
cc.LayerLoader = cc.NodeLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.Layer.create();
+
+ var layer = new cc.Layer();
+
+ layer.setContentSize(0,0);
+
+ return layer;
},
onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) {
if (propertyName === PROPERTY_TOUCH_ENABLED || propertyName === PROPERTY_IS_TOUCH_ENABLED) {
- node.setTouchEnabled(check);
+ //node.setTouchEnabled(check);
} else if (propertyName === PROPERTY_ACCELEROMETER_ENABLED || propertyName === PROPERTY_IS_ACCELEROMETER_ENABLED) {
- node.setAccelerometerEnabled(check);
+ //node.setAccelerometerEnabled(check);
} else if (propertyName === PROPERTY_MOUSE_ENABLED || propertyName === PROPERTY_IS_MOUSE_ENABLED ) {
- node.setMouseEnabled(check);
+ //node.setMouseEnabled(check);
} else if (propertyName === PROPERTY_KEYBOARD_ENABLED || propertyName === PROPERTY_IS_KEYBOARD_ENABLED) {
// TODO XXX
- if(node.setKeyboardEnabled && sys.platform === "browser") {
+ if(node.setKeyboardEnabled && !cc.sys.isNative) {
node.setKeyboardEnabled(check);
} else {
cc.log("The property '" + PROPERTY_IS_KEYBOARD_ENABLED + "' is not supported!");
@@ -123,7 +128,7 @@ cc.LayerLoader.loader = function () {
cc.LayerColorLoader = cc.LayerLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.LayerColor.create();
+ return new cc.LayerColor();
},
onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
@@ -161,12 +166,12 @@ var PROPERTY_VECTOR = "vector";
cc.LayerGradientLoader = cc.LayerLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.LayerGradient.create();
+ return new cc.LayerGradient();
},
onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
if (propertyName === PROPERTY_STARTCOLOR) {
node.setStartColor(ccColor3B);
- } else if (propertyName == PROPERTY_ENDCOLOR) {
+ } else if (propertyName === PROPERTY_ENDCOLOR) {
node.setEndColor(ccColor3B);
} else {
cc.LayerLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader);
@@ -205,7 +210,11 @@ cc.LayerGradientLoader.loader = function () {
cc.MenuLoader = cc.LayerLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.Menu.create();
+ var menu = new cc.Menu();
+
+ menu.setContentSize(0,0);
+
+ return menu;
}
});
@@ -245,7 +254,7 @@ var PROPERTY_DISABLEDDISPLAYFRAME = "disabledSpriteFrame";
cc.MenuItemImageLoader = cc.MenuItemLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.MenuItemImage.create();
+ return new cc.MenuItemImage();
},
onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) {
@@ -280,7 +289,7 @@ var PROPERTY_DIMENSIONS = "dimensions";
cc.LabelTTFLoader = cc.NodeLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.LabelTTF.create();
+ return new cc.LabelTTF();
},
onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
if (propertyName === PROPERTY_COLOR) {
@@ -352,7 +361,7 @@ var PROPERTY_FNTFILE = "fntFile";
cc.LabelBMFontLoader = cc.NodeLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.LabelBMFont.create();
+ return new cc.LabelBMFont();
},
onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) {
@@ -420,7 +429,7 @@ var PROPERTY_ROTATEPERSECOND = "rotatePerSecond";
cc.ParticleSystemLoader = cc.NodeLoader.extend({
_createCCNode:function (parent, ccbReader) {
- return cc.ParticleSystem.create();
+ return new cc.ParticleSystem();
},
onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) {
diff --git a/extensions/ccpool/CCPool.js b/extensions/ccpool/CCPool.js
new file mode 100644
index 0000000000..2159c091c8
--- /dev/null
+++ b/extensions/ccpool/CCPool.js
@@ -0,0 +1,146 @@
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ *
+ * cc.pool is a singleton object serves as an object cache pool.
+ * It can helps you to improve your game performance for objects which need frequent release and recreate operations
+ * Some common use case is :
+ * 1. Bullets in game (die very soon, massive creation and recreation, no side effect on other objects)
+ * 2. Blocks in candy crash (massive creation and recreation)
+ * etc...
+ *
+ *
+ * @example
+ * var sp = new cc.Sprite("a.png");
+ * this.addChild(sp);
+ * cc.pool.putInPool(sp);
+ *
+ * cc.pool.getFromPool(cc.Sprite, "a.png");
+ * @class
+ * @name cc.pool
+ */
+cc.pool = /** @lends cc.pool# */{
+ _pool: {},
+
+ _releaseCB: function () {
+ this.release();
+ },
+
+ _autoRelease: function (obj) {
+ var running = obj._running === undefined ? false : !obj._running;
+ cc.director.getScheduler().schedule(this._releaseCB, obj, 0, 0, 0, running)
+ },
+
+ /**
+ * Put the obj in pool
+ * @param obj
+ */
+ putInPool: function (obj) {
+ var pid = obj.constructor.prototype['__pid'];
+ if (!pid) {
+ var desc = {writable: true, enumerable: false, configurable: true};
+ desc.value = ClassManager.getNewID();
+ Object.defineProperty(obj.constructor.prototype, '__pid', desc);
+ }
+ if (!this._pool[pid]) {
+ this._pool[pid] = [];
+ }
+ // JSB retain to avoid being auto released
+ obj.retain && obj.retain();
+ // User implementation for disable the object
+ obj.unuse && obj.unuse();
+ this._pool[pid].push(obj);
+ },
+
+ /**
+ * Check if this kind of obj has already in pool
+ * @param objClass
+ * @returns {boolean} if this kind of obj is already in pool return true,else return false;
+ */
+ hasObject: function (objClass) {
+ var pid = objClass.prototype['__pid'];
+ var list = this._pool[pid];
+ if (!list || list.length === 0) {
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * Remove the obj if you want to delete it;
+ * @param obj
+ */
+ removeObject: function (obj) {
+ var pid = obj.constructor.prototype['__pid'];
+ if (pid) {
+ var list = this._pool[pid];
+ if (list) {
+ for (var i = 0; i < list.length; i++) {
+ if (obj === list[i]) {
+ // JSB release to avoid memory leak
+ obj.release && obj.release();
+ list.splice(i, 1);
+ }
+ }
+ }
+ }
+ },
+
+ /**
+ * Get the obj from pool
+ * @param args
+ * @returns {*} call the reuse function an return the obj
+ */
+ getFromPool: function (objClass/*,args*/) {
+ if (this.hasObject(objClass)) {
+ var pid = objClass.prototype['__pid'];
+ var list = this._pool[pid];
+ var args = Array.prototype.slice.call(arguments);
+ args.shift();
+ var obj = list.pop();
+ // User implementation for re-enable the object
+ obj.reuse && obj.reuse.apply(obj, args);
+ // JSB release to avoid memory leak
+ cc.sys.isNative && obj.release && this._autoRelease(obj);
+ return obj;
+ }
+ },
+
+ /**
+ * remove all objs in pool and reset the pool
+ */
+ drainAllPools: function () {
+ for (var i in this._pool) {
+ for (var j = 0; j < this._pool[i].length; j++) {
+ var obj = this._pool[i][j];
+ // JSB release to avoid memory leak
+ obj.release && obj.release();
+ }
+ }
+ this._pool = {};
+ }
+};
diff --git a/extensions/ccui/base-classes/CCProtectedNode.js b/extensions/ccui/base-classes/CCProtectedNode.js
new file mode 100644
index 0000000000..1925572fa5
--- /dev/null
+++ b/extensions/ccui/base-classes/CCProtectedNode.js
@@ -0,0 +1,305 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * A class inhert from cc.Node, use for saving some protected children in other list.
+ * @class
+ * @extends cc.Node
+ */
+cc.ProtectedNode = cc.Node.extend(/** @lends cc.ProtectedNode# */{
+ _protectedChildren: null,
+ _reorderProtectedChildDirty: false,
+
+ _insertProtectedChild: function (child, z) {
+ this._reorderProtectedChildDirty = true;
+ this._protectedChildren.push(child);
+ child._setLocalZOrder(z);
+ },
+
+ /**
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @function
+ */
+ ctor: function () {
+ cc.Node.prototype.ctor.call(this);
+ this._protectedChildren = [];
+ },
+
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ var renderer = cc.renderer;
+ var i, children = this._children, len = children.length, child;
+ var j, pChildren = this._protectedChildren, pLen = pChildren.length, pChild;
+
+ cmd.visit(parentCmd);
+
+ var locGrid = this.grid;
+ if (locGrid && locGrid._active)
+ locGrid.beforeDraw();
+
+ if (this._reorderChildDirty) this.sortAllChildren();
+ if (this._reorderProtectedChildDirty) this.sortAllProtectedChildren();
+
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0) {
+ child.visit(this);
+ }
+ else {
+ break;
+ }
+ }
+ for (j = 0; j < pLen; j++) {
+ pChild = pChildren[j];
+ if (pChild && pChild._localZOrder < 0) {
+ cmd._changeProtectedChild(pChild);
+ pChild.visit(this);
+ }
+ else
+ break;
+ }
+
+ renderer.pushRenderCommand(cmd);
+
+ for (; i < len; i++) {
+ children[i].visit(this);
+ }
+ for (; j < pLen; j++) {
+ pChild = pChildren[j];
+ if (!pChild) continue;
+ cmd._changeProtectedChild(pChild);
+ pChild.visit(this);
+ }
+
+ if (locGrid && locGrid._active)
+ locGrid.afterDraw(this);
+
+ cmd._dirtyFlag = 0;
+ },
+
+ /**
+ *
+ * Adds a child to the container with z order and tag
+ * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.
+ *
+ * @param {cc.Node} child A child node
+ * @param {Number} [localZOrder] Z order for drawing priority. Please refer to `setLocalZOrder(int)`
+ * @param {Number} [tag] An integer to identify the node easily. Please refer to `setTag(int)`
+ */
+ addProtectedChild: function (child, localZOrder, tag) {
+ cc.assert(child != null, "child must be non-nil");
+ cc.assert(!child.parent, "child already added. It can't be added again");
+
+ localZOrder = localZOrder || child.getLocalZOrder();
+ if (tag)
+ child.setTag(tag);
+
+ this._insertProtectedChild(child, localZOrder);
+ child.setParent(this);
+ child.setOrderOfArrival(cc.s_globalOrderOfArrival);
+
+ if (this._running) {
+ child._performRecursive(cc.Node._stateCallbackType.onEnter);
+ // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter
+ if (this._isTransitionFinished)
+ child._performRecursive(cc.Node._stateCallbackType.onEnterTransitionDidFinish);
+ }
+ if (this._cascadeColorEnabled)
+ this._renderCmd.setCascadeColorEnabledDirty();
+ if (this._cascadeOpacityEnabled)
+ this._renderCmd.setCascadeOpacityEnabledDirty();
+ },
+
+ /**
+ * Gets a child from the container with its tag
+ * @param {Number} tag An identifier to find the child node.
+ * @return {cc.Node} a Node object whose tag equals to the input parameter
+ */
+ getProtectedChildByTag: function (tag) {
+ cc.assert(tag !== cc.NODE_TAG_INVALID, "Invalid tag");
+ var locChildren = this._protectedChildren;
+ for (var i = 0, len = locChildren.length; i < len; i++)
+ if (locChildren.getTag() === tag)
+ return locChildren[i];
+ return null;
+ },
+
+ /**
+ * Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter.
+ * @param {cc.Node} child The child node which will be removed.
+ * @param {Boolean} [cleanup=true] true if all running actions and callbacks on the child node will be cleanup, false otherwise.
+ */
+ removeProtectedChild: function (child, cleanup) {
+ if (cleanup == null)
+ cleanup = true;
+ var locChildren = this._protectedChildren;
+ if (locChildren.length === 0)
+ return;
+ var idx = locChildren.indexOf(child);
+ if (idx > -1) {
+ if (this._running) {
+ child._performRecursive(cc.Node._stateCallbackType.onExitTransitionDidStart);
+ child._performRecursive(cc.Node._stateCallbackType.onExit);
+ }
+
+ // If you don't do cleanup, the child's actions will not get removed and the
+ // its scheduledSelectors_ dict will not get released!
+ if (cleanup)
+ child._performRecursive(cc.Node._stateCallbackType.cleanup);
+
+ // set parent nil at the end
+ child.setParent(null);
+ locChildren.splice(idx, 1);
+ }
+ },
+
+ /**
+ * Removes a child from the container by tag value.
+ * It will also cleanup all running actions depending on the cleanup parameter
+ * @param {Number} tag
+ * @param {Boolean} [cleanup=true]
+ */
+ removeProtectedChildByTag: function (tag, cleanup) {
+ cc.assert(tag !== cc.NODE_TAG_INVALID, "Invalid tag");
+
+ if (cleanup == null)
+ cleanup = true;
+
+ var child = this.getProtectedChildByTag(tag);
+
+ if (child == null)
+ cc.log("cocos2d: removeChildByTag(tag = %d): child not found!", tag);
+ else
+ this.removeProtectedChild(child, cleanup);
+ },
+
+ /**
+ * Removes all children from the container with a cleanup.
+ * @see cc.ProtectedNode#removeAllProtectedChildrenWithCleanup
+ */
+ removeAllProtectedChildren: function () {
+ this.removeAllProtectedChildrenWithCleanup(true);
+ },
+
+ /**
+ * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup parameter.
+ * @param {Boolean} [cleanup=true] true if all running actions on all children nodes should be cleanup, false otherwise.
+ */
+ removeAllProtectedChildrenWithCleanup: function (cleanup) {
+ if (cleanup == null)
+ cleanup = true;
+ var locChildren = this._protectedChildren;
+ // not using detachChild improves speed here
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var child = locChildren[i];
+ // IMPORTANT:
+ // -1st do onExit
+ // -2nd cleanup
+ if (this._running) {
+ child._performRecursive(cc.Node._stateCallbackType.onExitTransitionDidStart);
+ child._performRecursive(cc.Node._stateCallbackType.onExit);
+ }
+
+ if (cleanup)
+ child._performRecursive(cc.Node._stateCallbackType.cleanup);
+ // set parent nil at the end
+ child.setParent(null);
+ }
+ locChildren.length = 0;
+ },
+
+ /**
+ * Reorders a child according to a new z value.
+ * @param {cc.Node} child An already added child node. It MUST be already added.
+ * @param {Number} localZOrder Z order for drawing priority. Please refer to setLocalZOrder(int)
+ */
+ reorderProtectedChild: function (child, localZOrder) {
+ cc.assert(child != null, "Child must be non-nil");
+ this._reorderProtectedChildDirty = true;
+ child.setOrderOfArrival(cc.s_globalOrderOfArrival++);
+ child._setLocalZOrder(localZOrder);
+ },
+
+ /**
+ *
+ * Sorts the children array once before drawing, instead of every time when a child is added or reordered.
+ * This approach can improves the performance massively.
+ * @note Don't call this manually unless a child added needs to be removed in the same frame
+ *
+ */
+ sortAllProtectedChildren: function () {
+ if (this._reorderProtectedChildDirty) {
+ var _children = this._protectedChildren;
+
+ // insertion sort
+ var i, j, len = _children.length, tmp;
+ for (i = 1; i < len; i++) {
+ tmp = _children[i];
+ j = i - 1;
+
+ //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller
+ while (j >= 0) {
+ if (tmp._localZOrder < _children[j]._localZOrder) {
+ _children[j + 1] = _children[j];
+ } else if (tmp._localZOrder === _children[j]._localZOrder && tmp.arrivalOrder < _children[j].arrivalOrder) {
+ _children[j + 1] = _children[j];
+ } else
+ break;
+ j--;
+ }
+ _children[j + 1] = tmp;
+ }
+
+ //don't need to check children recursively, that's done in visit of each child
+ this._reorderProtectedChildDirty = false;
+ }
+ },
+
+ _changePosition: function () {
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new cc.ProtectedNode.CanvasRenderCmd(this);
+ else
+ return new cc.ProtectedNode.WebGLRenderCmd(this);
+ }
+});
+
+/**
+ * create a cc.ProtectedNode object;
+ * @deprecated since v3.0, please use new cc.ProtectedNode() instead.
+ * @return cc.ProtectedNode
+ */
+cc.ProtectedNode.create = function () {
+ return new cc.ProtectedNode();
+};
diff --git a/extensions/ccui/base-classes/CCProtectedNodeCanvasRenderCmd.js b/extensions/ccui/base-classes/CCProtectedNodeCanvasRenderCmd.js
new file mode 100644
index 0000000000..1ae8b1e62e
--- /dev/null
+++ b/extensions/ccui/base-classes/CCProtectedNodeCanvasRenderCmd.js
@@ -0,0 +1,169 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.ProtectedNode.RenderCmd = {
+ _updateDisplayColor: function (parentColor) {
+ var node = this._node;
+ var locDispColor = this._displayedColor, locRealColor = node._realColor;
+ var i, len, selChildren, item;
+ if (this._cascadeColorEnabledDirty && !node._cascadeColorEnabled) {
+ locDispColor.r = locRealColor.r;
+ locDispColor.g = locRealColor.g;
+ locDispColor.b = locRealColor.b;
+ var whiteColor = new cc.Color(255, 255, 255, 255);
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd)
+ item._renderCmd._updateDisplayColor(whiteColor);
+ }
+ this._cascadeColorEnabledDirty = false;
+ } else {
+ if (parentColor === undefined) {
+ var locParent = node._parent;
+ if (locParent && locParent._cascadeColorEnabled)
+ parentColor = locParent.getDisplayedColor();
+ else
+ parentColor = cc.color.WHITE;
+ }
+ locDispColor.r = 0 | (locRealColor.r * parentColor.r / 255.0);
+ locDispColor.g = 0 | (locRealColor.g * parentColor.g / 255.0);
+ locDispColor.b = 0 | (locRealColor.b * parentColor.b / 255.0);
+ if (node._cascadeColorEnabled) {
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd) {
+ item._renderCmd._updateDisplayColor(locDispColor);
+ item._renderCmd._updateColor();
+ }
+ }
+ }
+ selChildren = node._protectedChildren;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd) {
+ item._renderCmd._updateDisplayColor(locDispColor);
+ item._renderCmd._updateColor();
+ }
+ }
+ }
+ this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.colorDirty ^ this._dirtyFlag;
+ },
+
+ _updateDisplayOpacity: function (parentOpacity) {
+ var node = this._node;
+ var i, len, selChildren, item;
+ if (this._cascadeOpacityEnabledDirty && !node._cascadeOpacityEnabled) {
+ this._displayedOpacity = node._realOpacity;
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd)
+ item._renderCmd._updateDisplayOpacity(255);
+ }
+ this._cascadeOpacityEnabledDirty = false;
+ } else {
+ if (parentOpacity === undefined) {
+ var locParent = node._parent;
+ parentOpacity = 255;
+ if (locParent && locParent._cascadeOpacityEnabled)
+ parentOpacity = locParent.getDisplayedOpacity();
+ }
+ this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
+ if (node._cascadeOpacityEnabled) {
+ selChildren = node._children;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd) {
+ item._renderCmd._updateDisplayOpacity(this._displayedOpacity);
+ item._renderCmd._updateColor();
+ }
+ }
+ }
+ selChildren = node._protectedChildren;
+ for (i = 0, len = selChildren.length; i < len; i++) {
+ item = selChildren[i];
+ if (item && item._renderCmd) {
+ item._renderCmd._updateDisplayOpacity(this._displayedOpacity);
+ item._renderCmd._updateColor();
+ }
+ }
+ }
+ this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.opacityDirty ^ this._dirtyFlag;
+ },
+
+ _changeProtectedChild: function (child) {
+ var cmd = child._renderCmd,
+ dirty = cmd._dirtyFlag,
+ flags = cc.Node._dirtyFlags;
+
+ if (this._dirtyFlag & flags.colorDirty)
+ dirty |= flags.colorDirty;
+
+ if (this._dirtyFlag & flags.opacityDirty)
+ dirty |= flags.opacityDirty;
+
+ var colorDirty = dirty & flags.colorDirty,
+ opacityDirty = dirty & flags.opacityDirty;
+
+ if (colorDirty)
+ cmd._updateDisplayColor(this._displayedColor);
+ if (opacityDirty)
+ cmd._updateDisplayOpacity(this._displayedOpacity);
+ if (colorDirty || opacityDirty)
+ cmd._updateColor();
+ }
+ };
+
+ cc.ProtectedNode.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._cachedParent = null;
+ this._cacheDirty = false;
+ };
+
+ var proto = cc.ProtectedNode.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ cc.inject(cc.ProtectedNode.RenderCmd, proto);
+ proto.constructor = cc.ProtectedNode.CanvasRenderCmd;
+ proto._pNodeCmdCtor = cc.ProtectedNode.CanvasRenderCmd;
+
+ proto.transform = function (parentCmd, recursive) {
+ var node = this._node;
+
+ if (node._changePosition)
+ node._changePosition();
+
+ this.originTransform(parentCmd, recursive);
+
+ var i, len, locChildren = node._protectedChildren;
+ if (recursive && locChildren && locChildren.length !== 0) {
+ for (i = 0, len = locChildren.length; i < len; i++) {
+ locChildren[i]._renderCmd.transform(this, recursive);
+ }
+ }
+ };
+
+ proto.pNodeTransform = proto.transform;
+})();
diff --git a/extensions/ccui/base-classes/CCProtectedNodeWebGLRenderCmd.js b/extensions/ccui/base-classes/CCProtectedNodeWebGLRenderCmd.js
new file mode 100644
index 0000000000..b22907d383
--- /dev/null
+++ b/extensions/ccui/base-classes/CCProtectedNodeWebGLRenderCmd.js
@@ -0,0 +1,50 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ if (!cc.Node.WebGLRenderCmd)
+ return;
+ cc.ProtectedNode.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ };
+
+ var proto = cc.ProtectedNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ cc.inject(cc.ProtectedNode.RenderCmd, proto);
+ proto.constructor = cc.ProtectedNode.WebGLRenderCmd;
+ proto._pNodeCmdCtor = cc.ProtectedNode.WebGLRenderCmd;
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+
+ var i, len,
+ locChildren = this._node._protectedChildren;
+ if (recursive && locChildren && locChildren.length !== 0) {
+ for (i = 0, len = locChildren.length; i < len; i++) {
+ locChildren[i]._renderCmd.transform(this, recursive);
+ }
+ }
+ };
+
+ proto.pNodeTransform = proto.transform;
+})();
diff --git a/extensions/ccui/base-classes/UIScale9Sprite.js b/extensions/ccui/base-classes/UIScale9Sprite.js
new file mode 100644
index 0000000000..95df94cbc7
--- /dev/null
+++ b/extensions/ccui/base-classes/UIScale9Sprite.js
@@ -0,0 +1,936 @@
+/* global ccui */
+
+/****************************************************************************
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2012 Neofect. All rights reserved.
+ Copyright (c) 2016 zilongshanren. All rights reserved.
+
+ http://www.cocos2d-x.org
+
+ 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.
+
+ Created by Jung Sang-Taik on 2012-03-16
+ ****************************************************************************/
+(function () {
+
+var dataPool = {
+ _pool: {},
+ _lengths: [],
+ put: function (data) {
+ var length = data.length;
+ if (!this._pool[length]) {
+ this._pool[length] = [data];
+ this._lengths.push(length);
+ this._lengths.sort();
+ }
+ else {
+ this._pool[length].push(data);
+ }
+ },
+ get: function (length) {
+ var id;
+ for (var i = 0; i < this._lengths.length; i++) {
+ if (this._lengths[i] >= length) {
+ id = this._lengths[i];
+ break;
+ }
+ }
+ if (id) {
+ return this._pool[id].pop();
+ }
+ else {
+ return undefined;
+ }
+ }
+};
+
+var FIX_ARTIFACTS_BY_STRECHING_TEXEL = cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL, cornerId = [], webgl;
+
+
+var simpleQuadGenerator = {
+ _rebuildQuads_base: function (sprite, spriteFrame, contentSize, isTrimmedContentSize) {
+ //build vertices
+ var vertices = sprite._vertices,
+ wt = sprite._renderCmd._worldTransform,
+ l, b, r, t;
+ if (isTrimmedContentSize) {
+ l = 0;
+ b = 0;
+ r = contentSize.width;
+ t = contentSize.height;
+ } else {
+ var originalSize = spriteFrame._originalSize;
+ var rect = spriteFrame._rect;
+ var offset = spriteFrame._offset;
+ var scaleX = contentSize.width / originalSize.width;
+ var scaleY = contentSize.height / originalSize.height;
+ var trimmLeft = offset.x + (originalSize.width - rect.width) / 2;
+ var trimmRight = offset.x - (originalSize.width - rect.width) / 2;
+ var trimmedBottom = offset.y + (originalSize.height - rect.height) / 2;
+ var trimmedTop = offset.y - (originalSize.height - rect.height) / 2;
+
+ l = trimmLeft * scaleX;
+ b = trimmedBottom * scaleY;
+ r = contentSize.width + trimmRight * scaleX;
+ t = contentSize.height + trimmedTop * scaleY;
+ }
+
+ if (vertices.length < 8) {
+ dataPool.put(vertices);
+ vertices = dataPool.get(8) || new Float32Array(8);
+ sprite._vertices = vertices;
+ }
+ // bl, br, tl, tr
+ if (webgl) {
+ vertices[0] = l * wt.a + b * wt.c + wt.tx;
+ vertices[1] = l * wt.b + b * wt.d + wt.ty;
+ vertices[2] = r * wt.a + b * wt.c + wt.tx;
+ vertices[3] = r * wt.b + b * wt.d + wt.ty;
+ vertices[4] = l * wt.a + t * wt.c + wt.tx;
+ vertices[5] = l * wt.b + t * wt.d + wt.ty;
+ vertices[6] = r * wt.a + t * wt.c + wt.tx;
+ vertices[7] = r * wt.b + t * wt.d + wt.ty;
+ }
+ else {
+ vertices[0] = l;
+ vertices[1] = b;
+ vertices[2] = r;
+ vertices[3] = b;
+ vertices[4] = l;
+ vertices[5] = t;
+ vertices[6] = r;
+ vertices[7] = t;
+ }
+
+ cornerId[0] = 0;
+ cornerId[1] = 2;
+ cornerId[2] = 4;
+ cornerId[3] = 6;
+
+ //build uvs
+ if (sprite._uvsDirty) {
+ this._calculateUVs(sprite, spriteFrame);
+ }
+
+ sprite._vertCount = 4;
+ },
+
+ _calculateUVs: function (sprite, spriteFrame) {
+ var uvs = sprite._uvs;
+ var atlasWidth = spriteFrame._texture._pixelsWide;
+ var atlasHeight = spriteFrame._texture._pixelsHigh;
+ var textureRect = spriteFrame._rect;
+ textureRect = cc.rectPointsToPixels(textureRect);
+
+ if (uvs.length < 8) {
+ dataPool.put(uvs);
+ uvs = dataPool.get(8) || new Float32Array(8);
+ sprite._uvs = uvs;
+ }
+
+ //uv computation should take spritesheet into account.
+ var l, b, r, t;
+ var texelCorrect = FIX_ARTIFACTS_BY_STRECHING_TEXEL ? 0.5 : 0;
+
+ if (spriteFrame._rotated) {
+ l = (textureRect.x + texelCorrect) / atlasWidth;
+ b = (textureRect.y + textureRect.width - texelCorrect) / atlasHeight;
+ r = (textureRect.x + textureRect.height - texelCorrect) / atlasWidth;
+ t = (textureRect.y + texelCorrect) / atlasHeight;
+ uvs[0] = l; uvs[1] = t;
+ uvs[2] = l; uvs[3] = b;
+ uvs[4] = r; uvs[5] = t;
+ uvs[6] = r; uvs[7] = b;
+ }
+ else {
+ l = (textureRect.x + texelCorrect) / atlasWidth;
+ b = (textureRect.y + textureRect.height - texelCorrect) / atlasHeight;
+ r = (textureRect.x + textureRect.width - texelCorrect) / atlasWidth;
+ t = (textureRect.y + texelCorrect) / atlasHeight;
+ uvs[0] = l; uvs[1] = b;
+ uvs[2] = r; uvs[3] = b;
+ uvs[4] = l; uvs[5] = t;
+ uvs[6] = r; uvs[7] = t;
+ }
+ }
+};
+
+var scale9QuadGenerator = {
+ x: new Array(4),
+ y: new Array(4),
+ _rebuildQuads_base: function (sprite, spriteFrame, contentSize, insetLeft, insetRight, insetTop, insetBottom) {
+ //build vertices
+ var vertices = sprite._vertices;
+ var wt = sprite._renderCmd._worldTransform;
+ var leftWidth, centerWidth, rightWidth;
+ var topHeight, centerHeight, bottomHeight;
+ var rect = spriteFrame._rect;
+
+ leftWidth = insetLeft;
+ rightWidth = insetRight;
+ centerWidth = rect.width - leftWidth - rightWidth;
+ topHeight = insetTop;
+ bottomHeight = insetBottom;
+ centerHeight = rect.height - topHeight - bottomHeight;
+
+ var preferSize = contentSize;
+ var sizableWidth = preferSize.width - leftWidth - rightWidth;
+ var sizableHeight = preferSize.height - topHeight - bottomHeight;
+ var xScale = preferSize.width / (leftWidth + rightWidth);
+ var yScale = preferSize.height / (topHeight + bottomHeight);
+ xScale = xScale > 1 ? 1 : xScale;
+ yScale = yScale > 1 ? 1 : yScale;
+ sizableWidth = sizableWidth < 0 ? 0 : sizableWidth;
+ sizableHeight = sizableHeight < 0 ? 0 : sizableHeight;
+ var x = this.x;
+ var y = this.y;
+ x[0] = 0;
+ x[1] = leftWidth * xScale;
+ x[2] = x[1] + sizableWidth;
+ x[3] = preferSize.width;
+ y[0] = 0;
+ y[1] = bottomHeight * yScale;
+ y[2] = y[1] + sizableHeight;
+ y[3] = preferSize.height;
+
+ if (vertices.length < 32) {
+ dataPool.put(vertices);
+ vertices = dataPool.get(32) || new Float32Array(32);
+ sprite._vertices = vertices;
+ }
+ var offset = 0, row, col;
+ if (webgl) {
+ for (row = 0; row < 4; row++) {
+ for (col = 0; col < 4; col++) {
+ vertices[offset] = x[col] * wt.a + y[row] * wt.c + wt.tx;
+ vertices[offset+1] = x[col] * wt.b + y[row] * wt.d + wt.ty;
+ offset += 2;
+ }
+ }
+ }
+ else {
+ for (row = 0; row < 4; row++) {
+ for (col = 0; col < 4; col++) {
+ vertices[offset] = x[col];
+ vertices[offset+1] = y[row];
+ offset += 2;
+ }
+ }
+ }
+
+ cornerId[0] = 0;
+ cornerId[1] = 6;
+ cornerId[2] = 24;
+ cornerId[3] = 30;
+
+ //build uvs
+ if (sprite._uvsDirty) {
+ this._calculateUVs(sprite, spriteFrame, insetLeft, insetRight, insetTop, insetBottom);
+ }
+ },
+
+ _calculateUVs: function (sprite, spriteFrame, insetLeft, insetRight, insetTop, insetBottom) {
+ var uvs = sprite._uvs;
+ var rect = spriteFrame._rect;
+ var atlasWidth = spriteFrame._texture._pixelsWide;
+ var atlasHeight = spriteFrame._texture._pixelsHigh;
+
+ //caculate texture coordinate
+ var leftWidth, centerWidth, rightWidth;
+ var topHeight, centerHeight, bottomHeight;
+ var textureRect = spriteFrame._rect;
+ textureRect = cc.rectPointsToPixels(textureRect);
+ rect = cc.rectPointsToPixels(rect);
+ var scale = cc.contentScaleFactor();
+
+ leftWidth = insetLeft * scale;
+ rightWidth = insetRight * scale;
+ centerWidth = rect.width - leftWidth - rightWidth;
+ topHeight = insetTop * scale;
+ bottomHeight = insetBottom * scale;
+ centerHeight = rect.height - topHeight - bottomHeight;
+
+ if (uvs.length < 32) {
+ dataPool.put(uvs);
+ uvs = dataPool.get(32) || new Float32Array(32);
+ sprite._uvs = uvs;
+ }
+
+ //uv computation should take spritesheet into account.
+ var u = this.x;
+ var v = this.y;
+ var texelCorrect = FIX_ARTIFACTS_BY_STRECHING_TEXEL ? 0.5 : 0;
+ var offset = 0, row, col;
+
+ if (spriteFrame._rotated) {
+ u[0] = (textureRect.x + texelCorrect) / atlasWidth;
+ u[1] = (bottomHeight + textureRect.x) / atlasWidth;
+ u[2] = (bottomHeight + centerHeight + textureRect.x) / atlasWidth;
+ u[3] = (textureRect.x + textureRect.height - texelCorrect) / atlasWidth;
+
+ v[3] = (textureRect.y + texelCorrect) / atlasHeight;
+ v[2] = (leftWidth + textureRect.y) / atlasHeight;
+ v[1] = (leftWidth + centerWidth + textureRect.y) / atlasHeight;
+ v[0] = (textureRect.y + textureRect.width - texelCorrect) / atlasHeight;
+
+ for (row = 0; row < 4; row++) {
+ for (col = 0; col < 4; col++) {
+ uvs[offset] = u[row];
+ uvs[offset+1] = v[3-col];
+ offset += 2;
+ }
+ }
+ }
+ else {
+ u[0] = (textureRect.x + texelCorrect) / atlasWidth;
+ u[1] = (leftWidth + textureRect.x) / atlasWidth;
+ u[2] = (leftWidth + centerWidth + textureRect.x) / atlasWidth;
+ u[3] = (textureRect.x + textureRect.width - texelCorrect) / atlasWidth;
+
+ v[3] = (textureRect.y + texelCorrect) / atlasHeight;
+ v[2] = (topHeight + textureRect.y) / atlasHeight;
+ v[1] = (topHeight + centerHeight + textureRect.y) / atlasHeight;
+ v[0] = (textureRect.y + textureRect.height - texelCorrect) / atlasHeight;
+
+ for (row = 0; row < 4; row++) {
+ for (col = 0; col < 4; col++) {
+ uvs[offset] = u[col];
+ uvs[offset+1] = v[row];
+ offset += 2;
+ }
+ }
+ }
+ }
+};
+
+/**
+ *
+ * A 9-slice sprite for cocos2d UI.
+ *
+ * 9-slice scaling allows you to specify how scaling is applied
+ * to specific areas of a sprite. With 9-slice scaling (3x3 grid),
+ * you can ensure that the sprite does not become distorted when
+ * scaled.
+ * @see http://yannickloriot.com/library/ios/cccontrolextension/Classes/CCScale9Sprite.html
+ *
+ * @class
+ * @extends cc.Node
+ *
+ * @property {cc.Size} preferredSize - The preferred size of the 9-slice sprite
+ * @property {cc.Rect} capInsets - The cap insets of the 9-slice sprite
+ * @property {Number} insetLeft - The left inset of the 9-slice sprite
+ * @property {Number} insetTop - The top inset of the 9-slice sprite
+ * @property {Number} insetRight - The right inset of the 9-slice sprite
+ * @property {Number} insetBottom - The bottom inset of the 9-slice sprite
+ */
+
+ccui.Scale9Sprite = cc.Scale9Sprite = cc.Node.extend(/** @lends ccui.Scale9Sprite# */{
+ //resource data, could be async loaded.
+ _spriteFrame: null,
+ _scale9Image: null,
+
+ //scale 9 data
+ _insetLeft: 0,
+ _insetRight: 0,
+ _insetTop: 0,
+ _insetBottom: 0,
+ //blend function
+ _blendFunc: null,
+ //sliced or simple
+ _renderingType: 1,
+ //bright or not
+ _brightState: 0,
+ _opacityModifyRGB: false,
+ //rendering quads shared by canvas and webgl
+ _rawVerts: null,
+ _rawUvs: null,
+ _vertices: null,
+ _uvs: null,
+ _vertCount: 0,
+ _quadsDirty: true,
+ _uvsDirty: true,
+ _isTriangle: false,
+ _isTrimmedContentSize: false,
+ _textureLoaded: false,
+
+ //v3.3
+ _flippedX: false,
+ _flippedY: false,
+ _className: "Scale9Sprite",
+
+ /**
+ * Constructor function.
+ * @function
+ * @param {string|cc.SpriteFrame} file file name of texture or a SpriteFrame
+ * @param {cc.Rect} rectOrCapInsets
+ * @param {cc.Rect} capInsets
+ * @returns {Scale9Sprite}
+ */
+ ctor: function (file, rectOrCapInsets, capInsets) {
+ cc.Node.prototype.ctor.call(this);
+
+ //for async texture load
+ this._loader = new cc.Sprite.LoadManager();
+
+ this._renderCmd.setState(this._brightState);
+ this._blendFunc = cc.BlendFunc._alphaPremultiplied();
+ this.setAnchorPoint(cc.p(0.5, 0.5));
+ // Init vertex data for simple
+ this._rawVerts = null;
+ this._rawUvs = null;
+ this._vertices = dataPool.get(8) || new Float32Array(8);
+ this._uvs = dataPool.get(8) || new Float32Array(8);
+
+ if (file !== undefined) {
+ if (file instanceof cc.SpriteFrame)
+ this.initWithSpriteFrame(file, rectOrCapInsets);
+ else {
+ var frame = cc.spriteFrameCache.getSpriteFrame(file);
+ if (frame)
+ this.initWithSpriteFrame(frame, rectOrCapInsets);
+ else
+ this.initWithFile(file, rectOrCapInsets, capInsets);
+ }
+ }
+
+
+ if (webgl === undefined) {
+ webgl = cc._renderType === cc.game.RENDER_TYPE_WEBGL;
+ }
+ },
+
+ textureLoaded: function () {
+ return this._textureLoaded;
+ },
+
+ getCapInsets: function () {
+ return cc.rect(this._capInsetsInternal);
+ },
+
+ _asyncSetCapInsets: function () {
+ this.removeEventListener('load', this._asyncSetCapInsets, this);
+ this.setCapInsets(this._cacheCapInsets);
+ this._cacheCapInsets = null;
+ },
+
+ setCapInsets: function (capInsets) {
+ // Asynchronous loading texture requires this data
+ // This data does not take effect immediately, so it does not affect the existing texture.
+ if (!this.loaded()) {
+ this._cacheCapInsets = capInsets;
+ this.removeEventListener('load', this._asyncSetCapInsets, this);
+ this.addEventListener('load', this._asyncSetCapInsets, this);
+ return false;
+ }
+
+ this._capInsetsInternal = capInsets;
+ this._updateCapInsets(this._spriteFrame._rect, this._capInsetsInternal);
+ },
+
+ _updateCapInsets: function (rect, capInsets) {
+ if(!capInsets || !rect || cc._rectEqualToZero(capInsets)) {
+ rect = rect || {x:0, y:0, width: this._contentSize.width, height: this._contentSize.height};
+ this._capInsetsInternal = cc.rect(rect.width /3,
+ rect.height /3,
+ rect.width /3,
+ rect.height /3);
+ } else {
+ this._capInsetsInternal = capInsets;
+ }
+
+ if(!cc._rectEqualToZero(rect)) {
+ this._insetLeft = this._capInsetsInternal.x;
+ this._insetTop = this._capInsetsInternal.y;
+ this._insetRight = rect.width - this._insetLeft - this._capInsetsInternal.width;
+ this._insetBottom = rect.height - this._insetTop - this._capInsetsInternal.height;
+ }
+ },
+
+
+ initWithFile: function (file, rect, capInsets) {
+ if (file instanceof cc.Rect) {
+ file = arguments[1];
+ capInsets = arguments[0];
+ rect = cc.rect(0, 0, 0, 0);
+ } else {
+ rect = rect || cc.rect(0, 0, 0, 0);
+ capInsets = capInsets || cc.rect(0, 0, 0, 0);
+ }
+
+ if(!file)
+ throw new Error("ccui.Scale9Sprite.initWithFile(): file should be non-null");
+
+ var texture = cc.textureCache.getTextureForKey(file);
+ if (!texture) {
+ texture = cc.textureCache.addImage(file);
+ }
+
+ var locLoaded = texture.isLoaded();
+ this._textureLoaded = locLoaded;
+ this._loader.clear();
+ if (!locLoaded) {
+ this._loader.once(texture, function () {
+ this.initWithFile(file, rect, capInsets);
+ this.dispatchEvent("load");
+ }, this);
+ return false;
+ }
+
+ //in this function, the texture already make sure is loaded.
+ if( cc._rectEqualToZero(rect)) {
+ var textureSize = texture.getContentSize();
+ rect = cc.rect(0, 0, textureSize.width, textureSize.height);
+ }
+ this.setTexture(texture, rect);
+ this._updateCapInsets(rect, capInsets);
+
+ return true;
+ },
+
+ updateWithBatchNode: function (batchNode, originalRect, rotated, capInsets) {
+ if (!batchNode) {
+ return false;
+ }
+
+ var texture = batchNode.getTexture();
+ this._loader.clear();
+ if (!texture.isLoaded()) {
+ this._loader.once(texture, function () {
+ this.updateWithBatchNode(batchNode, originalRect, rotated, capInsets);
+ this.dispatchEvent("load");
+ }, this);
+ return false;
+ }
+
+ this.setTexture(texture, originalRect);
+ this._updateCapInsets(originalRect, capInsets);
+
+ return true;
+ },
+
+
+ /**
+ * Initializes a 9-slice sprite with an sprite frame
+ * @param spriteFrameOrSFName The sprite frame object.
+ */
+ initWithSpriteFrame: function (spriteFrame, capInsets) {
+ this.setSpriteFrame(spriteFrame);
+
+ capInsets = capInsets || cc.rect(0, 0, 0, 0);
+
+ this._updateCapInsets(spriteFrame._rect, capInsets);
+ },
+
+ initWithSpriteFrameName: function (spriteFrameName, capInsets) {
+ if(!spriteFrameName)
+ throw new Error("ccui.Scale9Sprite.initWithSpriteFrameName(): spriteFrameName should be non-null");
+ capInsets = capInsets || cc.rect(0, 0, 0, 0);
+
+ var frame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
+ if (frame == null) {
+ cc.log("ccui.Scale9Sprite.initWithSpriteFrameName(): can't find the sprite frame by spriteFrameName");
+ return false;
+ }
+ this.setSpriteFrame(frame);
+
+ capInsets = capInsets || cc.rect(0, 0, 0, 0);
+
+ this._updateCapInsets(frame._rect, capInsets);
+ },
+
+ loaded: function () {
+ if (this._spriteFrame === null) {
+ return false;
+ } else {
+ return this._spriteFrame.textureLoaded();
+ }
+ },
+
+ /**
+ * Change the texture file of 9 slice sprite
+ *
+ * @param textureOrTextureFile The name of the texture file.
+ */
+ setTexture: function (texture, rect) {
+ var spriteFrame = new cc.SpriteFrame(texture, rect);
+ this.setSpriteFrame(spriteFrame);
+ },
+
+ _updateBlendFunc: function () {
+ // it's possible to have an untextured sprite
+ var blendFunc = this._blendFunc;
+ if (!this._spriteFrame || !this._spriteFrame._texture.hasPremultipliedAlpha()) {
+ if (blendFunc.src === cc.ONE && blendFunc.dst === cc.BLEND_DST) {
+ blendFunc.src = cc.SRC_ALPHA;
+ }
+ this._opacityModifyRGB = false;
+ } else {
+ if (blendFunc.src === cc.SRC_ALPHA && blendFunc.dst === cc.BLEND_DST) {
+ blendFunc.src = cc.ONE;
+ }
+ this._opacityModifyRGB = true;
+ }
+ },
+
+ setOpacityModifyRGB: function (value) {
+ if (this._opacityModifyRGB !== value) {
+ this._opacityModifyRGB = value;
+ this._renderCmd._setColorDirty();
+ }
+ },
+
+ isOpacityModifyRGB: function () {
+ return this._opacityModifyRGB;
+ },
+
+ /**
+ * Change the sprite frame of 9 slice sprite
+ *
+ * @param spriteFrameOrSFFileName The name of the texture file.
+ */
+ setSpriteFrame: function (spriteFrame) {
+ if (spriteFrame) {
+ this._spriteFrame = spriteFrame;
+ this._quadsDirty = true;
+ this._uvsDirty = true;
+ var self = this;
+ var onResourceDataLoaded = function () {
+ if (cc.sizeEqualToSize(self._contentSize, cc.size(0, 0))) {
+ self.setContentSize(self._spriteFrame._rect);
+ }
+ self._textureLoaded = true;
+ self._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ cc.renderer.childrenOrderDirty = true;
+ };
+ self._textureLoaded = spriteFrame.textureLoaded();
+ if (self._textureLoaded) {
+ onResourceDataLoaded();
+ } else {
+ this._loader.clear();
+ this._loader.once(spriteFrame, function () {
+ onResourceDataLoaded();
+ this.dispatchEvent("load");
+ }, this);
+ }
+ }
+ },
+
+ /**
+ * Sets the source blending function.
+ *
+ * @param blendFunc A structure with source and destination factor to specify pixel arithmetic. e.g. {GL_ONE, GL_ONE}, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}.
+ */
+ setBlendFunc: function (blendFunc, dst) {
+ if (dst === undefined) {
+ this._blendFunc.src = blendFunc.src || cc.BLEND_SRC;
+ this._blendFunc.dst = blendFunc.dst || cc.BLEND_DST;
+ }
+ else {
+ this._blendFunc.src = blendFunc || cc.BLEND_SRC;
+ this._blendFunc.dst = dst || cc.BLEND_DST;
+ }
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ },
+
+ /**
+ * Returns the blending function that is currently being used.
+ *
+ * @return A BlendFunc structure with source and destination factor which specified pixel arithmetic.
+ */
+ getBlendFunc: function () {
+ return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
+ },
+
+ setPreferredSize: function (preferredSize) {
+ if (!preferredSize || cc.sizeEqualToSize(this._contentSize, preferredSize)) return;
+ this.setContentSize(preferredSize);
+ },
+
+ getPreferredSize: function () {
+ return this.getContentSize();
+ },
+
+ // overrides
+ setContentSize: function (width, height) {
+ if (height === undefined) {
+ height = width.height;
+ width = width.width;
+ }
+ if (width === this._contentSize.width && height === this._contentSize.height) {
+ return;
+ }
+
+ cc.Node.prototype.setContentSize.call(this, width, height);
+ this._quadsDirty = true;
+ },
+
+ getContentSize: function () {
+ if(this._renderingType === ccui.Scale9Sprite.RenderingType.SIMPLE) {
+ if(this._spriteFrame) {
+ return this._spriteFrame._originalSize;
+ }
+ return cc.size(this._contentSize);
+ } else {
+ return cc.size(this._contentSize);
+ }
+ },
+
+ _setWidth: function (value) {
+ cc.Node.prototype._setWidth.call(this, value);
+ this._quadsDirty = true;
+ },
+
+ _setHeight: function (value) {
+ cc.Node.prototype._setHeight.call(this, value);
+ this._quadsDirty = true;
+ },
+
+ /**
+ * Change the state of 9-slice sprite.
+ * @see `State`
+ * @param state A enum value in State.
+ */
+ setState: function (state) {
+ this._brightState = state;
+ this._renderCmd.setState(state);
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ },
+
+ /**
+ * Query the current bright state.
+ * @return @see `State`
+ */
+ getState: function () {
+ return this._brightState;
+ },
+
+ /**
+ * change the rendering type, could be simple or slice
+ * @return @see `RenderingType`
+ */
+ setRenderingType: function (type) {
+ if (this._renderingType === type) return;
+
+ this._renderingType = type;
+ this._quadsDirty = true;
+ this._uvsDirty = true;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ },
+ /**
+ * get the rendering type, could be simple or slice
+ * @return @see `RenderingType`
+ */
+ getRenderingType: function () {
+ return this._renderingType;
+ },
+ /**
+ * change the left border of 9 slice sprite, it should be specified before trimmed.
+ * @param insetLeft left border.
+ */
+ setInsetLeft: function (insetLeft) {
+ this._insetLeft = insetLeft;
+ this._quadsDirty = true;
+ this._uvsDirty = true;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ },
+ /**
+ * get the left border of 9 slice sprite, the result is specified before trimmed.
+ * @return left border.
+ */
+ getInsetLeft: function () {
+ return this._insetLeft;
+ },
+ /**
+ * change the top border of 9 slice sprite, it should be specified before trimmed.
+ * @param insetTop top border.
+ */
+ setInsetTop: function (insetTop) {
+ this._insetTop = insetTop;
+ this._quadsDirty = true;
+ this._uvsDirty = true;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ },
+
+ /**
+ * get the top border of 9 slice sprite, the result is specified before trimmed.
+ * @return top border.
+ */
+ getInsetTop: function () {
+ return this._insetTop;
+ },
+
+ /**
+ * change the right border of 9 slice sprite, it should be specified before trimmed.
+ * @param insetRight right border.
+ */
+ setInsetRight: function (insetRight) {
+ this._insetRight = insetRight;
+ this._quadsDirty = true;
+ this._uvsDirty = true;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ },
+
+ /**
+ * get the right border of 9 slice sprite, the result is specified before trimmed.
+ * @return right border.
+ */
+ getInsetRight: function () {
+ return this._insetRight;
+ },
+
+ /**
+ * change the bottom border of 9 slice sprite, it should be specified before trimmed.
+ * @param insetBottom bottom border.
+ */
+ setInsetBottom: function (insetBottom) {
+ this._insetBottom = insetBottom;
+ this._quadsDirty = true;
+ this._uvsDirty = true;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ },
+ /**
+ * get the bottom border of 9 slice sprite, the result is specified before trimmed.
+ * @return bottom border.
+ */
+ getInsetBottom: function () {
+ return this._insetBottom;
+ },
+
+ _rebuildQuads: function () {
+ if (!this._spriteFrame || !this._spriteFrame._textureLoaded) {
+ return;
+ }
+
+ this._updateBlendFunc();
+
+ this._isTriangle = false;
+ switch (this._renderingType) {
+ case RenderingType.SIMPLE:
+ simpleQuadGenerator._rebuildQuads_base(this, this._spriteFrame, this._contentSize, this._isTrimmedContentSize);
+ break;
+ case RenderingType.SLICED:
+ scale9QuadGenerator._rebuildQuads_base(this, this._spriteFrame, this._contentSize, this._insetLeft, this._insetRight, this._insetTop, this._insetBottom);
+ break;
+ default:
+ this._quadsDirty = false;
+ this._uvsDirty = false;
+ cc.error('Can not generate quad');
+ return;
+ }
+
+
+ this._quadsDirty = false;
+ this._uvsDirty = false;
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new ccui.Scale9Sprite.CanvasRenderCmd(this);
+ else
+ return new ccui.Scale9Sprite.WebGLRenderCmd(this);
+ }
+});
+
+var _p = ccui.Scale9Sprite.prototype;
+cc.EventHelper.prototype.apply(_p);
+
+// Extended properties
+/** @expose */
+_p.preferredSize;
+cc.defineGetterSetter(_p, "preferredSize", _p.getPreferredSize, _p.setPreferredSize);
+/** @expose */
+_p.capInsets;
+cc.defineGetterSetter(_p, "capInsets", _p.getCapInsets, _p.setCapInsets);
+/** @expose */
+_p.insetLeft;
+cc.defineGetterSetter(_p, "insetLeft", _p.getInsetLeft, _p.setInsetLeft);
+/** @expose */
+_p.insetTop;
+cc.defineGetterSetter(_p, "insetTop", _p.getInsetTop, _p.setInsetTop);
+/** @expose */
+_p.insetRight;
+cc.defineGetterSetter(_p, "insetRight", _p.getInsetRight, _p.setInsetRight);
+/** @expose */
+_p.insetBottom;
+cc.defineGetterSetter(_p, "insetBottom", _p.getInsetBottom, _p.setInsetBottom);
+
+_p = null;
+
+/**
+ * Creates a 9-slice sprite with a texture file, a delimitation zone and
+ * with the specified cap insets.
+ * @deprecated since v3.0, please use new ccui.Scale9Sprite(file, rect, capInsets) instead.
+ * @param {String|cc.SpriteFrame} file file name of texture or a cc.Sprite object
+ * @param {cc.Rect} rect the rect of the texture
+ * @param {cc.Rect} capInsets the cap insets of ccui.Scale9Sprite
+ * @returns {ccui.Scale9Sprite}
+ */
+ccui.Scale9Sprite.create = function (file, rect, capInsets) {
+ return new ccui.Scale9Sprite(file, rect, capInsets);
+};
+
+/**
+ * create a ccui.Scale9Sprite with Sprite frame.
+ * @deprecated since v3.0, please use "new ccui.Scale9Sprite(spriteFrame, capInsets)" instead.
+ * @param {cc.SpriteFrame} spriteFrame
+ * @param {cc.Rect} capInsets
+ * @returns {ccui.Scale9Sprite}
+ */
+ccui.Scale9Sprite.createWithSpriteFrame = function (spriteFrame, capInsets) {
+ return new ccui.Scale9Sprite(spriteFrame, capInsets);
+};
+
+/**
+ * create a ccui.Scale9Sprite with a Sprite frame name
+ * @deprecated since v3.0, please use "new ccui.Scale9Sprite(spriteFrameName, capInsets)" instead.
+ * @param {string} spriteFrameName
+ * @param {cc.Rect} capInsets
+ * @returns {Scale9Sprite}
+ */
+ccui.Scale9Sprite.createWithSpriteFrameName = function (spriteFrameName, capInsets) {
+ return new ccui.Scale9Sprite(spriteFrameName, capInsets);
+};
+
+/**
+ * @ignore
+ */
+ccui.Scale9Sprite.POSITIONS_CENTRE = 0;
+ccui.Scale9Sprite.POSITIONS_TOP = 1;
+ccui.Scale9Sprite.POSITIONS_LEFT = 2;
+ccui.Scale9Sprite.POSITIONS_RIGHT = 3;
+ccui.Scale9Sprite.POSITIONS_BOTTOM = 4;
+ccui.Scale9Sprite.POSITIONS_TOPRIGHT = 5;
+ccui.Scale9Sprite.POSITIONS_TOPLEFT = 6;
+ccui.Scale9Sprite.POSITIONS_BOTTOMRIGHT = 7;
+
+ccui.Scale9Sprite.state = {NORMAL: 0, GRAY: 1};
+
+var RenderingType = ccui.Scale9Sprite.RenderingType = {
+ /**
+ * @property {Number} SIMPLE
+ */
+ SIMPLE: 0,
+ /**
+ * @property {Number} SLICED
+ */
+ SLICED: 1
+};
+})();
diff --git a/extensions/ccui/base-classes/UIScale9SpriteCanvasRenderCmd.js b/extensions/ccui/base-classes/UIScale9SpriteCanvasRenderCmd.js
new file mode 100644
index 0000000000..12f1bcaf82
--- /dev/null
+++ b/extensions/ccui/base-classes/UIScale9SpriteCanvasRenderCmd.js
@@ -0,0 +1,154 @@
+/****************************************************************************
+ Copyright (c) 2013-2016 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function() {
+ ccui.Scale9Sprite.CanvasRenderCmd = function (renderable) {
+ cc.Node.CanvasRenderCmd.call(this, renderable);
+ this._needDraw = true;
+
+ this._state = ccui.Scale9Sprite.state.NORMAL;
+ this._originalTexture = this._textureToRender = null;
+ };
+
+ var proto = ccui.Scale9Sprite.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ proto.constructor = ccui.Scale9Sprite.CanvasRenderCmd;
+
+ proto.transform = function(parentCmd, recursive){
+ this.originTransform(parentCmd, recursive);
+ this._node._rebuildQuads();
+ };
+
+ proto.needDraw = function () {
+ return this._needDraw && this._node.loaded();
+ };
+
+ proto._updateDisplayColor = function(parentColor){
+ cc.Node.RenderCmd.prototype._updateDisplayColor.call(this, parentColor);
+ this._originalTexture = this._textureToRender = null;
+ };
+
+ proto.setState = function(state){
+ if(this._state === state) return;
+
+ this._state = state;
+ this._originalTexture = this._textureToRender = null;
+ };
+
+ proto._setColorDirty = function () {
+ this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty | cc.Node._dirtyFlags.opacityDirty);
+ };
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var node = this._node;
+ var locDisplayOpacity = this._displayedOpacity;
+ var alpha = locDisplayOpacity/ 255;
+ var locTexture = null;
+ if (node._spriteFrame) locTexture = node._spriteFrame._texture;
+ if (!node.loaded() || locDisplayOpacity === 0)
+ return;
+ if (this._textureToRender === null || this._originalTexture !== locTexture) {
+ this._textureToRender = this._originalTexture = locTexture;
+ if (cc.Scale9Sprite.state.GRAY === this._state) {
+ this._textureToRender = this._textureToRender._generateGrayTexture();
+ }
+ var color = node.getDisplayedColor();
+ if (locTexture && (color.r !== 255 || color.g !==255 || color.b !== 255))
+ this._textureToRender = this._textureToRender._generateColorTexture(color.r,color.g,color.b);
+ }
+
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ wrapper.setCompositeOperation(cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc(node._blendFunc));
+ wrapper.setGlobalAlpha(alpha);
+
+ if (this._textureToRender) {
+ if (node._quadsDirty) {
+ node._rebuildQuads();
+ }
+ var sx,sy,sw,sh;
+ var x, y, w,h;
+ var textureWidth = this._textureToRender._pixelsWide;
+ var textureHeight = this._textureToRender._pixelsHigh;
+ var image = this._textureToRender._htmlElementObj;
+ var vertices = node._vertices;
+ var uvs = node._uvs;
+ var i = 0, off = 0;
+
+ if (node._renderingType === cc.Scale9Sprite.RenderingType.SLICED) {
+ // Sliced use a special vertices layout 16 vertices for 9 quads
+ for (var r = 0; r < 3; ++r) {
+ for (var c = 0; c < 3; ++c) {
+ off = r*8 + c*2;
+ x = vertices[off];
+ y = vertices[off+1];
+ w = vertices[off+10] - x;
+ h = vertices[off+11] - y;
+ y = - y - h;
+
+ sx = uvs[off] * textureWidth;
+ sy = uvs[off+11] * textureHeight;
+ sw = (uvs[off+10] - uvs[off]) * textureWidth;
+ sh = (uvs[off+1] - uvs[off+11]) * textureHeight;
+
+ if (sw > 0 && sh > 0 && w > 0 && h > 0) {
+ context.drawImage(image,
+ sx, sy, sw, sh,
+ x, y, w, h);
+ }
+ }
+ }
+ cc.g_NumberOfDraws += 9;
+ } else {
+ var quadCount = Math.floor(node._vertCount / 4);
+ for (i = 0, off = 0; i < quadCount; i++) {
+ x = vertices[off];
+ y = vertices[off+1];
+ w = vertices[off+6] - x;
+ h = vertices[off+7] - y;
+ y = - y - h;
+
+ sx = uvs[off] * textureWidth;
+ sy = uvs[off+7] * textureHeight;
+ sw = (uvs[off+6] - uvs[off]) * textureWidth;
+ sh = (uvs[off+1] - uvs[off+7]) * textureHeight;
+
+
+ if (this._textureToRender._pattern !== '') {
+ wrapper.setFillStyle(context.createPattern(image, this._textureToRender._pattern));
+ context.fillRect(x, y, w, h);
+ } else {
+ if (sw > 0 && sh > 0 && w > 0 && h > 0) {
+ context.drawImage(image,
+ sx, sy, sw, sh,
+ x, y, w, h);
+ }
+ }
+ off += 8;
+ }
+ cc.g_NumberOfDraws += quadCount;
+ }
+ }
+ };
+
+})();
diff --git a/extensions/ccui/base-classes/UIScale9SpriteWebGLRenderCmd.js b/extensions/ccui/base-classes/UIScale9SpriteWebGLRenderCmd.js
new file mode 100644
index 0000000000..16df4ee947
--- /dev/null
+++ b/extensions/ccui/base-classes/UIScale9SpriteWebGLRenderCmd.js
@@ -0,0 +1,159 @@
+/****************************************************************************
+ Copyright (c) 2013-2016 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function() {
+ if(!cc.Node.WebGLRenderCmd) return;
+
+ ccui.Scale9Sprite.WebGLRenderCmd = function (renderable) {
+ cc.Node.WebGLRenderCmd.call(this, renderable);
+
+ this._needDraw = true;
+
+ this._color = new Uint32Array(1);
+ this._dirty = false;
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
+ };
+
+
+
+ var Scale9Sprite = ccui.Scale9Sprite;
+ var proto = ccui.Scale9Sprite.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ proto.constructor = ccui.Scale9Sprite.WebGLRenderCmd;
+
+ proto.needDraw = function () {
+ return this._needDraw && this._node.loaded();
+ };
+
+ proto._uploadSliced = function (vertices, uvs, color, z, f32buffer, ui32buffer, offset) {
+ var off;
+ for (var r = 0; r < 3; ++r) {
+ for (var c = 0; c < 3; ++c) {
+ off = r*8 + c*2;
+ // lb
+ f32buffer[offset] = vertices[off];
+ f32buffer[offset+1] = vertices[off+1];
+ f32buffer[offset+2] = z;
+ ui32buffer[offset+3] = color[0];
+ f32buffer[offset+4] = uvs[off];
+ f32buffer[offset+5] = uvs[off+1];
+ offset += 6;
+ // rb
+ f32buffer[offset] = vertices[off+2];
+ f32buffer[offset + 1] = vertices[off+3];
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = color[0];
+ f32buffer[offset + 4] = uvs[off+2];
+ f32buffer[offset + 5] = uvs[off+3];
+ offset += 6;
+ // lt
+ f32buffer[offset] = vertices[off+8];
+ f32buffer[offset + 1] = vertices[off+9];
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = color[0];
+ f32buffer[offset + 4] = uvs[off+8];
+ f32buffer[offset + 5] = uvs[off+9];
+ offset += 6;
+ // rt
+ f32buffer[offset] = vertices[off+10];
+ f32buffer[offset + 1] = vertices[off+11];
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = color[0];
+ f32buffer[offset + 4] = uvs[off+10];
+ f32buffer[offset + 5] = uvs[off+11];
+ offset += 6;
+ }
+ }
+ return 36;
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+ this._node._rebuildQuads();
+ };
+
+ proto._setColorDirty = function () {
+ };
+
+ proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset){
+ var node = this._node;
+ if (this._displayedOpacity === 0) {
+ return 0;
+ }
+
+ // Rebuild vertex data
+ if (node._quadsDirty) {
+ node._rebuildQuads();
+ }
+
+ // Color & z
+ var opacity = this._displayedOpacity;
+ var r = this._displayedColor.r,
+ g = this._displayedColor.g,
+ b = this._displayedColor.b;
+ if (node._opacityModifyRGB) {
+ var a = opacity / 255;
+ r *= a;
+ g *= a;
+ b *= a;
+ }
+ this._color[0] = ((opacity<<24) | (b<<16) | (g<<8) | r);
+ var z = node._vertexZ;
+
+ // Upload data
+ var vertices = node._vertices;
+ var uvs = node._uvs;
+ var types = Scale9Sprite.RenderingType;
+ var offset = vertexDataOffset;
+ var len = 0;
+ switch (node._renderingType) {
+ case types.SIMPLE:
+ // Inline for performance
+ len = this._node._vertCount;
+ for (var i = 0, srcOff = 0; i < len; i++, srcOff += 2) {
+ f32buffer[offset] = vertices[srcOff];
+ f32buffer[offset + 1] = vertices[srcOff+1];
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = this._color[0];
+ f32buffer[offset + 4] = uvs[srcOff];
+ f32buffer[offset + 5] = uvs[srcOff+1];
+ offset += 6;
+ }
+ break;
+ case types.SLICED:
+ len = this._uploadSliced(vertices, uvs, this._color, z, f32buffer, ui32buffer, offset);
+ break;
+ }
+ return len;
+ };
+
+ proto.setState = function (state) {
+ if (state === Scale9Sprite.state.NORMAL) {
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
+ } else if (state === Scale9Sprite.state.GRAY) {
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR_GRAY);
+ }
+ };
+
+
+})();
diff --git a/extensions/ccui/base-classes/UIWidget.js b/extensions/ccui/base-classes/UIWidget.js
new file mode 100644
index 0000000000..b01ac526db
--- /dev/null
+++ b/extensions/ccui/base-classes/UIWidget.js
@@ -0,0 +1,2087 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+ccui._FocusNavigationController = cc.Class.extend({
+ _keyboardListener: null,
+ _firstFocusedWidget: null,
+ _enableFocusNavigation: false,
+ _keyboardEventPriority: 1,
+
+ enableFocusNavigation: function (flag) {
+ if (this._enableFocusNavigation === flag)
+ return;
+
+ this._enableFocusNavigation = flag;
+ if (flag)
+ this._addKeyboardEventListener();
+ else
+ this._removeKeyboardEventListener();
+ },
+
+ _setFirstFocsuedWidget: function (widget) {
+ this._firstFocusedWidget = widget;
+ },
+
+ _onKeyPressed: function (keyCode, event) {
+ if (this._enableFocusNavigation && this._firstFocusedWidget) {
+ if (keyCode === cc.KEY.dpadDown) {
+ this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.DOWN, this._firstFocusedWidget);
+ }
+ if (keyCode === cc.KEY.dpadUp) {
+ this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.UP, this._firstFocusedWidget);
+ }
+ if (keyCode === cc.KEY.dpadLeft) {
+ this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.LEFT, this._firstFocusedWidget);
+ }
+ if (keyCode === cc.KEY.dpadRight) {
+ this._firstFocusedWidget = this._firstFocusedWidget.findNextFocusedWidget(ccui.Widget.RIGHT, this._firstFocusedWidget);
+ }
+ }
+ },
+
+ _addKeyboardEventListener: function () {
+ if (!this._keyboardListener) {
+ this._keyboardListener = cc.EventListener.create({
+ event: cc.EventListener.KEYBOARD,
+ onKeyReleased: this._onKeyPressed.bind(this)
+ });
+ cc.eventManager.addListener(this._keyboardListener, this._keyboardEventPriority);
+ }
+ },
+
+ _removeKeyboardEventListener: function () {
+ if (this._keyboardListener) {
+ cc.eventManager.removeEventListener(this._keyboardListener);
+ this._keyboardListener = null;
+ }
+ }
+});
+
+ccui.__LAYOUT_COMPONENT_NAME = "__ui_layout";
+
+/**
+ * The base class for ccui controls and layout
+ * @sample
+ * var uiWidget = new ccui.Widget();
+ * this.addChild(uiWidget);
+ * @class
+ * @extends ccui.ProtectedNode
+ *
+ * @property {Number} xPercent - Position x in percentage of width
+ * @property {Number} yPercent - Position y in percentage of height
+ * @property {Number} widthPercent - Width in percentage of parent width
+ * @property {Number} heightPercent - Height in percentage of parent height
+ * @property {ccui.Widget} widgetParent - <@readonly> The direct parent when it's a widget also, otherwise equals null
+ * @property {Boolean} enabled - Indicate whether the widget is enabled
+ * @property {Boolean} focused - Indicate whether the widget is focused
+ * @property {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} sizeType - The size type of the widget
+ * @property {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER} widgetType - <@readonly> The type of the widget
+ * @property {Boolean} touchEnabled - Indicate whether touch events are enabled
+ * @property {Boolean} updateEnabled - Indicate whether the update function is scheduled
+ * @property {Boolean} bright - Indicate whether the widget is bright
+ * @property {String} name - The name of the widget
+ * @property {Number} actionTag - The action tag of the widget
+ */
+ccui.Widget = ccui.ProtectedNode.extend(/** @lends ccui.Widget# */{
+ _enabled: true, ///< Highest control of widget
+ _bright: true, ///< is this widget bright
+ _touchEnabled: false, ///< is this widget touch endabled
+
+ _brightStyle: null, ///< bright style
+
+ _touchBeganPosition: null, ///< touch began point
+ _touchMovePosition: null, ///< touch moved point
+ _touchEndPosition: null, ///< touch ended point
+
+ _touchEventListener: null,
+ _touchEventSelector: null,
+
+ _name: "default",
+ _widgetType: null,
+ _actionTag: 0,
+ _customSize: null,
+ _layoutParameterDictionary: null,
+ _layoutParameterType: 0,
+
+ _focused: false,
+ _focusEnabled: true,
+
+ _ignoreSize: false,
+ _affectByClipping: false,
+
+ _sizeType: null,
+ _sizePercent: null,
+ _positionType: null,
+ _positionPercent: null,
+ _hit: false,
+ _nodes: null,
+ _touchListener: null,
+ _className: "Widget",
+ _flippedX: false,
+ _flippedY: false,
+ _opacity: 255,
+ _highlight: false,
+
+ _touchEventCallback: null,
+ _clickEventListener: null,
+
+ _propagateTouchEvents: true,
+ _unifySize: false,
+
+ _callbackName: null,
+ _callbackType: null,
+ _usingLayoutComponent: false,
+ _inViewRect: true,
+
+ /**
+ * Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @function
+ */
+ ctor: function () {
+ cc.ProtectedNode.prototype.ctor.call(this);
+ this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
+ this._touchBeganPosition = cc.p(0, 0);
+ this._touchMovePosition = cc.p(0, 0);
+ this._touchEndPosition = cc.p(0, 0);
+ this._widgetType = ccui.Widget.TYPE_WIDGET;
+ this._customSize = cc.size(0, 0);
+ this._layoutParameterDictionary = {};
+ this._sizeType = ccui.Widget.SIZE_ABSOLUTE;
+ this._sizePercent = cc.p(0, 0);
+ this._positionType = ccui.Widget.POSITION_ABSOLUTE;
+ this._positionPercent = cc.p(0, 0);
+ this._nodes = [];
+ this._layoutParameterType = ccui.LayoutParameter.NONE;
+ ccui.Widget.prototype.init.call(this);
+ },
+
+ /**
+ * initializes state of widget. please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
+ * @returns {boolean}
+ */
+ init: function () {
+ this._layoutParameterDictionary = {};
+ this._initRenderer();
+ this.setBright(true);
+
+ this.onFocusChanged = this.onFocusChange;
+ this.onNextFocusedWidget = null;
+ this.setAnchorPoint(cc.p(0.5, 0.5));
+
+ this.ignoreContentAdaptWithSize(true);
+ return true;
+ },
+
+ /**
+ * Calls updateSizeAndPosition and its parent's onEnter
+ * @override
+ */
+ onEnter: function () {
+ var locListener = this._touchListener;
+ if (locListener && !locListener._isRegistered() && this._touchEnabled)
+ cc.eventManager.addListener(locListener, this);
+ if(!this._usingLayoutComponent)
+ this.updateSizeAndPosition();
+ if (this._sizeDirty)
+ this._onSizeChanged();
+ cc.ProtectedNode.prototype.onEnter.call(this);
+ },
+
+ /**
+ * Calls unscheduleUpdate and its parent's onExit
+ * @override
+ */
+ onExit: function () {
+ this.unscheduleUpdate();
+ cc.ProtectedNode.prototype.onExit.call(this);
+ },
+
+ _getOrCreateLayoutComponent: function(){
+ var layoutComponent = this.getComponent(ccui.__LAYOUT_COMPONENT_NAME);
+ if (null == layoutComponent){
+ layoutComponent = new ccui.LayoutComponent();
+ this.addComponent(layoutComponent);
+ }
+ return layoutComponent;
+ },
+
+ /**
+ * The direct parent when it's a widget also, otherwise equals null
+ * @returns {ccui.Widget|null}
+ */
+ getWidgetParent: function () {
+ var widget = this.getParent();
+ if (widget instanceof ccui.Widget)
+ return widget;
+ return null;
+ },
+
+ _updateContentSizeWithTextureSize: function (size) {
+ if(this._unifySize){
+ this.setContentSize(size);
+ return;
+ }
+ this.setContentSize(this._ignoreSize ? size : this._customSize);
+ },
+
+ _isAncestorsEnabled: function () {
+ var parentWidget = this._getAncensterWidget(this);
+ if (parentWidget == null)
+ return true;
+ if (parentWidget && !parentWidget.isEnabled())
+ return false;
+
+ return parentWidget._isAncestorsEnabled();
+ },
+
+ /**
+ * Allow widget touch events to propagate to its parents. Set false will disable propagation
+ * @since v3.2
+ * @param {Boolean} isPropagate
+ */
+ setPropagateTouchEvents: function (isPropagate) {
+ this._propagateTouchEvents = isPropagate;
+ },
+
+ /**
+ * Return whether the widget is propagate touch events to its parents or not
+ * @since v3.2
+ * @returns {boolean}
+ */
+ isPropagateTouchEvents: function () {
+ return this._propagateTouchEvents;
+ },
+
+ /**
+ * Specify widget to swallow touches or not
+ * @since v3.2
+ * @param {Boolean} swallow
+ */
+ setSwallowTouches: function (swallow) {
+ if (this._touchListener)
+ this._touchListener.setSwallowTouches(swallow);
+ },
+
+ /**
+ * Return whether the widget is swallowing touch or not
+ * @since v3.2
+ * @returns {boolean}
+ */
+ isSwallowTouches: function () {
+ if (this._touchListener) {
+ //return true; //todo need test
+ return this._touchListener.isSwallowTouches();
+ }
+ return false;
+ },
+
+ _getAncensterWidget: function (node) {
+ if (null == node)
+ return null;
+
+ var parent = node.getParent();
+ if (null == parent)
+ return null;
+
+ if (parent instanceof ccui.Widget)
+ return parent;
+ else
+ return this._getAncensterWidget(parent.getParent());
+ },
+
+ _isAncestorsVisible: function (node) {
+ if (null == node)
+ return true;
+
+ var parent = node.getParent();
+
+ if (parent && !parent.isVisible())
+ return false;
+ return this._isAncestorsVisible(parent);
+ },
+
+ /**
+ *
+ * Sets whether the widget is enabled
+ * true if the widget is enabled, widget may be touched , false if the widget is disabled, widget cannot be touched.
+ * The default value is true, a widget is default to enabled
+ *
+ * @param {Boolean} enabled
+ */
+ setEnabled: function (enabled) {
+ this._enabled = enabled;
+ this.setBright(enabled);
+ },
+
+ /**
+ * initializes renderer of widget.
+ */
+ _initRenderer: function () {
+ },
+
+ /**
+ * Sets _customSize of ccui.Widget, if ignoreSize is true, the content size is its renderer's contentSize, otherwise the content size is parameter.
+ * and updates size percent by parent content size. At last, updates its children's size and position.
+ * @param {cc.Size|Number} contentSize content size or width of content size
+ * @param {Number} [height]
+ * @override
+ */
+ setContentSize: function(contentSize, height){
+ cc.Node.prototype.setContentSize.call(this, contentSize, height);
+
+ var locWidth = this._contentSize.width;
+ var locHeight = this._contentSize.height;
+
+ this._customSize.width = locWidth;
+ this._customSize.height = locHeight;
+ if(this._unifySize){
+ //unify size logic
+ } else if (this._ignoreSize) {
+ this._contentSize = this.getVirtualRendererSize();
+ }
+ if (!this._usingLayoutComponent && this._running) {
+ var widgetParent = this.getWidgetParent();
+ var pSize = widgetParent ? widgetParent.getContentSize() : this._parent.getContentSize();
+ this._sizePercent.x = (pSize.width > 0.0) ? locWidth / pSize.width : 0.0;
+ this._sizePercent.y = (pSize.height > 0.0) ? locHeight / pSize.height : 0.0;
+ }
+
+ if (this._running) {
+ this._onSizeChanged();
+ } else {
+ this._sizeDirty = true;
+ }
+ },
+
+ _setWidth: function (w) {
+ if (w === this._contentSize.width) {
+ return;
+ }
+ cc.Node.prototype._setWidth.call(this, w);
+ this._customSize.width = w;
+ if(this._unifySize){
+ //unify size logic
+ } else if (this._ignoreSize) {
+ this._contentSize = this.getVirtualRendererSize();
+ }
+
+ if (!this._usingLayoutComponent && this._running) {
+ var widgetParent = this.getWidgetParent();
+ var locWidth = widgetParent ? widgetParent.width : this._parent.width;
+ this._sizePercent.x = locWidth > 0 ? this._customSize.width / locWidth : 0;
+ }
+
+ if (this._running) {
+ this._onSizeChanged();
+ } else {
+ this._sizeDirty = true;
+ }
+ },
+ _setHeight: function (h) {
+ if (h === this._contentSize.height) {
+ return;
+ }
+
+ cc.Node.prototype._setHeight.call(this, h);
+ this._customSize.height = h;
+ if(this._unifySize){
+ //unify size logic
+ } else if (this._ignoreSize) {
+ this._contentSize = this.getVirtualRendererSize();
+ }
+
+ if (!this._usingLayoutComponent && this._running) {
+ var widgetParent = this.getWidgetParent();
+ var locH = widgetParent ? widgetParent.height : this._parent.height;
+ this._sizePercent.y = locH > 0 ? this._customSize.height / locH : 0;
+ }
+
+ if (this._running) {
+ this._onSizeChanged();
+ } else {
+ this._sizeDirty = true;
+ }
+ },
+
+ /**
+ * Changes the percent that is widget's percent size
+ * @param {cc.Point} percent that is widget's percent size, width and height value from 0 to 1.
+ */
+ setSizePercent: function (percent) {
+ if(this._usingLayoutComponent){
+ var component = this._getOrCreateLayoutComponent();
+ component.setUsingPercentContentSize(true);
+ component.setPercentContentSize(percent);
+ component.refreshLayout();
+ return;
+ }
+
+ this._sizePercent.x = percent.x;
+ this._sizePercent.y = percent.y;
+ var width = this._customSize.width, height = this._customSize.height;
+ if (this._running) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent) {
+ width = widgetParent.width * percent.x;
+ height = widgetParent.height * percent.y;
+ } else {
+ width = this._parent.width * percent.x;
+ height = this._parent.height * percent.y;
+ }
+ }
+ if (this._ignoreSize)
+ this.setContentSize(this.getVirtualRendererSize());
+ else
+ this.setContentSize(width, height);
+
+ this._customSize.width = width;
+ this._customSize.height = height;
+ },
+
+ _setWidthPercent: function (percent) {
+ this._sizePercent.x = percent;
+ var width = this._customSize.width;
+ if (this._running) {
+ var widgetParent = this.getWidgetParent();
+ width = (widgetParent ? widgetParent.width : this._parent.width) * percent;
+ }
+ if (this._ignoreSize)
+ this._setWidth(this.getVirtualRendererSize().width);
+ else
+ this._setWidth(width);
+ this._customSize.width = width;
+ },
+ _setHeightPercent: function (percent) {
+ this._sizePercent.y = percent;
+ var height = this._customSize.height;
+ if (this._running) {
+ var widgetParent = this.getWidgetParent();
+ height = (widgetParent ? widgetParent.height : this._parent.height) * percent;
+ }
+ if (this._ignoreSize)
+ this._setHeight(this.getVirtualRendererSize().height);
+ else
+ this._setHeight(height);
+ this._customSize.height = height;
+ },
+
+ /**
+ * updates its size by size type and its position by position type.
+ * @param {cc.Size} [parentSize] parent size
+ */
+ updateSizeAndPosition: function (parentSize) {
+ if (!parentSize) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent)
+ parentSize = widgetParent.getLayoutSize();
+ else
+ parentSize = this._parent.getContentSize();
+ }
+
+ switch (this._sizeType) {
+ case ccui.Widget.SIZE_ABSOLUTE:
+ if (this._ignoreSize)
+ this.setContentSize(this.getVirtualRendererSize());
+ else
+ this.setContentSize(this._customSize);
+ this._sizePercent.x = (parentSize.width > 0) ? this._customSize.width / parentSize.width : 0;
+ this._sizePercent.y = (parentSize.height > 0) ? this._customSize.height / parentSize.height : 0;
+ break;
+ case ccui.Widget.SIZE_PERCENT:
+ var cSize = cc.size(parentSize.width * this._sizePercent.x, parentSize.height * this._sizePercent.y);
+ if (this._ignoreSize)
+ this.setContentSize(this.getVirtualRendererSize());
+ else
+ this.setContentSize(cSize);
+ this._customSize.width = cSize.width;
+ this._customSize.height = cSize.height;
+ break;
+ default:
+ break;
+ }
+ this._onSizeChanged();
+ var absPos = this.getPosition();
+ switch (this._positionType) {
+ case ccui.Widget.POSITION_ABSOLUTE:
+ if (parentSize.width <= 0 || parentSize.height <= 0) {
+ this._positionPercent.x = this._positionPercent.y = 0;
+ } else {
+ this._positionPercent.x = absPos.x / parentSize.width;
+ this._positionPercent.y = absPos.y / parentSize.height;
+ }
+ break;
+ case ccui.Widget.POSITION_PERCENT:
+ absPos = cc.p(parentSize.width * this._positionPercent.x, parentSize.height * this._positionPercent.y);
+ break;
+ default:
+ break;
+ }
+ if (this._parent instanceof ccui.ImageView) {
+ var renderer = this._parent._imageRenderer;
+ if (renderer && !renderer._textureLoaded)
+ return;
+ }
+ this.setPosition(absPos);
+ },
+
+ /**TEXTURE_RES_TYPE
+ * Changes the size type of widget.
+ * @param {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} type that is widget's size type
+ */
+ setSizeType: function (type) {
+ this._sizeType = type;
+ if (this._usingLayoutComponent) {
+ var component = this._getOrCreateLayoutComponent();
+ component.setUsingPercentContentSize(this._sizeType === ccui.SIZE_PERCENT);
+ }
+ },
+
+ /**
+ * Gets the size type of widget.
+ * @returns {ccui.Widget.SIZE_ABSOLUTE|ccui.Widget.SIZE_PERCENT} that is widget's size type
+ */
+ getSizeType: function () {
+ return this._sizeType;
+ },
+
+ /**
+ * Ignore the widget size
+ * @param {Boolean} ignore true that widget will ignore it's size, use texture size, false otherwise. Default value is true.
+ */
+ ignoreContentAdaptWithSize: function (ignore) {
+ if(this._unifySize){
+ this.setContentSize(this._customSize);
+ return;
+ }
+
+ if (this._ignoreSize === ignore)
+ return;
+
+ this._ignoreSize = ignore;
+ this.setContentSize(ignore ? this.getVirtualRendererSize() : this._customSize);
+ //this._onSizeChanged();
+ },
+
+ /**
+ * Gets whether ignore the content size (custom size)
+ * @returns {boolean} true that widget will ignore it's size, use texture size, false otherwise.
+ */
+ isIgnoreContentAdaptWithSize: function () {
+ return this._ignoreSize;
+ },
+
+ /**
+ * Get custom size of ccui.Widget
+ * @returns {cc.Size}
+ */
+ getCustomSize: function () {
+ return cc.size(this._customSize);
+ },
+
+ /**
+ * Gets layout size of ccui.Widget.
+ * @returns {cc.Size}
+ */
+ getLayoutSize: function () {
+ return cc.size(this._contentSize);
+ },
+
+ /**
+ * Returns size percent of ccui.Widget
+ * @returns {cc.Point}
+ */
+ getSizePercent: function () {
+ if(this._usingLayoutComponent){
+ var component = this._getOrCreateLayoutComponent();
+ this._sizePercent = component.getPercentContentSize();
+ }
+ return this._sizePercent;
+ },
+ _getWidthPercent: function () {
+ return this._sizePercent.x;
+ },
+ _getHeightPercent: function () {
+ return this._sizePercent.y;
+ },
+
+ /**
+ * Gets world position of ccui.Widget.
+ * @returns {cc.Point} world position of ccui.Widget.
+ */
+ getWorldPosition: function () {
+ return this.convertToWorldSpace(cc.p(this._anchorPoint.x * this._contentSize.width, this._anchorPoint.y * this._contentSize.height));
+ },
+
+ /**
+ * Gets the Virtual Renderer of widget.
+ * @returns {ccui.Widget}
+ */
+ getVirtualRenderer: function () {
+ return this;
+ },
+
+ /**
+ * Gets the content size of widget. Content size is widget's texture size.
+ */
+ getVirtualRendererSize: function () {
+ return cc.size(this._contentSize);
+ },
+
+ /**
+ * call back function called when size changed.
+ */
+ _onSizeChanged: function () {
+ if(!this._usingLayoutComponent){
+ var locChildren = this.getChildren();
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var child = locChildren[i];
+ if (child instanceof ccui.Widget)
+ child.updateSizeAndPosition();
+ }
+ this._sizeDirty = false;
+ }
+ },
+
+ /**
+ * Sets whether the widget is touch enabled. The default value is false, a widget is default to touch disabled
+ * @param {Boolean} enable true if the widget is touch enabled, false if the widget is touch disabled.
+ */
+ setTouchEnabled: function (enable) {
+ if (this._touchEnabled === enable)
+ return;
+
+ this._touchEnabled = enable; //TODO need consider remove and re-add.
+ if (this._touchEnabled) {
+ if (!this._touchListener)
+ this._touchListener = cc.EventListener.create({
+ event: cc.EventListener.TOUCH_ONE_BY_ONE,
+ swallowTouches: true,
+ onTouchBegan: this.onTouchBegan.bind(this),
+ onTouchMoved: this.onTouchMoved.bind(this),
+ onTouchEnded: this.onTouchEnded.bind(this)
+ });
+ cc.eventManager.addListener(this._touchListener, this);
+ } else {
+ cc.eventManager.removeListener(this._touchListener);
+ }
+ },
+
+ /**
+ * Returns whether or not touch is enabled.
+ * @returns {boolean} true if the widget is touch enabled, false if the widget is touch disabled.
+ */
+ isTouchEnabled: function () {
+ return this._touchEnabled;
+ },
+
+ /**
+ * Determines if the widget is highlighted
+ * @returns {boolean} true if the widget is highlighted, false if the widget is not highlighted .
+ */
+ isHighlighted: function () {
+ return this._highlight;
+ },
+
+ /**
+ * Sets whether the widget is highlighted. The default value is false, a widget is default to not highlighted
+ * @param highlight true if the widget is highlighted, false if the widget is not highlighted.
+ */
+ setHighlighted: function (highlight) {
+ if (highlight === this._highlight)
+ return;
+ this._highlight = highlight;
+ if (this._bright) {
+ if (this._highlight)
+ this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT);
+ else
+ this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL);
+ } else
+ this._onPressStateChangedToDisabled();
+ },
+
+ /**
+ * Determines if the widget is on focused
+ * @returns {boolean} whether the widget is focused or not
+ */
+ isFocused: function () {
+ return this._focused;
+ },
+
+ /**
+ * Sets whether the widget is on focused
+ * The default value is false, a widget is default to not on focused
+ * @param {boolean} focus pass true to let the widget get focus or pass false to let the widget lose focus
+ */
+ setFocused: function (focus) {
+ this._focused = focus;
+ //make sure there is only one focusedWidget
+ if (focus) {
+ ccui.Widget._focusedWidget = this;
+ if (ccui.Widget._focusNavigationController)
+ ccui.Widget._focusNavigationController._setFirstFocsuedWidget(this);
+ }
+ },
+
+ /**
+ * returns whether the widget could accept focus.
+ * @returns {boolean} true represent the widget could accept focus, false represent the widget couldn't accept focus
+ */
+ isFocusEnabled: function () {
+ return this._focusEnabled;
+ },
+
+ /**
+ * sets whether the widget could accept focus.
+ * @param {Boolean} enable true represent the widget could accept focus, false represent the widget couldn't accept focus
+ */
+ setFocusEnabled: function (enable) {
+ this._focusEnabled = enable;
+ },
+
+ /**
+ *
+ * When a widget is in a layout, you could call this method to get the next focused widget within a specified direction.
+ * If the widget is not in a layout, it will return itself
+ *
+ * @param direction the direction to look for the next focused widget in a layout
+ * @param current the current focused widget
+ * @return the next focused widget in a layout
+ */
+ findNextFocusedWidget: function (direction, current) {
+ if (null === this.onNextFocusedWidget || null == this.onNextFocusedWidget(direction)) {
+ var isLayout = current instanceof ccui.Layout;
+ if (this.isFocused() || isLayout) {
+ var layout = this.getParent();
+ if (null === layout || !(layout instanceof ccui.Layout)) {
+ //the outer layout's default behaviour is : loop focus
+ if (isLayout)
+ return current.findNextFocusedWidget(direction, current);
+ return current;
+ } else
+ return layout.findNextFocusedWidget(direction, current);
+ } else
+ return current;
+ } else {
+ var getFocusWidget = this.onNextFocusedWidget(direction);
+ this.dispatchFocusEvent(this, getFocusWidget);
+ return getFocusWidget;
+ }
+ },
+
+ /**
+ * when a widget calls this method, it will get focus immediately.
+ */
+ requestFocus: function () {
+ if (this === ccui.Widget._focusedWidget)
+ return;
+ this.dispatchFocusEvent(ccui.Widget._focusedWidget, this);
+ },
+
+ /**
+ * no matter what widget object you call this method on , it will return you the exact one focused widget
+ */
+ getCurrentFocusedWidget: function () {
+ return ccui.Widget._focusedWidget;
+ },
+
+ /**
+ *
+ * When a widget lose/get focus, this method will be called. Be Caution when you provide your own version,
+ * you must call widget.setFocused(true/false) to change the focus state of the current focused widget;
+ *
+ */
+ onFocusChanged: null,
+
+ /**
+ * use this function to manually specify the next focused widget regards to each direction
+ */
+ onNextFocusedWidget: null,
+
+ /**
+ * Sends the touch event to widget's parent, its subclass will override it, e.g. ccui.ScrollView, ccui.PageView
+ * @param {Number} eventType
+ * @param {ccui.Widget} sender
+ * @param {cc.Touch} touch
+ */
+ interceptTouchEvent: function (eventType, sender, touch) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent)
+ widgetParent.interceptTouchEvent(eventType, sender, touch);
+ },
+
+ /**
+ * This method is called when a focus change event happens
+ * @param {ccui.Widget} widgetLostFocus
+ * @param {ccui.Widget} widgetGetFocus
+ */
+ onFocusChange: function (widgetLostFocus, widgetGetFocus) {
+ //only change focus when there is indeed a get&lose happens
+ if (widgetLostFocus)
+ widgetLostFocus.setFocused(false);
+ if (widgetGetFocus)
+ widgetGetFocus.setFocused(true);
+ },
+
+ /**
+ * Dispatch a EventFocus through a EventDispatcher
+ * @param {ccui.Widget} widgetLostFocus
+ * @param {ccui.Widget} widgetGetFocus
+ */
+ dispatchFocusEvent: function (widgetLostFocus, widgetGetFocus) {
+ //if the widgetLoseFocus doesn't get focus, it will use the previous focused widget instead
+ if (widgetLostFocus && !widgetLostFocus.isFocused())
+ widgetLostFocus = ccui.Widget._focusedWidget;
+
+ if (widgetGetFocus !== widgetLostFocus) {
+ if (widgetGetFocus && widgetGetFocus.onFocusChanged)
+ widgetGetFocus.onFocusChanged(widgetLostFocus, widgetGetFocus);
+ if (widgetLostFocus && widgetGetFocus.onFocusChanged)
+ widgetLostFocus.onFocusChanged(widgetLostFocus, widgetGetFocus);
+ cc.eventManager.dispatchEvent(new cc.EventFocus(widgetLostFocus, widgetGetFocus));
+ }
+ },
+
+ /**
+ * Sets whether the widget is bright. The default value is true, a widget is default to bright
+ * @param {Boolean} bright true if the widget is bright, false if the widget is dark.
+ */
+ setBright: function (bright) {
+ this._bright = bright;
+ if (this._bright) {
+ this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
+ this.setBrightStyle(ccui.Widget.BRIGHT_STYLE_NORMAL);
+ } else
+ this._onPressStateChangedToDisabled();
+ },
+
+ /**
+ * To set the bright style of ccui.Widget.
+ * @param {Number} style BRIGHT_NORMAL the widget is normal state, BRIGHT_HIGHLIGHT the widget is height light state.
+ */
+ setBrightStyle: function (style) {
+ if (this._brightStyle === style)
+ return;
+
+ style = style || ccui.Widget.BRIGHT_STYLE_NORMAL;
+ this._brightStyle = style;
+ switch (this._brightStyle) {
+ case ccui.Widget.BRIGHT_STYLE_NORMAL:
+ this._onPressStateChangedToNormal();
+ break;
+ case ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT:
+ this._onPressStateChangedToPressed();
+ break;
+ default:
+ break;
+ }
+ },
+
+ _onPressStateChangedToNormal: function () {
+ },
+
+ _onPressStateChangedToPressed: function () {
+ },
+
+ _onPressStateChangedToDisabled: function () {
+ },
+
+ _updateChildrenDisplayedRGBA: function () {
+ this.setColor(this.getColor());
+ this.setOpacity(this.getOpacity());
+ },
+
+ /**
+ * A call back function when widget lost of focus.
+ */
+ didNotSelectSelf: function () {
+ },
+
+ /**
+ *
+ * The callback of touch began event.
+ * If the bounding box of ccui.Widget contains the touch point, it will do the following things:
+ * 1. sets highlight state,
+ * 2. sends event to parent widget by interceptTouchEvent
+ * 3. calls the callback of touch began event.
+ * 4. returns true,
+ * otherwise returns false directly.
+ *
+ * @override
+ * @param {cc.Touch} touch
+ * @param {cc.Event} event
+ * @returns {boolean}
+ */
+ onTouchBegan: function (touch, event) {
+ this._hit = false;
+ if (this.isVisible() && this.isEnabled() && this._isAncestorsEnabled() && this._isAncestorsVisible(this)) {
+ var touchPoint = touch.getLocation();
+ this._touchBeganPosition.x = touchPoint.x;
+ this._touchBeganPosition.y = touchPoint.y;
+ if (this.hitTest(this._touchBeganPosition) && this.isClippingParentContainsPoint(this._touchBeganPosition))
+ this._hit = true;
+ }
+ if (!this._hit) {
+ return false;
+ }
+ this.setHighlighted(true);
+
+ /*
+ * Propagate touch events to its parents
+ */
+ if (this._propagateTouchEvents) {
+ this.propagateTouchEvent(ccui.Widget.TOUCH_BEGAN, this, touch);
+ }
+
+ this._pushDownEvent();
+ return true;
+ },
+
+ propagateTouchEvent: function (event, sender, touch) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent) {
+ widgetParent.interceptTouchEvent(event, sender, touch);
+ }
+ },
+
+ /**
+ *
+ * The callback of touch moved event.
+ * It sets the highlight state by touch, sends event to parent widget by interceptTouchEvent and calls the callback of touch moved event.
+ *
+ * @param {cc.Touch} touch
+ * @param {cc.Event} event
+ */
+ onTouchMoved: function (touch, event) {
+ var touchPoint = touch.getLocation();
+ this._touchMovePosition.x = touchPoint.x;
+ this._touchMovePosition.y = touchPoint.y;
+ this.setHighlighted(this.hitTest(touchPoint));
+ /*
+ * Propagate touch events to its parents
+ */
+ if (this._propagateTouchEvents)
+ this.propagateTouchEvent(ccui.Widget.TOUCH_MOVED, this, touch);
+ this._moveEvent();
+ },
+
+ /**
+ *
+ * The callback of touch end event
+ * It sends event to parent widget by interceptTouchEvent,
+ * calls the callback of touch end event (highlight= true) or touch canceled event (highlight= false).
+ * sets the highlight state to false ,
+ *
+ * @param touch
+ * @param event
+ */
+ onTouchEnded: function (touch, event) {
+ var touchPoint = touch.getLocation();
+ this._touchEndPosition.x = touchPoint.x;
+ this._touchEndPosition.y = touchPoint.y;
+ /*
+ * Propagate touch events to its parents
+ */
+ if (this._propagateTouchEvents)
+ this.propagateTouchEvent(ccui.Widget.TOUCH_ENDED, this, touch);
+
+ var highlight = this._highlight;
+ this.setHighlighted(false);
+ if (highlight)
+ this._releaseUpEvent();
+ else
+ this._cancelUpEvent();
+ },
+
+ /**
+ * A call back function called when widget is selected, and on touch canceled.
+ * @param {cc.Point} touchPoint
+ */
+ onTouchCancelled: function (touchPoint) {
+ this.setHighlighted(false);
+ this._cancelUpEvent();
+ },
+
+ /**
+ * A call back function called when widget is selected, and on touch long clicked.
+ * @param {cc.Point} touchPoint
+ */
+ onTouchLongClicked: function (touchPoint) {
+ this.longClickEvent();
+ },
+
+ //call back function called widget's state changed to dark.
+ _pushDownEvent: function () {
+ if (this._touchEventCallback)
+ this._touchEventCallback(this, ccui.Widget.TOUCH_BEGAN);
+ if (this._touchEventListener && this._touchEventSelector)
+ this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_BEGAN);
+ },
+
+ _moveEvent: function () {
+ if (this._touchEventCallback)
+ this._touchEventCallback(this, ccui.Widget.TOUCH_MOVED);
+ if (this._touchEventListener && this._touchEventSelector)
+ this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_MOVED);
+ },
+
+ _releaseUpEvent: function () {
+ if (this._touchEventCallback)
+ this._touchEventCallback(this, ccui.Widget.TOUCH_ENDED);
+ if (this._touchEventListener && this._touchEventSelector)
+ this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_ENDED);
+ if (this._clickEventListener)
+ this._clickEventListener(this);
+ },
+
+ _cancelUpEvent: function () {
+ if (this._touchEventCallback)
+ this._touchEventCallback(this, ccui.Widget.TOUCH_CANCELED);
+ if (this._touchEventListener && this._touchEventSelector)
+ this._touchEventSelector.call(this._touchEventListener, this, ccui.Widget.TOUCH_CANCELED);
+ },
+
+ longClickEvent: function () {
+ //TODO it will implement in v3.1
+ },
+
+ /**
+ * Sets the touch event target/selector of the ccui.Widget
+ * @param {Function} selector
+ * @param {Object} target
+ */
+ addTouchEventListener: function (selector, target) {
+ if (target === undefined)
+ this._touchEventCallback = selector;
+ else {
+ this._touchEventSelector = selector;
+ this._touchEventListener = target;
+ }
+ },
+
+ addClickEventListener: function (callback) {
+ this._clickEventListener = callback;
+ },
+
+ /**
+ * Checks a point if is in widget's space
+ * @param {cc.Point} pt
+ * @returns {boolean} true if the point is in widget's space, false otherwise.
+ */
+ hitTest: function (pt) {
+ var bb = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
+ return cc.rectContainsPoint(bb, this.convertToNodeSpace(pt));
+ },
+
+ /**
+ * returns whether clipping parent widget contains point.
+ * @param {cc.Point} pt location point
+ * @returns {Boolean}
+ */
+ isClippingParentContainsPoint: function (pt) {
+ this._affectByClipping = false;
+ var parent = this.getParent();
+ var clippingParent = null;
+ while (parent) {
+ if (parent instanceof ccui.Layout) {
+ if (parent.isClippingEnabled()) {
+ this._affectByClipping = true;
+ clippingParent = parent;
+ break;
+ }
+ }
+ parent = parent.getParent();
+ }
+
+ if (!this._affectByClipping)
+ return true;
+
+ if (clippingParent) {
+ if (clippingParent.hitTest(pt))
+ return clippingParent.isClippingParentContainsPoint(pt);
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * Calls the checkChildInfo of widget's parent, its subclass will override it.
+ * @param {number} handleState
+ * @param {ccui.Widget} sender
+ * @param {cc.Point} touchPoint
+ */
+ checkChildInfo: function (handleState, sender, touchPoint) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent)
+ widgetParent.checkChildInfo(handleState, sender, touchPoint);
+ },
+
+ /**
+ * Changes the position (x,y) of the widget .
+ * The original point (0,0) is at the left-bottom corner of screen.
+ * @override
+ * @param {cc.Point|Number} pos
+ * @param {Number} [posY]
+ */
+ setPosition: function (pos, posY) {
+ if (!this._usingLayoutComponent && this._running) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent) {
+ var pSize = widgetParent.getContentSize();
+ if (pSize.width <= 0 || pSize.height <= 0) {
+ this._positionPercent.x = 0;
+ this._positionPercent.y = 0;
+ } else {
+ if (posY === undefined) {
+ this._positionPercent.x = pos.x / pSize.width;
+ this._positionPercent.y = pos.y / pSize.height;
+ } else {
+ this._positionPercent.x = pos / pSize.width;
+ this._positionPercent.y = posY / pSize.height;
+ }
+ }
+ }
+ }
+
+ cc.Node.prototype.setPosition.call(this, pos, posY);
+ //this._positionType = ccui.Widget.POSITION_ABSOLUTE;
+ },
+
+ setPositionX: function (x) {
+ if (this._running) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent) {
+ var pw = widgetParent.width;
+ if (pw <= 0)
+ this._positionPercent.x = 0;
+ else
+ this._positionPercent.x = x / pw;
+ }
+ }
+
+ cc.Node.prototype.setPositionX.call(this, x);
+ },
+ setPositionY: function (y) {
+ if (this._running) {
+ var widgetParent = this.getWidgetParent();
+ if (widgetParent) {
+ var ph = widgetParent.height;
+ if (ph <= 0)
+ this._positionPercent.y = 0;
+ else
+ this._positionPercent.y = y / ph;
+ }
+ }
+
+ cc.Node.prototype.setPositionY.call(this, y);
+ },
+
+ /**
+ * Changes the position (x,y) of the widget
+ * @param {cc.Point} percent
+ */
+ setPositionPercent: function (percent) {
+ if (this._usingLayoutComponent){
+ var component = this._getOrCreateLayoutComponent();
+ component.setPositionPercentX(percent.x);
+ component.setPositionPercentY(percent.y);
+ component.refreshLayout();
+ return;
+ }else{
+ this._setXPercent(percent.x);
+ this._setYPercent(percent.y);
+ }
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+ _setXPercent: function (percent) {
+ if (this._usingLayoutComponent){
+ var component = this._getOrCreateLayoutComponent();
+ component.setPositionPercentX(percent.x);
+ component.refreshLayout();
+ return;
+ }
+ this._positionPercent.x = percent;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+ _setYPercent: function (percent) {
+ if (this._usingLayoutComponent){
+ var component = this._getOrCreateLayoutComponent();
+ component.setPositionPercentY(percent.x);
+ component.refreshLayout();
+ return;
+ }
+ this._positionPercent.y = percent;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Gets the percent (x,y) of the widget
+ * @returns {cc.Point} The percent (x,y) of the widget in OpenGL coordinates
+ */
+ getPositionPercent: function () {
+ if (this._usingLayoutComponent) {
+ var component = this._getOrCreateLayoutComponent();
+ this._positionPercent.x = component.getPositionPercentX();
+ this._positionPercent.y = component.getPositionPercentY();
+ }
+ return cc.p(this._positionPercent);
+ },
+
+ _getXPercent: function () {
+ if (this._usingLayoutComponent) {
+ var component = this._getOrCreateLayoutComponent();
+ this._positionPercent.x = component.getPositionPercentX();
+ this._positionPercent.y = component.getPositionPercentY();
+ }
+ return this._positionPercent.x;
+ },
+ _getYPercent: function () {
+ if (this._usingLayoutComponent) {
+ var component = this._getOrCreateLayoutComponent();
+ this._positionPercent.x = component.getPositionPercentX();
+ this._positionPercent.y = component.getPositionPercentY();
+ }
+ return this._positionPercent.y;
+ },
+
+ /**
+ * Changes the position type of the widget
+ * @param {Number} type the position type of widget
+ */
+ setPositionType: function (type) {
+ this._positionType = type;
+ if(this._usingLayoutComponent){
+ var component = this._getOrCreateLayoutComponent();
+ if (type === ccui.POSITION_ABSOLUTE){
+ component.setPositionPercentXEnabled(false);
+ component.setPositionPercentYEnabled(false);
+ } else {
+ component.setPositionPercentXEnabled(true);
+ component.setPositionPercentYEnabled(true);
+ }
+ }
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ /**
+ * Gets the position type of the widget
+ * @returns {Number} the position type of widget
+ */
+ getPositionType: function () {
+ return this._positionType;
+ },
+
+ /**
+ * Sets whether the widget should be flipped horizontally or not.
+ * @param {Boolean} flipX true if the widget should be flipped horizontally, false otherwise.
+ */
+ setFlippedX: function (flipX) {
+ var realScale = this.getScaleX();
+ this._flippedX = flipX;
+ this.setScaleX(realScale);
+ },
+
+ /**
+ *
+ * Returns the flag which indicates whether the widget is flipped horizontally or not.
+ * It only flips the texture of the widget, and not the texture of the widget's children.
+ * Also, flipping the texture doesn't alter the anchorPoint.
+ * If you want to flip the anchorPoint too, and/or to flip the children too use:
+ * widget.setScaleX(sprite.getScaleX() * -1);
+ *
+ * @returns {Boolean} true if the widget is flipped horizontally, false otherwise.
+ */
+ isFlippedX: function () {
+ return this._flippedX;
+ },
+
+ /**
+ * Sets whether the widget should be flipped vertically or not.
+ * @param {Boolean} flipY true if the widget should be flipped vertically, false otherwise.
+ */
+ setFlippedY: function (flipY) {
+ var realScale = this.getScaleY();
+ this._flippedY = flipY;
+ this.setScaleY(realScale);
+ },
+
+ /**
+ *
+ * Return the flag which indicates whether the widget is flipped vertically or not.
+ * It only flips the texture of the widget, and not the texture of the widget's children.
+ * Also, flipping the texture doesn't alter the anchorPoint.
+ * If you want to flip the anchorPoint too, and/or to flip the children too use:
+ * widget.setScaleY(widget.getScaleY() * -1);
+ *
+ * @returns {Boolean} true if the widget is flipped vertically, false otherwise.
+ */
+ isFlippedY: function () {
+ return this._flippedY;
+ },
+
+ _adaptRenderers: function () {
+ },
+
+ /**
+ * Determines if the widget is bright
+ * @returns {boolean} true if the widget is bright, false if the widget is dark.
+ */
+ isBright: function () {
+ return this._bright;
+ },
+
+ /**
+ * Determines if the widget is enabled
+ * @returns {boolean}
+ */
+ isEnabled: function () {
+ return this._enabled;
+ },
+
+ /**
+ * Gets the left boundary position of this widget.
+ * @returns {number}
+ */
+ getLeftBoundary: function () {
+ return this.getPositionX() - this._getAnchorX() * this._contentSize.width;
+ },
+
+ /**
+ * Gets the bottom boundary position of this widget.
+ * @returns {number}
+ */
+ getBottomBoundary: function () {
+ return this.getPositionY() - this._getAnchorY() * this._contentSize.height;
+ },
+
+ /**
+ * Gets the right boundary position of this widget.
+ * @returns {number}
+ */
+ getRightBoundary: function () {
+ return this.getLeftBoundary() + this._contentSize.width;
+ },
+
+ /**
+ * Gets the top boundary position of this widget.
+ * @returns {number}
+ */
+ getTopBoundary: function () {
+ return this.getBottomBoundary() + this._contentSize.height;
+ },
+
+ /**
+ * Gets the position of touch began event.
+ * @returns {cc.Point}
+ */
+ getTouchBeganPosition: function () {
+ return cc.p(this._touchBeganPosition);
+ },
+
+ /**
+ * Gets the position of touch moved event
+ * @returns {cc.Point}
+ */
+ getTouchMovePosition: function () {
+ return cc.p(this._touchMovePosition);
+ },
+
+ /**
+ * Gets the position of touch end event
+ * @returns {cc.Point}
+ */
+ getTouchEndPosition: function () {
+ return cc.p(this._touchEndPosition);
+ },
+
+ /**
+ * get widget type
+ * @returns {ccui.Widget.TYPE_WIDGET|ccui.Widget.TYPE_CONTAINER}
+ */
+ getWidgetType: function () {
+ return this._widgetType;
+ },
+
+ /**
+ * Gets LayoutParameter of widget.
+ * @param {ccui.LayoutParameter} parameter
+ */
+ setLayoutParameter: function (parameter) {
+ if (!parameter)
+ return;
+ this._layoutParameterDictionary[parameter.getLayoutType()] = parameter;
+ this._layoutParameterType = parameter.getLayoutType();
+ },
+
+ /**
+ * Gets layout parameter
+ * @param {ccui.LayoutParameter.NONE|ccui.LayoutParameter.LINEAR|ccui.LayoutParameter.RELATIVE} type
+ * @returns {ccui.LayoutParameter}
+ */
+ getLayoutParameter: function (type) {
+ type = type || this._layoutParameterType;
+ return this._layoutParameterDictionary[type];
+ },
+
+ /**
+ * Returns the "class name" of widget.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "Widget";
+ },
+
+ /**
+ * Clones a new widget.
+ * @returns {ccui.Widget}
+ */
+ clone: function () {
+ var clonedWidget = this._createCloneInstance();
+ clonedWidget._copyProperties(this);
+ clonedWidget._copyClonedWidgetChildren(this);
+ return clonedWidget;
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.Widget();
+ },
+
+ _copyClonedWidgetChildren: function (model) {
+ var widgetChildren = model.getChildren();
+ for (var i = 0; i < widgetChildren.length; i++) {
+ var locChild = widgetChildren[i];
+ if (locChild instanceof ccui.Widget)
+ this.addChild(locChild.clone());
+ }
+ },
+
+ _copySpecialProperties: function (model) {
+ },
+
+ _copyProperties: function (widget) {
+ this.setEnabled(widget.isEnabled());
+ this.setVisible(widget.isVisible());
+ this.setBright(widget.isBright());
+ this.setTouchEnabled(widget.isTouchEnabled());
+ this.setLocalZOrder(widget.getLocalZOrder());
+ this.setTag(widget.getTag());
+ this.setName(widget.getName());
+ this.setActionTag(widget.getActionTag());
+
+ this._ignoreSize = widget._ignoreSize;
+
+ this.setContentSize(widget._contentSize);
+ this._customSize.width = widget._customSize.width;
+ this._customSize.height = widget._customSize.height;
+
+ this._copySpecialProperties(widget);
+ this._sizeType = widget.getSizeType();
+ this._sizePercent.x = widget._sizePercent.x;
+ this._sizePercent.y = widget._sizePercent.y;
+
+ this._positionType = widget._positionType;
+ this._positionPercent.x = widget._positionPercent.x;
+ this._positionPercent.y = widget._positionPercent.y;
+
+ this.setPosition(widget.getPosition());
+ this.setAnchorPoint(widget.getAnchorPoint());
+ this.setScaleX(widget.getScaleX());
+ this.setScaleY(widget.getScaleY());
+ this.setRotation(widget.getRotation());
+ this.setRotationX(widget.getRotationX());
+ this.setRotationY(widget.getRotationY());
+ this.setFlippedX(widget.isFlippedX());
+ this.setFlippedY(widget.isFlippedY());
+ this.setColor(widget.getColor());
+ this.setOpacity(widget.getOpacity());
+
+ this._touchEventCallback = widget._touchEventCallback;
+ this._touchEventListener = widget._touchEventListener;
+ this._touchEventSelector = widget._touchEventSelector;
+ this._clickEventListener = widget._clickEventListener;
+ this._focused = widget._focused;
+ this._focusEnabled = widget._focusEnabled;
+ this._propagateTouchEvents = widget._propagateTouchEvents;
+
+ for (var key in widget._layoutParameterDictionary) {
+ var parameter = widget._layoutParameterDictionary[key];
+ if (parameter)
+ this.setLayoutParameter(parameter.clone());
+ }
+ },
+
+ /*temp action*/
+ setActionTag: function (tag) {
+ this._actionTag = tag;
+ },
+
+ getActionTag: function () {
+ return this._actionTag;
+ },
+
+ /**
+ * Gets the left boundary position of this widget.
+ * @deprecated since v3.0, please use getLeftBoundary instead.
+ * @returns {number}
+ */
+ getLeftInParent: function () {
+ cc.log("getLeftInParent is deprecated. Please use getLeftBoundary instead.");
+ return this.getLeftBoundary();
+ },
+
+ /**
+ * Gets the bottom boundary position of this widget.
+ * @deprecated since v3.0, please use getBottomBoundary instead.
+ * @returns {number}
+ */
+ getBottomInParent: function () {
+ cc.log("getBottomInParent is deprecated. Please use getBottomBoundary instead.");
+ return this.getBottomBoundary();
+ },
+
+ /**
+ * Gets the right boundary position of this widget.
+ * @deprecated since v3.0, please use getRightBoundary instead.
+ * @returns {number}
+ */
+ getRightInParent: function () {
+ cc.log("getRightInParent is deprecated. Please use getRightBoundary instead.");
+ return this.getRightBoundary();
+ },
+
+ /**
+ * Gets the top boundary position of this widget.
+ * @deprecated since v3.0, please use getTopBoundary instead.
+ * @returns {number}
+ */
+ getTopInParent: function () {
+ cc.log("getTopInParent is deprecated. Please use getTopBoundary instead.");
+ return this.getTopBoundary();
+ },
+
+ /**
+ * Gets the touch end point of widget when widget is selected.
+ * @deprecated since v3.0, please use getTouchEndPosition instead.
+ * @returns {cc.Point} the touch end point.
+ */
+ getTouchEndPos: function () {
+ cc.log("getTouchEndPos is deprecated. Please use getTouchEndPosition instead.");
+ return this.getTouchEndPosition();
+ },
+
+ /**
+ *Gets the touch move point of widget when widget is selected.
+ * @deprecated since v3.0, please use getTouchMovePosition instead.
+ * @returns {cc.Point} the touch move point.
+ */
+ getTouchMovePos: function () {
+ cc.log("getTouchMovePos is deprecated. Please use getTouchMovePosition instead.");
+ return this.getTouchMovePosition();
+ },
+
+ /**
+ * Checks a point if in parent's area.
+ * @deprecated since v3.0, please use isClippingParentContainsPoint instead.
+ * @param {cc.Point} pt
+ * @returns {Boolean}
+ */
+ clippingParentAreaContainPoint: function (pt) {
+ cc.log("clippingParentAreaContainPoint is deprecated. Please use isClippingParentContainsPoint instead.");
+ this.isClippingParentContainsPoint(pt);
+ },
+
+ /**
+ * Gets the touch began point of widget when widget is selected.
+ * @deprecated since v3.0, please use getTouchBeganPosition instead.
+ * @returns {cc.Point} the touch began point.
+ */
+ getTouchStartPos: function () {
+ cc.log("getTouchStartPos is deprecated. Please use getTouchBeganPosition instead.");
+ return this.getTouchBeganPosition();
+ },
+
+ /**
+ * Changes the size that is widget's size
+ * @deprecated since v3.0, please use setContentSize instead.
+ * @param {cc.Size} size that is widget's size
+ */
+ setSize: function (size) {
+ this.setContentSize(size);
+ },
+
+ /**
+ * Returns size of widget
+ * @deprecated since v3.0, please use getContentSize instead.
+ * @returns {cc.Size}
+ */
+ getSize: function () {
+ return this.getContentSize();
+ },
+
+ /**
+ * Adds a node for widget (this function is deleted in -x)
+ * @param {cc.Node} node
+ * @param {Number} zOrder
+ * @param {Number} tag
+ * @deprecated since v3.0, please use addChild instead.
+ */
+ addNode: function (node, zOrder, tag) {
+ if (node instanceof ccui.Widget) {
+ cc.log("Please use addChild to add a Widget.");
+ return;
+ }
+ cc.Node.prototype.addChild.call(this, node, zOrder, tag);
+ this._nodes.push(node);
+ },
+
+ /**
+ * Gets node by tag
+ * @deprecated since v3.0, please use getChildByTag instead.
+ * @param {Number} tag
+ * @returns {cc.Node}
+ */
+ getNodeByTag: function (tag) {
+ var _nodes = this._nodes;
+ for (var i = 0; i < _nodes.length; i++) {
+ var node = _nodes[i];
+ if (node && node.getTag() === tag) {
+ return node;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Returns all children.
+ * @deprecated since v3.0, please use getChildren instead.
+ * @returns {Array}
+ */
+ getNodes: function () {
+ return this._nodes;
+ },
+
+ /**
+ * Removes a node from ccui.Widget
+ * @deprecated since v3.0, please use removeChild instead.
+ * @param {cc.Node} node
+ * @param {Boolean} cleanup
+ */
+ removeNode: function (node, cleanup) {
+ cc.Node.prototype.removeChild.call(this, node, cleanup);
+ cc.arrayRemoveObject(this._nodes, node);
+ },
+
+ _getNormalGLProgram: function () {
+ return cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
+ },
+
+ _getGrayGLProgram: function () {
+ return cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR_GRAY);
+ },
+
+ /**
+ * Removes node by tag
+ * @deprecated since v3.0, please use removeChildByTag instead.
+ * @param {Number} tag
+ * @param {Boolean} [cleanup]
+ */
+ removeNodeByTag: function (tag, cleanup) {
+ var node = this.getChildByTag(tag);
+ if (!node)
+ cc.log("cocos2d: removeNodeByTag(tag = %d): child not found!", tag);
+ else
+ this.removeChild(node, cleanup);
+ },
+
+ /**
+ * Removes all node
+ * @deprecated since v3.0, please use removeAllChildren instead.
+ */
+ removeAllNodes: function () {
+ for (var i = 0; i < this._nodes.length; i++) {
+ var node = this._nodes[i];
+ cc.Node.prototype.removeChild.call(this, node);
+ }
+ this._nodes.length = 0;
+ },
+
+ _findLayout: function () {
+ cc.renderer.childrenOrderDirty = true;
+ var layout = this._parent;
+ while (layout) {
+ if (layout._doLayout) {
+ layout._doLayoutDirty = true;
+ break;
+ } else
+ layout = layout._parent;
+ }
+ },
+
+ /**
+ * @since v3.2
+ * @returns {boolean} true represent the widget use Unify Size, false represent the widget couldn't use Unify Size
+ */
+ isUnifySizeEnabled: function(){
+ return this._unifySize;
+ },
+
+ /**
+ * @since v3.2
+ * @param {Boolean} enable enable Unify Size of a widget
+ */
+ setUnifySizeEnabled: function(enable){
+ this._unifySize = enable;
+ },
+
+ //v3.3
+ _ccEventCallback: null,
+ /**
+ * Set a event handler to the widget in order to use cocostudio editor and framework
+ * @since v3.3
+ * @param {function} callback
+ */
+ addCCSEventListener: function (callback) {
+ this._ccEventCallback = callback;
+ },
+
+ //override the scale functions.
+ setScaleX: function (scaleX) {
+ if (this._flippedX)
+ scaleX = scaleX * -1;
+ cc.Node.prototype.setScaleX.call(this, scaleX);
+ },
+ setScaleY: function (scaleY) {
+ if (this._flippedY)
+ scaleY = scaleY * -1;
+ cc.Node.prototype.setScaleY.call(this, scaleY);
+ },
+ setScale: function (scaleX, scaleY) {
+ if (scaleY === undefined)
+ scaleY = scaleX;
+ this.setScaleX(scaleX);
+ this.setScaleY(scaleY);
+ },
+
+ getScaleX: function () {
+ var originalScale = cc.Node.prototype.getScaleX.call(this);
+ if (this._flippedX)
+ originalScale = originalScale * -1.0;
+ return originalScale;
+ },
+ getScaleY: function () {
+ var originalScale = cc.Node.prototype.getScaleY.call(this);
+ if (this._flippedY)
+ originalScale = originalScale * -1.0;
+ return originalScale;
+ },
+ getScale: function () {
+ if (this.getScaleX() !== this.getScaleY())
+ cc.log("Widget#scale. ScaleX != ScaleY. Don't know which one to return");
+ return this.getScaleX();
+ },
+
+ /**
+ * Sets callback name to widget.
+ * @since v3.3
+ * @param {String} callbackName
+ */
+ setCallbackName: function (callbackName) {
+ this._callbackName = callbackName;
+ },
+
+ /**
+ * Gets callback name of widget
+ * @since v3.3
+ * @returns {String|Null}
+ */
+ getCallbackName: function () {
+ return this._callbackName;
+ },
+
+ /**
+ * Sets callback type to widget
+ * @since v3.3
+ * @param {String} callbackType
+ */
+ setCallbackType: function (callbackType) {
+ this._callbackType = callbackType;
+ },
+
+ /**
+ * Gets callback type of widget
+ * @since v3.3
+ * @returns {String|null}
+ */
+ getCallbackType: function () {
+ return this._callbackType;
+ },
+
+ /**
+ * Whether enable layout component of a widget
+ * @since v3.3
+ * @param {Boolean} enable enable layout Component of a widget
+ */
+ setLayoutComponentEnabled: function(enable){
+ this._usingLayoutComponent = enable;
+ },
+
+ /**
+ * Returns whether enable layout component of a widget
+ * @return {Boolean} true represent the widget use Layout Component, false represent the widget couldn't use Layout Component.
+ */
+ isLayoutComponentEnabled: function(){
+ return this._usingLayoutComponent;
+ },
+
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new ccui.Widget.WebGLRenderCmd(this);
+ else
+ return new ccui.Widget.CanvasRenderCmd(this);
+ }
+});
+
+var _p = ccui.Widget.prototype;
+
+// Extended properties
+/** @expose */
+_p.xPercent;
+cc.defineGetterSetter(_p, "xPercent", _p._getXPercent, _p._setXPercent);
+/** @expose */
+_p.yPercent;
+cc.defineGetterSetter(_p, "yPercent", _p._getYPercent, _p._setYPercent);
+/** @expose */
+_p.widthPercent;
+cc.defineGetterSetter(_p, "widthPercent", _p._getWidthPercent, _p._setWidthPercent);
+/** @expose */
+_p.heightPercent;
+cc.defineGetterSetter(_p, "heightPercent", _p._getHeightPercent, _p._setHeightPercent);
+/** @expose */
+_p.widgetParent;
+cc.defineGetterSetter(_p, "widgetParent", _p.getWidgetParent);
+/** @expose */
+_p.enabled;
+cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled);
+/** @expose */
+_p.focused;
+cc.defineGetterSetter(_p, "focused", _p.isFocused, _p.setFocused);
+/** @expose */
+_p.sizeType;
+cc.defineGetterSetter(_p, "sizeType", _p.getSizeType, _p.setSizeType);
+/** @expose */
+_p.widgetType;
+cc.defineGetterSetter(_p, "widgetType", _p.getWidgetType);
+/** @expose */
+_p.touchEnabled;
+cc.defineGetterSetter(_p, "touchEnabled", _p.isTouchEnabled, _p.setTouchEnabled);
+/** @expose */
+_p.updateEnabled;
+cc.defineGetterSetter(_p, "updateEnabled", _p.isUpdateEnabled, _p.setUpdateEnabled);
+/** @expose */
+_p.bright;
+cc.defineGetterSetter(_p, "bright", _p.isBright, _p.setBright);
+/** @expose */
+_p.name;
+cc.defineGetterSetter(_p, "name", _p.getName, _p.setName);
+/** @expose */
+_p.actionTag;
+cc.defineGetterSetter(_p, "actionTag", _p.getActionTag, _p.setActionTag);
+/** @expose */
+_p.opacity;
+cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
+
+_p = null;
+
+/**
+ * allocates and initializes a UIWidget.
+ * @deprecated
+ * @return {ccui.Widget}
+ */
+ccui.Widget.create = function () {
+ return new ccui.Widget();
+};
+
+ccui.Widget._focusedWidget = null; //both layout & widget will be stored in this variable
+ccui.Widget._focusNavigationController = null;
+
+/**
+ * call this method with parameter true to enable the Android Dpad focus navigation feature
+ * @note it doesn't implemented on Web
+ * @param {Boolean} enable set true to enable dpad focus navigation, otherwise disable dpad focus navigation
+ */
+ccui.Widget.enableDpadNavigation = function (enable) {
+ if (enable) {
+ if (null == ccui.Widget._focusNavigationController) {
+ ccui.Widget._focusNavigationController = new ccui._FocusNavigationController();
+ if (ccui.Widget._focusedWidget) {
+ ccui.Widget._focusNavigationController._setFirstFocsuedWidget(ccui.Widget._focusedWidget);
+ }
+ }
+ ccui.Widget._focusNavigationController.enableFocusNavigation(true);
+ } else {
+ if (ccui.Widget._focusNavigationController) {
+ ccui.Widget._focusNavigationController.enableFocusNavigation(false);
+ ccui.Widget._focusNavigationController = null;
+ }
+ }
+};
+
+/**
+ * Gets the focused widget of current stage.
+ * @function
+ * @returns {null|ccui.Widget}
+ */
+ccui.Widget.getCurrentFocusedWidget = function () {
+ return ccui.Widget._focusedWidget;
+};
+
+// Constants
+//bright style
+/**
+ * None bright style of ccui.Widget.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.BRIGHT_STYLE_NONE = -1;
+/**
+ * Normal bright style of ccui.Widget.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.BRIGHT_STYLE_NORMAL = 0;
+/**
+ * Light bright style of ccui.Widget.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.BRIGHT_STYLE_HIGH_LIGHT = 1;
+
+//widget type
+/**
+ * The type code of Widget for ccui controls.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.TYPE_WIDGET = 0;
+/**
+ * The type code of Container for ccui controls.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.TYPE_CONTAINER = 1;
+
+//Focus Direction
+/**
+ * The left of Focus direction for ccui.Widget
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.LEFT = 0;
+/**
+ * The right of Focus direction for ccui.Widget
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.RIGHT = 1;
+/**
+ * The up of Focus direction for ccui.Widget
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.UP = 2;
+/**
+ * The down of Focus direction for ccui.Widget
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.DOWN = 3;
+
+//texture resource type
+/**
+ * The image file texture type of ccui.Widget loads.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.LOCAL_TEXTURE = 0;
+/**
+ * The sprite frame texture type of ccui.Widget loads.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.PLIST_TEXTURE = 1;
+
+//touch event type
+/**
+ * The touch began type of ccui.Widget's touch event
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.TOUCH_BEGAN = 0;
+/**
+ * The touch moved type of ccui.Widget's touch event
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.TOUCH_MOVED = 1;
+/**
+ * The touch end type of ccui.Widget's touch event
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.TOUCH_ENDED = 2;
+/**
+ * The touch canceled type of ccui.Widget's touch event
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.TOUCH_CANCELED = 3;
+
+//size type
+/**
+ * The absolute of ccui.Widget's size type.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.SIZE_ABSOLUTE = 0;
+/**
+ * The percent of ccui.Widget's size type.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.SIZE_PERCENT = 1;
+
+//position type
+/**
+ * The absolute of ccui.Widget's position type.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.POSITION_ABSOLUTE = 0;
+/**
+ * The percent of ccui.Widget's position type.
+ * @constant
+ * @type {number}
+ */
+ccui.Widget.POSITION_PERCENT = 1;
diff --git a/extensions/ccui/base-classes/UIWidgetRenderCmd.js b/extensions/ccui/base-classes/UIWidgetRenderCmd.js
new file mode 100644
index 0000000000..fca76f9735
--- /dev/null
+++ b/extensions/ccui/base-classes/UIWidgetRenderCmd.js
@@ -0,0 +1,126 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+ ccui.Widget.CanvasRenderCmd = function (renderable) {
+ this._pNodeCmdCtor(renderable);
+ this._needDraw = false;
+ };
+
+ var proto = ccui.Widget.CanvasRenderCmd.prototype = Object.create(cc.ProtectedNode.CanvasRenderCmd.prototype);
+ proto.constructor = ccui.Widget.CanvasRenderCmd;
+
+ proto.visit = function (parentCmd) {
+ var node = this._node, renderer = cc.renderer;
+
+ parentCmd = parentCmd || this.getParentRenderCmd();
+ if (parentCmd)
+ this._curLevel = parentCmd._curLevel + 1;
+
+ if (isNaN(node._customZ)) {
+ node._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+
+ node._adaptRenderers();
+ this._syncStatus(parentCmd);
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ if (!this._transform) {
+ this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ }
+
+ var node = this._node;
+ if (node._visible && node._running) {
+ node._adaptRenderers();
+ if(!this._usingLayoutComponent){
+ var widgetParent = node.getWidgetParent();
+ if (widgetParent) {
+ var parentSize = widgetParent.getContentSize();
+ if (parentSize.width !== 0 && parentSize.height !== 0) {
+ node._position.x = parentSize.width * node._positionPercent.x;
+ node._position.y = parentSize.height * node._positionPercent.y;
+ }
+ }
+ }
+ this.pNodeTransform(parentCmd, recursive);
+ }
+ };
+
+ proto.widgetTransform = proto.transform;
+ } else {
+ ccui.Widget.WebGLRenderCmd = function (renderable) {
+ this._pNodeCmdCtor(renderable);
+ this._needDraw = false;
+ };
+
+ var proto = ccui.Widget.WebGLRenderCmd.prototype = Object.create(cc.ProtectedNode.WebGLRenderCmd.prototype);
+ proto.constructor = ccui.Widget.WebGLRenderCmd;
+
+ proto.visit = function (parentCmd) {
+ var node = this._node, renderer = cc.renderer;
+
+ parentCmd = parentCmd || this.getParentRenderCmd();
+ if (parentCmd)
+ this._curLevel = parentCmd._curLevel + 1;
+
+ if (isNaN(node._customZ)) {
+ node._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+
+ node._adaptRenderers();
+ this._syncStatus(parentCmd);
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ if (!this._transform) {
+ this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ }
+
+ var node = this._node;
+ if (node._visible && node._running) {
+ node._adaptRenderers();
+
+ if(!this._usingLayoutComponent) {
+ var widgetParent = node.getWidgetParent();
+ if (widgetParent) {
+ var parentSize = widgetParent.getContentSize();
+ if (parentSize.width !== 0 && parentSize.height !== 0) {
+ node._position.x = parentSize.width * node._positionPercent.x;
+ node._position.y = parentSize.height * node._positionPercent.y;
+ }
+ }
+ }
+ this.pNodeTransform(parentCmd, recursive);
+ }
+ };
+
+ proto.widgetTransform = proto.transform;
+ }
+});
diff --git a/extensions/CocoStudio/GUI/BaseClasses/UIRootWidget.js b/extensions/ccui/layouts/UIHBox.js
similarity index 63%
rename from extensions/CocoStudio/GUI/BaseClasses/UIRootWidget.js
rename to extensions/ccui/layouts/UIHBox.js
index 624eeff863..f808668c22 100644
--- a/extensions/CocoStudio/GUI/BaseClasses/UIRootWidget.js
+++ b/extensions/ccui/layouts/UIHBox.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -23,36 +24,32 @@
****************************************************************************/
/**
- * Base class for cc.UIRootWidget
+ * The horizontal box of Cocos UI. Its layout type is ccui.Layout.LINEAR_HORIZONTAL.
* @class
- * @extends cc.Layout
+ * @extends ccui.Layout
*/
-cc.UIRootWidget = cc.Layout.extend({
+ccui.HBox = ccui.Layout.extend(/** @lends ccui.HBox# */{
/**
- * initializes state of widget.
- * @returns {boolean}
+ * The constructor of ccui.HBox
+ * @function
+ * @param {cc.Size} [size]
*/
- init: function () {
- if (cc.Layout.prototype.init.call(this)) {
- this.setSize(cc.Director.getInstance().getWinSize());
- return true;
- }
- return false;
- },
+ ctor: function(size){
+ ccui.Layout.prototype.ctor.call(this);
+ this.setLayoutType(ccui.Layout.LINEAR_HORIZONTAL);
- /**
- * Returns the "class name" of widget.
- * @returns {string}
- */
- getDescription: function () {
- return "RootWidget";
+ if(size) {
+ this.setContentSize(size);
+ }
}
});
-cc.UIRootWidget.create = function () {
- var widget = new cc.UIRootWidget();
- if (widget && widget.init()) {
- return widget;
- }
- return null;
+/**
+ * Creates a HBox object
+ * @deprecated since v3.0, please use new ccui.HBox(size) instead.
+ * @param {cc.Size} size
+ * @returns {ccui.HBox}
+ */
+ccui.HBox.create = function(size){
+ return new ccui.HBox(size);
};
\ No newline at end of file
diff --git a/extensions/ccui/layouts/UILayout.js b/extensions/ccui/layouts/UILayout.js
new file mode 100644
index 0000000000..34361aa8a9
--- /dev/null
+++ b/extensions/ccui/layouts/UILayout.js
@@ -0,0 +1,1571 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * ccui.Layout is the base class of ccui.PageView and ccui.ScrollView, it does layout by layout manager
+ * and clips area by its _clippingStencil when clippingEnabled is true.
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {Boolean} clippingEnabled - Indicate whether clipping is enabled
+ * @property {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR} clippingType
+ * @property {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE} layoutType
+ *
+ */
+ccui.Layout = ccui.Widget.extend(/** @lends ccui.Layout# */{
+ _clippingEnabled: false,
+ _backGroundScale9Enabled: null,
+ _backGroundImage: null,
+ _backGroundImageFileName: null,
+ _backGroundImageCapInsets: null,
+ _colorType: null,
+ _bgImageTexType: ccui.Widget.LOCAL_TEXTURE,
+ _colorRender: null,
+ _gradientRender: null,
+ _color: null,
+ _startColor: null,
+ _endColor: null,
+ _alongVector: null,
+ _opacity: 255,
+ _backGroundImageTextureSize: null,
+ _layoutType: null,
+ _doLayoutDirty: true,
+ _clippingRectDirty: true,
+ _clippingType: null,
+ _clippingStencil: null,
+ _scissorRectDirty: false,
+ _clippingRect: null,
+ _clippingParent: null,
+ _className: "Layout",
+ _backGroundImageColor: null,
+ _finalPositionX: 0,
+ _finalPositionY: 0,
+
+ _backGroundImageOpacity: 0,
+
+ _loopFocus: false, //whether enable loop focus or not
+ __passFocusToChild: true, //on default, it will pass the focus to the next nearest widget
+ _isFocusPassing: false, //when finding the next focused widget, use this variable to pass focus between layout & widget
+ _isInterceptTouch: false,
+
+ /**
+ * Allocates and initializes an UILayout.
+ * Constructor of ccui.Layout
+ * @function
+ * @example
+ * // example
+ * var uiLayout = new ccui.Layout();
+ */
+ ctor: function () {
+ this._layoutType = ccui.Layout.ABSOLUTE;
+ this._widgetType = ccui.Widget.TYPE_CONTAINER;
+ this._clippingType = ccui.Layout.CLIPPING_SCISSOR;
+ this._colorType = ccui.Layout.BG_COLOR_NONE;
+
+ ccui.Widget.prototype.ctor.call(this);
+
+ this.ignoreContentAdaptWithSize(false);
+ this.setContentSize(cc.size(0, 0));
+ this.setAnchorPoint(0, 0);
+ this.onPassFocusToChild = this._findNearestChildWidgetIndex.bind(this);
+
+ this._backGroundImageCapInsets = cc.rect(0, 0, 0, 0);
+
+ this._color = cc.color(255, 255, 255, 255);
+ this._startColor = cc.color(255, 255, 255, 255);
+ this._endColor = cc.color(255, 255, 255, 255);
+ this._alongVector = cc.p(0, -1);
+ this._backGroundImageTextureSize = cc.size(0, 0);
+
+ this._clippingRect = cc.rect(0, 0, 0, 0);
+ this._backGroundImageColor = cc.color(255, 255, 255, 255);
+ },
+
+ /**
+ * Calls its parent's onEnter, and calls its clippingStencil's onEnter if clippingStencil isn't null.
+ * @override
+ */
+ onEnter: function () {
+ ccui.Widget.prototype.onEnter.call(this);
+ if (this._clippingStencil)
+ this._clippingStencil._performRecursive(cc.Node._stateCallbackType.onEnter);
+ this._doLayoutDirty = true;
+ this._clippingRectDirty = true;
+ },
+
+ /**
+ * Calls its parent's onExit, and calls its clippingStencil's onExit if clippingStencil isn't null.
+ * @override
+ */
+ onExit: function () {
+ ccui.Widget.prototype.onExit.call(this);
+ if (this._clippingStencil)
+ this._clippingStencil._performRecursive(cc.Node._stateCallbackType.onExit);
+ },
+
+ /**
+ *
+ * Calls adaptRenderers (its subclass will override it.) and do layout.
+ * If clippingEnabled is true, it will clip/scissor area.
+ *
+ * @override
+ * @param {cc.Node} [parent]
+ */
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ this._adaptRenderers();
+ this._doLayout();
+
+ var renderer = cc.renderer;
+ cmd.visit(parentCmd);
+
+ var stencilClipping = this._clippingEnabled && this._clippingType === ccui.Layout.CLIPPING_STENCIL;
+ var scissorClipping = this._clippingEnabled && this._clippingType === ccui.Layout.CLIPPING_SCISSOR;
+
+ if (stencilClipping) {
+ cmd.stencilClippingVisit(parentCmd);
+ }
+ else if (scissorClipping) {
+ cmd.scissorClippingVisit(parentCmd);
+ }
+
+ var i, children = this._children, len = children.length, child;
+ var j, pChildren = this._protectedChildren, pLen = pChildren.length, pChild;
+
+ if (this._reorderChildDirty) this.sortAllChildren();
+ if (this._reorderProtectedChildDirty) this.sortAllProtectedChildren();
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0) {
+ child.visit(this);
+ }
+ else break;
+ }
+ for (j = 0; j < pLen; j++) {
+ pChild = pChildren[j];
+ if (pChild._localZOrder < 0) {
+ cmd._changeProtectedChild(pChild);
+ pChild.visit(this);
+ }
+ else break;
+ }
+ // draw children zOrder >= 0
+ for (; i < len; i++) {
+ children[i].visit(this);
+ }
+ for (; j < pLen; j++) {
+ pChild = pChildren[j];
+ cmd._changeProtectedChild(pChild);
+ pChild.visit(this);
+ }
+
+ if (stencilClipping) {
+ cmd.postStencilVisit();
+ }
+ else if (scissorClipping) {
+ cmd.postScissorVisit();
+ }
+
+ cmd._dirtyFlag = 0;
+ },
+
+ /**
+ * If a layout is loop focused which means that the focus movement will be inside the layout
+ * @param {Boolean} loop pass true to let the focus movement loop inside the layout
+ */
+ setLoopFocus: function (loop) {
+ this._loopFocus = loop;
+ },
+
+ /**
+ * Gets whether enable focus loop
+ * @returns {boolean} If focus loop is enabled, then it will return true, otherwise it returns false. The default value is false.
+ */
+ isLoopFocus: function () {
+ return this._loopFocus;
+ },
+
+ /**
+ * Specifies whether the layout pass its focus to its child
+ * @param pass To specify whether the layout pass its focus to its child
+ */
+ setPassFocusToChild: function (pass) {
+ this.__passFocusToChild = pass;
+ },
+
+ /**
+ * Returns whether the layout will pass the focus to its children or not. The default value is true
+ * @returns {boolean} To query whether the layout will pass the focus to its children or not. The default value is true
+ */
+ isPassFocusToChild: function () {
+ return this.__passFocusToChild;
+ },
+
+ /**
+ * When a widget is in a layout, you could call this method to get the next focused widget within a specified direction.
+ * If the widget is not in a layout, it will return itself
+ * @param {Number} direction the direction to look for the next focused widget in a layout
+ * @param {ccui.Widget} current the current focused widget
+ * @returns {ccui.Widget} return the index of widget in the layout
+ */
+ findNextFocusedWidget: function (direction, current) {
+ if (this._isFocusPassing || this.isFocused()) {
+ var parent = this.getParent();
+ this._isFocusPassing = false;
+ if (this.__passFocusToChild) {
+ var w = this._passFocusToChild(direction, current);
+ if (w instanceof ccui.Layout && parent) {
+ parent._isFocusPassing = true;
+ return parent.findNextFocusedWidget(direction, this);
+ }
+ return w;
+ }
+
+ if (null == parent || !(parent instanceof ccui.Layout))
+ return this;
+ parent._isFocusPassing = true;
+ return parent.findNextFocusedWidget(direction, this);
+ } else if (current.isFocused() || current instanceof ccui.Layout) {
+ if (this._layoutType === ccui.Layout.LINEAR_HORIZONTAL) {
+ switch (direction) {
+ case ccui.Widget.LEFT:
+ return this._getPreviousFocusedWidget(direction, current);
+ break;
+ case ccui.Widget.RIGHT:
+ return this._getNextFocusedWidget(direction, current);
+ break;
+ case ccui.Widget.DOWN:
+ case ccui.Widget.UP:
+ if (this._isLastWidgetInContainer(this, direction)) {
+ if (this._isWidgetAncestorSupportLoopFocus(current, direction))
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ return current;
+ } else {
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ }
+ break;
+ default:
+ cc.assert(0, "Invalid Focus Direction");
+ return current;
+ }
+ } else if (this._layoutType === ccui.Layout.LINEAR_VERTICAL) {
+ switch (direction) {
+ case ccui.Widget.LEFT:
+ case ccui.Widget.RIGHT:
+ if (this._isLastWidgetInContainer(this, direction)) {
+ if (this._isWidgetAncestorSupportLoopFocus(current, direction))
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ return current;
+ }
+ else
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ break;
+ case ccui.Widget.DOWN:
+ return this._getNextFocusedWidget(direction, current);
+ break;
+ case ccui.Widget.UP:
+ return this._getPreviousFocusedWidget(direction, current);
+ break;
+ default:
+ cc.assert(0, "Invalid Focus Direction");
+ return current;
+ }
+ } else {
+ cc.assert(0, "Un Supported Layout type, please use VBox and HBox instead!!!");
+ return current;
+ }
+ } else
+ return current;
+ },
+
+ /**
+ * To specify a user-defined functor to decide which child widget of the layout should get focused
+ * @function
+ * @param {Number} direction
+ * @param {ccui.Widget} current
+ */
+ onPassFocusToChild: null,
+
+ /**
+ * Adds a widget to the container.
+ * @param {ccui.Widget} widget
+ * @param {Number} [zOrder]
+ * @param {Number|string} [tag] tag or name
+ * @override
+ */
+ addChild: function (widget, zOrder, tag) {
+ if ((widget instanceof ccui.Widget)) {
+ this._supplyTheLayoutParameterLackToChild(widget);
+ }
+ ccui.Widget.prototype.addChild.call(this, widget, zOrder, tag);
+ this._doLayoutDirty = true;
+ },
+
+ /**
+ * Removes child widget from ccui.Layout, and sets the layout dirty flag to true.
+ * @param {ccui.Widget} widget
+ * @param {Boolean} [cleanup=true]
+ * @override
+ */
+ removeChild: function (widget, cleanup) {
+ ccui.Widget.prototype.removeChild.call(this, widget, cleanup);
+ this._doLayoutDirty = true;
+ },
+
+ /**
+ * Removes all children from the container with a cleanup, and sets the layout dirty flag to true.
+ * @param {Boolean} cleanup
+ */
+ removeAllChildren: function (cleanup) {
+ ccui.Widget.prototype.removeAllChildren.call(this, cleanup);
+ this._doLayoutDirty = true;
+ },
+
+ /**
+ * Removes all children from the container, do a cleanup to all running actions depending on the cleanup parameter,
+ * and sets the layout dirty flag to true.
+ * @param {Boolean} cleanup true if all running actions on all children nodes should be cleanup, false otherwise.
+ */
+ removeAllChildrenWithCleanup: function (cleanup) {
+ ccui.Widget.prototype.removeAllChildrenWithCleanup.call(this, cleanup);
+ this._doLayoutDirty = true;
+ },
+
+ /**
+ * Gets if layout is clipping enabled.
+ * @returns {Boolean} if layout is clipping enabled.
+ */
+ isClippingEnabled: function () {
+ return this._clippingEnabled;
+ },
+
+ /**
+ * Changes if layout can clip it's content and locChild.
+ * If you really need this, please enable it. But it would reduce the rendering efficiency.
+ * @param {Boolean} able clipping enabled.
+ */
+ setClippingEnabled: function (able) {
+ if (able === this._clippingEnabled)
+ return;
+ this._clippingEnabled = able;
+ switch (this._clippingType) {
+ case ccui.Layout.CLIPPING_SCISSOR:
+ case ccui.Layout.CLIPPING_STENCIL:
+ if (able) {
+ this._clippingStencil = new cc.DrawNode();
+ this._renderCmd.rebindStencilRendering(this._clippingStencil);
+ if (this._running)
+ this._clippingStencil._performRecursive(cc.Node._stateCallbackType.onEnter);
+ this._setStencilClippingSize(this._contentSize);
+ } else {
+ if (this._running && this._clippingStencil)
+ this._clippingStencil._performRecursive(cc.Node._stateCallbackType.onExit);
+ this._clippingStencil = null;
+ }
+ break;
+ default:
+ break;
+ }
+ },
+
+ /**
+ * Sets clipping type to ccui.Layout
+ * @param {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR} type
+ */
+ setClippingType: function (type) {
+ if (type === this._clippingType)
+ return;
+ var clippingEnabled = this.isClippingEnabled();
+ this.setClippingEnabled(false);
+ this._clippingType = type;
+ this.setClippingEnabled(clippingEnabled);
+ },
+
+ /**
+ * Gets clipping type of ccui.Layout
+ * @returns {ccui.Layout.CLIPPING_STENCIL|ccui.Layout.CLIPPING_SCISSOR}
+ */
+ getClippingType: function () {
+ return this._clippingType;
+ },
+
+ _setStencilClippingSize: function (size) {
+ if (this._clippingEnabled) {
+ var rect = [];
+ rect[0] = cc.p(0, 0);
+ rect[1] = cc.p(size.width, 0);
+ rect[2] = cc.p(size.width, size.height);
+ rect[3] = cc.p(0, size.height);
+ var green = cc.color.GREEN;
+ this._clippingStencil.clear();
+ this._clippingStencil.setLocalBB && this._clippingStencil.setLocalBB(0, 0, size.width, size.height);
+ this._clippingStencil.drawPoly(rect, 4, green, 0, green);
+ }
+ },
+
+ _getClippingRect: function () {
+ if (this._clippingRectDirty) {
+ var worldPos = this.convertToWorldSpace(cc.p(0, 0));
+ var t = this.getNodeToWorldTransform();
+ var scissorWidth = this._contentSize.width * t.a;
+ var scissorHeight = this._contentSize.height * t.d;
+ var parentClippingRect;
+ var parent = this;
+
+ while (parent) {
+ parent = parent.getParent();
+ if (parent && parent instanceof ccui.Layout && parent.isClippingEnabled()) {
+ this._clippingParent = parent;
+ break;
+ }
+ }
+
+ if (this._clippingParent) {
+ parentClippingRect = this._clippingParent._getClippingRect();
+
+ this._clippingRect.x = Math.max(worldPos.x, parentClippingRect.x);
+ this._clippingRect.y = Math.max(worldPos.y, parentClippingRect.y);
+
+ var right = Math.min(worldPos.x + scissorWidth, parentClippingRect.x + parentClippingRect.width);
+ var top = Math.min(worldPos.y + scissorHeight, parentClippingRect.y + parentClippingRect.height);
+
+ this._clippingRect.width = Math.max(0.0, right - this._clippingRect.x);
+ this._clippingRect.height = Math.max(0.0, top - this._clippingRect.y);
+ } else {
+ this._clippingRect.x = worldPos.x;
+ this._clippingRect.y = worldPos.y;
+ this._clippingRect.width = scissorWidth;
+ this._clippingRect.height = scissorHeight;
+ }
+ this._clippingRectDirty = false;
+ }
+ return this._clippingRect;
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ var locContentSize = this._contentSize;
+ this._setStencilClippingSize(locContentSize);
+ this._doLayoutDirty = true;
+ this._clippingRectDirty = true;
+ if (this._backGroundImage) {
+ this._backGroundImage.setPosition(locContentSize.width * 0.5, locContentSize.height * 0.5);
+ if (this._backGroundScale9Enabled && this._backGroundImage instanceof ccui.Scale9Sprite)
+ this._backGroundImage.setPreferredSize(locContentSize);
+ }
+ if (this._colorRender)
+ this._colorRender.setContentSize(locContentSize);
+ if (this._gradientRender)
+ this._gradientRender.setContentSize(locContentSize);
+ },
+
+ /**
+ * Sets background image use scale9 renderer.
+ * @param {Boolean} able true that use scale9 renderer, false otherwise.
+ */
+ setBackGroundImageScale9Enabled: function (able) {
+ if (this._backGroundScale9Enabled === able)
+ return;
+ this.removeProtectedChild(this._backGroundImage);
+ this._backGroundImage = null;
+ this._backGroundScale9Enabled = able;
+ this._addBackGroundImage();
+ this.setBackGroundImage(this._backGroundImageFileName, this._bgImageTexType);
+ this.setBackGroundImageCapInsets(this._backGroundImageCapInsets);
+ },
+
+ /**
+ * Get whether background image is use scale9 renderer.
+ * @returns {Boolean}
+ */
+ isBackGroundImageScale9Enabled: function () {
+ return this._backGroundScale9Enabled;
+ },
+
+ /**
+ * Sets a background image for layout
+ * @param {String} fileName
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ setBackGroundImage: function (fileName, texType) {
+ if (!fileName)
+ return;
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ if (this._backGroundImage === null) {
+ this._addBackGroundImage();
+ this.setBackGroundImageScale9Enabled(this._backGroundScale9Enabled);
+ }
+ this._backGroundImageFileName = fileName;
+ this._bgImageTexType = texType;
+ var locBackgroundImage = this._backGroundImage;
+ switch (this._bgImageTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ locBackgroundImage.initWithFile(fileName);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ locBackgroundImage.initWithSpriteFrameName(fileName);
+ break;
+ default:
+ break;
+ }
+ if (this._backGroundScale9Enabled)
+ locBackgroundImage.setPreferredSize(this._contentSize);
+
+ this._backGroundImageTextureSize = locBackgroundImage.getContentSize();
+ locBackgroundImage.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
+ this._updateBackGroundImageColor();
+ },
+
+ /**
+ * Sets a background image CapInsets for layout, if the background image is a scale9 render.
+ * @param {cc.Rect} capInsets capinsets of background image.
+ */
+ setBackGroundImageCapInsets: function (capInsets) {
+ if (!capInsets)
+ return;
+ var locInsets = this._backGroundImageCapInsets;
+ locInsets.x = capInsets.x;
+ locInsets.y = capInsets.y;
+ locInsets.width = capInsets.width;
+ locInsets.height = capInsets.height;
+ if (this._backGroundScale9Enabled)
+ this._backGroundImage.setCapInsets(capInsets);
+ },
+
+ /**
+ * Gets background image capinsets of ccui.Layout.
+ * @returns {cc.Rect}
+ */
+ getBackGroundImageCapInsets: function () {
+ return cc.rect(this._backGroundImageCapInsets);
+ },
+
+ _supplyTheLayoutParameterLackToChild: function (locChild) {
+ if (!locChild) {
+ return;
+ }
+ switch (this._layoutType) {
+ case ccui.Layout.ABSOLUTE:
+ break;
+ case ccui.Layout.LINEAR_HORIZONTAL:
+ case ccui.Layout.LINEAR_VERTICAL:
+ var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.LINEAR);
+ if (!layoutParameter)
+ locChild.setLayoutParameter(new ccui.LinearLayoutParameter());
+ break;
+ case ccui.Layout.RELATIVE:
+ var layoutParameter = locChild.getLayoutParameter(ccui.LayoutParameter.RELATIVE);
+ if (!layoutParameter)
+ locChild.setLayoutParameter(new ccui.RelativeLayoutParameter());
+ break;
+ default:
+ break;
+ }
+ },
+
+ _addBackGroundImage: function () {
+ var contentSize = this._contentSize;
+ if (this._backGroundScale9Enabled) {
+ this._backGroundImage = new ccui.Scale9Sprite();
+ this._backGroundImage.setPreferredSize(contentSize);
+ } else
+ this._backGroundImage = new cc.Sprite();
+ this.addProtectedChild(this._backGroundImage, ccui.Layout.BACKGROUND_IMAGE_ZORDER, -1);
+ this._backGroundImage.setPosition(contentSize.width * 0.5, contentSize.height * 0.5);
+ },
+
+ /**
+ * Remove the background image of ccui.Layout.
+ */
+ removeBackGroundImage: function () {
+ if (!this._backGroundImage)
+ return;
+ this.removeProtectedChild(this._backGroundImage);
+ this._backGroundImage = null;
+ this._backGroundImageFileName = "";
+ this._backGroundImageTextureSize.width = 0;
+ this._backGroundImageTextureSize.height = 0;
+ },
+
+ /**
+ * Sets Color Type for ccui.Layout.
+ * @param {ccui.Layout.BG_COLOR_NONE|ccui.Layout.BG_COLOR_SOLID|ccui.Layout.BG_COLOR_GRADIENT} type
+ */
+ setBackGroundColorType: function (type) {
+ if (this._colorType === type)
+ return;
+ switch (this._colorType) {
+ case ccui.Layout.BG_COLOR_NONE:
+ if (this._colorRender) {
+ this.removeProtectedChild(this._colorRender);
+ this._colorRender = null;
+ }
+ if (this._gradientRender) {
+ this.removeProtectedChild(this._gradientRender);
+ this._gradientRender = null;
+ }
+ break;
+ case ccui.Layout.BG_COLOR_SOLID:
+ if (this._colorRender) {
+ this.removeProtectedChild(this._colorRender);
+ this._colorRender = null;
+ }
+ break;
+ case ccui.Layout.BG_COLOR_GRADIENT:
+ if (this._gradientRender) {
+ this.removeProtectedChild(this._gradientRender);
+ this._gradientRender = null;
+ }
+ break;
+ default:
+ break;
+ }
+ this._colorType = type;
+ switch (this._colorType) {
+ case ccui.Layout.BG_COLOR_NONE:
+ break;
+ case ccui.Layout.BG_COLOR_SOLID:
+ this._colorRender = new cc.LayerColor();
+ this._colorRender.setContentSize(this._contentSize);
+ this._colorRender.setOpacity(this._opacity);
+ this._colorRender.setColor(this._color);
+ this.addProtectedChild(this._colorRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1);
+ break;
+ case ccui.Layout.BG_COLOR_GRADIENT:
+ this._gradientRender = new cc.LayerGradient(cc.color(255, 0, 0, 255), cc.color(0, 255, 0, 255));
+ this._gradientRender.setContentSize(this._contentSize);
+ this._gradientRender.setOpacity(this._opacity);
+ this._gradientRender.setStartColor(this._startColor);
+ this._gradientRender.setEndColor(this._endColor);
+ this._gradientRender.setVector(this._alongVector);
+ this.addProtectedChild(this._gradientRender, ccui.Layout.BACKGROUND_RENDERER_ZORDER, -1);
+ break;
+ default:
+ break;
+ }
+ },
+
+ /**
+ * Get background color type of ccui.Layout.
+ * @returns {ccui.Layout.BG_COLOR_NONE|ccui.Layout.BG_COLOR_SOLID|ccui.Layout.BG_COLOR_GRADIENT}
+ */
+ getBackGroundColorType: function () {
+ return this._colorType;
+ },
+
+ /**
+ * Sets background color for layout, if color type is Layout.COLOR_SOLID
+ * @param {cc.Color} color
+ * @param {cc.Color} [endColor]
+ */
+ setBackGroundColor: function (color, endColor) {
+ if (!endColor) {
+ this._color.r = color.r;
+ this._color.g = color.g;
+ this._color.b = color.b;
+ if (this._colorRender)
+ this._colorRender.setColor(color);
+ } else {
+ this._startColor.r = color.r;
+ this._startColor.g = color.g;
+ this._startColor.b = color.b;
+ if (this._gradientRender)
+ this._gradientRender.setStartColor(color);
+
+ this._endColor.r = endColor.r;
+ this._endColor.g = endColor.g;
+ this._endColor.b = endColor.b;
+ if (this._gradientRender)
+ this._gradientRender.setEndColor(endColor);
+ }
+ },
+
+ /**
+ * Gets background color of ccui.Layout, if color type is Layout.COLOR_SOLID.
+ * @returns {cc.Color}
+ */
+ getBackGroundColor: function () {
+ var tmpColor = this._color;
+ return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
+ },
+
+ /**
+ * Gets background start color of ccui.Layout
+ * @returns {cc.Color}
+ */
+ getBackGroundStartColor: function () {
+ var tmpColor = this._startColor;
+ return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
+ },
+
+ /**
+ * Gets background end color of ccui.Layout
+ * @returns {cc.Color}
+ */
+ getBackGroundEndColor: function () {
+ var tmpColor = this._endColor;
+ return cc.color(tmpColor.r, tmpColor.g, tmpColor.b, tmpColor.a);
+ },
+
+ /**
+ * Sets background opacity to ccui.Layout.
+ * @param {number} opacity
+ */
+ setBackGroundColorOpacity: function (opacity) {
+ this._opacity = opacity;
+ switch (this._colorType) {
+ case ccui.Layout.BG_COLOR_NONE:
+ break;
+ case ccui.Layout.BG_COLOR_SOLID:
+ this._colorRender.setOpacity(opacity);
+ break;
+ case ccui.Layout.BG_COLOR_GRADIENT:
+ this._gradientRender.setOpacity(opacity);
+ break;
+ default:
+ break;
+ }
+ },
+
+ /**
+ * Get background opacity value of ccui.Layout.
+ * @returns {Number}
+ */
+ getBackGroundColorOpacity: function () {
+ return this._opacity;
+ },
+
+ /**
+ * Sets background color vector for layout, if color type is Layout.COLOR_GRADIENT
+ * @param {cc.Point} vector
+ */
+ setBackGroundColorVector: function (vector) {
+ this._alongVector.x = vector.x;
+ this._alongVector.y = vector.y;
+ if (this._gradientRender) {
+ this._gradientRender.setVector(vector);
+ }
+ },
+
+ /**
+ * Gets background color vector of ccui.Layout, if color type is Layout.COLOR_GRADIENT
+ * @returns {cc.Point}
+ */
+ getBackGroundColorVector: function () {
+ return this._alongVector;
+ },
+
+ /**
+ * Sets backGround image color
+ * @param {cc.Color} color
+ */
+ setBackGroundImageColor: function (color) {
+ this._backGroundImageColor.r = color.r;
+ this._backGroundImageColor.g = color.g;
+ this._backGroundImageColor.b = color.b;
+
+ this._updateBackGroundImageColor();
+ },
+
+ /**
+ * Sets backGround image Opacity
+ * @param {Number} opacity
+ */
+ setBackGroundImageOpacity: function (opacity) {
+ this._backGroundImageColor.a = opacity;
+ this.getBackGroundImageColor();
+ },
+
+ /**
+ * Gets backGround image color
+ * @returns {cc.Color}
+ */
+ getBackGroundImageColor: function () {
+ var color = this._backGroundImageColor;
+ return cc.color(color.r, color.g, color.b, color.a);
+ },
+
+ /**
+ * Gets backGround image opacity
+ * @returns {Number}
+ */
+ getBackGroundImageOpacity: function () {
+ return this._backGroundImageColor.a;
+ },
+
+ _updateBackGroundImageColor: function () {
+ if (this._backGroundImage)
+ this._backGroundImage.setColor(this._backGroundImageColor);
+ },
+
+ /**
+ * Gets background image texture size.
+ * @returns {cc.Size}
+ */
+ getBackGroundImageTextureSize: function () {
+ return this._backGroundImageTextureSize;
+ },
+
+ /**
+ * Sets LayoutType to ccui.Layout, LayoutManager will do layout by layout type..
+ * @param {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE} type
+ */
+ setLayoutType: function (type) {
+ this._layoutType = type;
+ var layoutChildrenArray = this._children;
+ var locChild = null;
+ for (var i = 0; i < layoutChildrenArray.length; i++) {
+ locChild = layoutChildrenArray[i];
+ if (locChild instanceof ccui.Widget)
+ this._supplyTheLayoutParameterLackToChild(locChild);
+ }
+ this._doLayoutDirty = true;
+ },
+
+ /**
+ * Gets LayoutType of ccui.Layout.
+ * @returns {null}
+ */
+ getLayoutType: function () {
+ return this._layoutType;
+ },
+
+ /**
+ * request to refresh widget layout, it will do layout at visit calls
+ */
+ requestDoLayout: function () {
+ this._doLayoutDirty = true;
+ },
+
+ _doLayout: function () {
+ if (!this._doLayoutDirty)
+ return;
+
+ this.sortAllChildren();
+
+ var executant = ccui.getLayoutManager(this._layoutType);
+ if (executant)
+ executant._doLayout(this);
+ this._doLayoutDirty = false;
+ },
+
+ _getLayoutContentSize: function () {
+ return this.getContentSize();
+ },
+
+ _getLayoutElements: function () {
+ return this.getChildren();
+ },
+
+ _updateBackGroundImageOpacity: function () {
+ if (this._backGroundImage)
+ this._backGroundImage.setOpacity(this._backGroundImageOpacity);
+ },
+
+ _updateBackGroundImageRGBA: function () {
+ if (this._backGroundImage) {
+ this._backGroundImage.setColor(this._backGroundImageColor);
+ this._backGroundImage.setOpacity(this._backGroundImageOpacity);
+ }
+ },
+
+ /**
+ * Gets the content size of the layout, it will accumulate all its children's content size
+ * @returns {cc.Size}
+ * @private
+ */
+ _getLayoutAccumulatedSize: function () {
+ var children = this.getChildren();
+ var layoutSize = cc.size(0, 0);
+ var widgetCount = 0, locSize;
+ for (var i = 0, len = children.length; i < len; i++) {
+ var layout = children[i];
+ if (null !== layout && layout instanceof ccui.Layout) {
+ locSize = layout._getLayoutAccumulatedSize();
+ layoutSize.width += locSize.width;
+ layoutSize.height += locSize.height;
+ } else {
+ if (layout instanceof ccui.Widget) {
+ widgetCount++;
+ var m = layout.getLayoutParameter().getMargin();
+ locSize = layout.getContentSize();
+ layoutSize.width += locSize.width + (m.right + m.left) * 0.5;
+ layoutSize.height += locSize.height + (m.top + m.bottom) * 0.5;
+ }
+ }
+ }
+
+ //substract extra size
+ var type = this.getLayoutType();
+ if (type === ccui.Layout.LINEAR_HORIZONTAL)
+ layoutSize.height = layoutSize.height - layoutSize.height / widgetCount * (widgetCount - 1);
+
+ if (type === ccui.Layout.LINEAR_VERTICAL)
+ layoutSize.width = layoutSize.width - layoutSize.width / widgetCount * (widgetCount - 1);
+ return layoutSize;
+ },
+
+ /**
+ * When the layout get focused, it the layout pass the focus to its child, it will use this method to determine which child
+ * will get the focus. The current algorithm to determine which child will get focus is nearest-distance-priority algorithm
+ * @param {Number} direction next focused widget direction
+ * @param {ccui.Widget} baseWidget
+ * @returns {Number}
+ * @private
+ */
+ _findNearestChildWidgetIndex: function (direction, baseWidget) {
+ if (baseWidget == null || baseWidget === this)
+ return this._findFirstFocusEnabledWidgetIndex();
+
+ var index = 0, locChildren = this.getChildren();
+ var count = locChildren.length, widgetPosition;
+
+ var distance = cc.FLT_MAX, found = 0;
+ if (direction === ccui.Widget.LEFT || direction === ccui.Widget.RIGHT || direction === ccui.Widget.DOWN || direction === ccui.Widget.UP) {
+ widgetPosition = this._getWorldCenterPoint(baseWidget);
+ while (index < count) {
+ var w = locChildren[index];
+ if (w && w instanceof ccui.Widget && w.isFocusEnabled()) {
+ var length = (w instanceof ccui.Layout) ? w._calculateNearestDistance(baseWidget)
+ : cc.pLength(cc.pSub(this._getWorldCenterPoint(w), widgetPosition));
+ if (length < distance) {
+ found = index;
+ distance = length;
+ }
+ }
+ index++;
+ }
+ return found;
+ }
+ cc.log("invalid focus direction!");
+ return 0;
+ },
+
+ /**
+ * When the layout get focused, it the layout pass the focus to its child, it will use this method to determine which child
+ * will get the focus. The current algorithm to determine which child will get focus is farthest-distance-priority algorithm
+ * @param {Number} direction next focused widget direction
+ * @param {ccui.Widget} baseWidget
+ * @returns {Number} The index of child widget in the container
+ * @private
+ */
+ _findFarthestChildWidgetIndex: function (direction, baseWidget) {
+ if (baseWidget == null || baseWidget === this)
+ return this._findFirstFocusEnabledWidgetIndex();
+
+ var index = 0, locChildren = this.getChildren();
+ var count = locChildren.length;
+
+ var distance = -cc.FLT_MAX, found = 0;
+ if (direction === ccui.Widget.LEFT || direction === ccui.Widget.RIGHT || direction === ccui.Widget.DOWN || direction === ccui.Widget.UP) {
+ var widgetPosition = this._getWorldCenterPoint(baseWidget);
+ while (index < count) {
+ var w = locChildren[index];
+ if (w && w instanceof ccui.Widget && w.isFocusEnabled()) {
+ var length = (w instanceof ccui.Layout) ? w._calculateFarthestDistance(baseWidget)
+ : cc.pLength(cc.pSub(this._getWorldCenterPoint(w), widgetPosition));
+ if (length > distance) {
+ found = index;
+ distance = length;
+ }
+ }
+ index++;
+ }
+ return found;
+ }
+ cc.log("invalid focus direction!!!");
+ return 0;
+ },
+
+ /**
+ * calculate the nearest distance between the baseWidget and the children of the layout
+ * @param {ccui.Widget} baseWidget the base widget which will be used to calculate the distance between the layout's children and itself
+ * @returns {Number} return the nearest distance between the baseWidget and the layout's children
+ * @private
+ */
+ _calculateNearestDistance: function (baseWidget) {
+ var distance = cc.FLT_MAX;
+ var widgetPosition = this._getWorldCenterPoint(baseWidget);
+ var locChildren = this._children;
+
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var widget = locChildren[i], length;
+ if (widget instanceof ccui.Layout)
+ length = widget._calculateNearestDistance(baseWidget);
+ else {
+ if (widget instanceof ccui.Widget && widget.isFocusEnabled())
+ length = cc.pLength(cc.pSub(this._getWorldCenterPoint(widget), widgetPosition));
+ else
+ continue;
+ }
+ if (length < distance)
+ distance = length;
+ }
+ return distance;
+ },
+
+ /**
+ * calculate the farthest distance between the baseWidget and the children of the layout
+ * @param baseWidget
+ * @returns {number}
+ * @private
+ */
+ _calculateFarthestDistance: function (baseWidget) {
+ var distance = -cc.FLT_MAX;
+ var widgetPosition = this._getWorldCenterPoint(baseWidget);
+ var locChildren = this._children;
+
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var layout = locChildren[i];
+ var length;
+ if (layout instanceof ccui.Layout)
+ length = layout._calculateFarthestDistance(baseWidget);
+ else {
+ if (layout instanceof ccui.Widget && layout.isFocusEnabled()) {
+ var wPosition = this._getWorldCenterPoint(layout);
+ length = cc.pLength(cc.pSub(wPosition, widgetPosition));
+ } else
+ continue;
+ }
+
+ if (length > distance)
+ distance = length;
+ }
+ return distance;
+ },
+
+ /**
+ * when a layout pass the focus to it's child, use this method to determine which algorithm to use, nearest or farthest distance algorithm or not
+ * @param direction
+ * @param baseWidget
+ * @private
+ */
+ _findProperSearchingFunctor: function (direction, baseWidget) {
+ if (baseWidget === undefined)
+ return;
+
+ var previousWidgetPosition = this._getWorldCenterPoint(baseWidget);
+ var widgetPosition = this._getWorldCenterPoint(this._findFirstNonLayoutWidget());
+ if (direction === ccui.Widget.LEFT) {
+ this.onPassFocusToChild = (previousWidgetPosition.x > widgetPosition.x) ? this._findNearestChildWidgetIndex
+ : this._findFarthestChildWidgetIndex;
+ } else if (direction === ccui.Widget.RIGHT) {
+ this.onPassFocusToChild = (previousWidgetPosition.x > widgetPosition.x) ? this._findFarthestChildWidgetIndex
+ : this._findNearestChildWidgetIndex;
+ } else if (direction === ccui.Widget.DOWN) {
+ this.onPassFocusToChild = (previousWidgetPosition.y > widgetPosition.y) ? this._findNearestChildWidgetIndex
+ : this._findFarthestChildWidgetIndex;
+ } else if (direction === ccui.Widget.UP) {
+ this.onPassFocusToChild = (previousWidgetPosition.y < widgetPosition.y) ? this._findNearestChildWidgetIndex
+ : this._findFarthestChildWidgetIndex;
+ } else
+ cc.log("invalid direction!");
+ },
+
+ /**
+ * find the first non-layout widget in this layout
+ * @returns {ccui.Widget}
+ * @private
+ */
+ _findFirstNonLayoutWidget: function () {
+ var locChildren = this._children;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var child = locChildren[i];
+ if (child instanceof ccui.Layout) {
+ var widget = child._findFirstNonLayoutWidget();
+ if (widget)
+ return widget;
+ } else {
+ if (child instanceof ccui.Widget)
+ return child;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * find the first focus enabled widget index in the layout, it will recursive searching the child widget
+ * @returns {number}
+ * @private
+ */
+ _findFirstFocusEnabledWidgetIndex: function () {
+ var index = 0, locChildren = this.getChildren();
+ var count = locChildren.length;
+ while (index < count) {
+ var w = locChildren[index];
+ if (w && w instanceof ccui.Widget && w.isFocusEnabled())
+ return index;
+ index++;
+ }
+ return 0;
+ },
+
+ /**
+ * find a focus enabled child Widget in the layout by index
+ * @param index
+ * @returns {*}
+ * @private
+ */
+ _findFocusEnabledChildWidgetByIndex: function (index) {
+ var widget = this._getChildWidgetByIndex(index);
+ if (widget) {
+ if (widget.isFocusEnabled())
+ return widget;
+ index = index + 1;
+ return this._findFocusEnabledChildWidgetByIndex(index);
+ }
+ return null;
+ },
+
+ /**
+ * get the center point of a widget in world space
+ * @param {ccui.Widget} widget
+ * @returns {cc.Point}
+ * @private
+ */
+ _getWorldCenterPoint: function (widget) {
+ //FIXEDME: we don't need to calculate the content size of layout anymore
+ var widgetSize = widget instanceof ccui.Layout ? widget._getLayoutAccumulatedSize() : widget.getContentSize();
+ return widget.convertToWorldSpace(cc.p(widgetSize.width / 2, widgetSize.height / 2));
+ },
+
+ /**
+ * this method is called internally by nextFocusedWidget. When the dir is Right/Down, then this method will be called
+ * @param {Number} direction
+ * @param {ccui.Widget} current the current focused widget
+ * @returns {ccui.Widget} the next focused widget
+ * @private
+ */
+ _getNextFocusedWidget: function (direction, current) {
+ var nextWidget = null, locChildren = this._children;
+ var previousWidgetPos = locChildren.indexOf(current);
+ previousWidgetPos = previousWidgetPos + 1;
+ if (previousWidgetPos < locChildren.length) {
+ nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
+ //handle widget
+ if (nextWidget) {
+ if (nextWidget.isFocusEnabled()) {
+ if (nextWidget instanceof ccui.Layout) {
+ nextWidget._isFocusPassing = true;
+ return nextWidget.findNextFocusedWidget(direction, nextWidget);
+ } else {
+ this.dispatchFocusEvent(current, nextWidget);
+ return nextWidget;
+ }
+ } else
+ return this._getNextFocusedWidget(direction, nextWidget);
+ } else
+ return current;
+ } else {
+ if (this._loopFocus) {
+ if (this._checkFocusEnabledChild()) {
+ previousWidgetPos = 0;
+ nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
+ if (nextWidget.isFocusEnabled()) {
+ if (nextWidget instanceof ccui.Layout) {
+ nextWidget._isFocusPassing = true;
+ return nextWidget.findNextFocusedWidget(direction, nextWidget);
+ } else {
+ this.dispatchFocusEvent(current, nextWidget);
+ return nextWidget;
+ }
+ } else
+ return this._getNextFocusedWidget(direction, nextWidget);
+ } else
+ return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
+ } else {
+ if (this._isLastWidgetInContainer(current, direction)) {
+ if (this._isWidgetAncestorSupportLoopFocus(this, direction))
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
+ } else
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ }
+ }
+ },
+
+ /**
+ * this method is called internally by nextFocusedWidget. When the dir is Left/Up, then this method will be called
+ * @param direction
+ * @param {ccui.Widget} current the current focused widget
+ * @returns {ccui.Widget} the next focused widget
+ * @private
+ */
+ _getPreviousFocusedWidget: function (direction, current) {
+ var nextWidget = null, locChildren = this._children;
+ var previousWidgetPos = locChildren.indexOf(current);
+ previousWidgetPos = previousWidgetPos - 1;
+ if (previousWidgetPos >= 0) {
+ nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
+ if (nextWidget.isFocusEnabled()) {
+ if (nextWidget instanceof ccui.Layout) {
+ nextWidget._isFocusPassing = true;
+ return nextWidget.findNextFocusedWidget(direction, nextWidget);
+ }
+ this.dispatchFocusEvent(current, nextWidget);
+ return nextWidget;
+ } else
+ return this._getPreviousFocusedWidget(direction, nextWidget); //handling the disabled widget, there is no actual focus lose or get, so we don't need any envet
+ } else {
+ if (this._loopFocus) {
+ if (this._checkFocusEnabledChild()) {
+ previousWidgetPos = locChildren.length - 1;
+ nextWidget = this._getChildWidgetByIndex(previousWidgetPos);
+ if (nextWidget.isFocusEnabled()) {
+ if (nextWidget instanceof ccui.Layout) {
+ nextWidget._isFocusPassing = true;
+ return nextWidget.findNextFocusedWidget(direction, nextWidget);
+ } else {
+ this.dispatchFocusEvent(current, nextWidget);
+ return nextWidget;
+ }
+ } else
+ return this._getPreviousFocusedWidget(direction, nextWidget);
+ } else
+ return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
+ } else {
+ if (this._isLastWidgetInContainer(current, direction)) {
+ if (this._isWidgetAncestorSupportLoopFocus(this, direction))
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ return (current instanceof ccui.Layout) ? current : ccui.Widget._focusedWidget;
+ } else
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, this);
+ }
+ }
+ },
+
+ /**
+ * find the nth element in the _children array. Only the Widget descendant object will be returned
+ * @param {Number} index
+ * @returns {ccui.Widget}
+ * @private
+ */
+ _getChildWidgetByIndex: function (index) {
+ var locChildren = this._children;
+ var size = locChildren.length, count = 0, oldIndex = index;
+ while (index < size) {
+ var firstChild = locChildren[index];
+ if (firstChild && firstChild instanceof ccui.Widget)
+ return firstChild;
+ count++;
+ index++;
+ }
+
+ var begin = 0;
+ while (begin < oldIndex) {
+ var child = locChildren[begin];
+ if (child && child instanceof ccui.Widget)
+ return child;
+ count++;
+ begin++;
+ }
+ return null;
+ },
+
+ /**
+ * whether it is the last element according to all their parents
+ * @param {ccui.Widget} widget
+ * @param {Number} direction
+ * @returns {Boolean}
+ * @private
+ */
+ _isLastWidgetInContainer: function (widget, direction) {
+ var parent = widget.getParent();
+ if (parent == null || !(parent instanceof ccui.Layout))
+ return true;
+
+ var container = parent.getChildren();
+ var index = container.indexOf(widget);
+ if (parent.getLayoutType() === ccui.Layout.LINEAR_HORIZONTAL) {
+ if (direction === ccui.Widget.LEFT) {
+ if (index === 0)
+ return this._isLastWidgetInContainer(parent, direction);
+ else
+ return false;
+ }
+ if (direction === ccui.Widget.RIGHT) {
+ if (index === container.length - 1)
+ return this._isLastWidgetInContainer(parent, direction);
+ else
+ return false;
+ }
+ if (direction === ccui.Widget.DOWN)
+ return this._isLastWidgetInContainer(parent, direction);
+
+ if (direction === ccui.Widget.UP)
+ return this._isLastWidgetInContainer(parent, direction);
+ } else if (parent.getLayoutType() === ccui.Layout.LINEAR_VERTICAL) {
+ if (direction === ccui.Widget.UP) {
+ if (index === 0)
+ return this._isLastWidgetInContainer(parent, direction);
+ else
+ return false;
+ }
+ if (direction === ccui.Widget.DOWN) {
+ if (index === container.length - 1)
+ return this._isLastWidgetInContainer(parent, direction);
+ else
+ return false;
+ }
+ if (direction === ccui.Widget.LEFT)
+ return this._isLastWidgetInContainer(parent, direction);
+
+ if (direction === ccui.Widget.RIGHT)
+ return this._isLastWidgetInContainer(parent, direction);
+ } else {
+ cc.log("invalid layout Type");
+ return false;
+ }
+ },
+
+ /**
+ * Lookup any parent widget with a layout type as the direction, if the layout is loop focused, then return true, otherwise it returns false.
+ * @param {ccui.Widget} widget
+ * @param {Number} direction
+ * @returns {Boolean}
+ * @private
+ */
+ _isWidgetAncestorSupportLoopFocus: function (widget, direction) {
+ var parent = widget.getParent();
+ if (parent == null || !(parent instanceof ccui.Layout))
+ return false;
+ if (parent.isLoopFocus()) {
+ var layoutType = parent.getLayoutType();
+ if (layoutType === ccui.Layout.LINEAR_HORIZONTAL) {
+ if (direction === ccui.Widget.LEFT || direction === ccui.Widget.RIGHT)
+ return true;
+ else
+ return this._isWidgetAncestorSupportLoopFocus(parent, direction);
+ }
+ if (layoutType === ccui.Layout.LINEAR_VERTICAL) {
+ if (direction === ccui.Widget.DOWN || direction === ccui.Widget.UP)
+ return true;
+ else
+ return this._isWidgetAncestorSupportLoopFocus(parent, direction);
+ } else {
+ cc.assert(0, "invalid layout type");
+ return false;
+ }
+ } else
+ return this._isWidgetAncestorSupportLoopFocus(parent, direction);
+ },
+
+ /**
+ * pass the focus to the layout's next focus enabled child
+ * @param {Number} direction
+ * @param {ccui.Widget} current
+ * @returns {ccui.Widget}
+ * @private
+ */
+ _passFocusToChild: function (direction, current) {
+ if (this._checkFocusEnabledChild()) {
+ var previousWidget = ccui.Widget.getCurrentFocusedWidget();
+ this._findProperSearchingFunctor(direction, previousWidget);
+ var index = this.onPassFocusToChild(direction, previousWidget);
+
+ var widget = this._getChildWidgetByIndex(index);
+ if (widget instanceof ccui.Layout) {
+ widget._isFocusPassing = true;
+ return widget.findNextFocusedWidget(direction, widget);
+ } else {
+ this.dispatchFocusEvent(current, widget);
+ return widget;
+ }
+ } else
+ return this;
+ },
+
+ /**
+ * If there are no focus enabled child in the layout, it will return false, otherwise it returns true
+ * @returns {boolean}
+ * @private
+ */
+ _checkFocusEnabledChild: function () {
+ var locChildren = this._children;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var widget = locChildren[i];
+ if (widget && widget instanceof ccui.Widget && widget.isFocusEnabled())
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Returns the "class name" of widget.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "Layout";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.Layout();
+ },
+
+ _copyClonedWidgetChildren: function (model) {
+ ccui.Widget.prototype._copyClonedWidgetChildren.call(this, model);
+ },
+
+ _copySpecialProperties: function (layout) {
+ if (!(layout instanceof ccui.Layout))
+ return;
+ this.setBackGroundImageScale9Enabled(layout._backGroundScale9Enabled);
+ this.setBackGroundImage(layout._backGroundImageFileName, layout._bgImageTexType);
+ this.setBackGroundImageCapInsets(layout._backGroundImageCapInsets);
+ this.setBackGroundColorType(layout._colorType);
+ this.setBackGroundColor(layout._color);
+ this.setBackGroundColor(layout._startColor, layout._endColor);
+ this.setBackGroundColorOpacity(layout._opacity);
+ this.setBackGroundColorVector(layout._alongVector);
+ this.setLayoutType(layout._layoutType);
+ this.setClippingEnabled(layout._clippingEnabled);
+ this.setClippingType(layout._clippingType);
+ this._loopFocus = layout._loopFocus;
+ this.__passFocusToChild = layout.__passFocusToChild;
+ this._isInterceptTouch = layout._isInterceptTouch;
+ },
+
+ /**
+ * force refresh widget layout
+ */
+ forceDoLayout: function () {
+ this.requestDoLayout();
+ this._doLayout();
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new ccui.Layout.WebGLRenderCmd(this);
+ else
+ return new ccui.Layout.CanvasRenderCmd(this);
+ }
+});
+
+var _p = ccui.Layout.prototype;
+
+// Extended properties
+/** @expose */
+_p.clippingEnabled;
+cc.defineGetterSetter(_p, "clippingEnabled", _p.isClippingEnabled, _p.setClippingEnabled);
+/** @expose */
+_p.clippingType;
+cc.defineGetterSetter(_p, "clippingType", null, _p.setClippingType);
+/** @expose */
+_p.layoutType;
+cc.defineGetterSetter(_p, "layoutType", _p.getLayoutType, _p.setLayoutType);
+
+_p = null;
+
+/**
+ * allocates and initializes a UILayout.
+ * @deprecated since v3.0, please use new ccui.Layout() instead.
+ * @return {ccui.Layout}
+ */
+ccui.Layout.create = function () {
+ return new ccui.Layout();
+};
+
+// Constants
+
+//layoutBackGround color type
+/**
+ * The None of ccui.Layout's background color type
+ * @constant
+ * @type {number}
+ */
+ccui.Layout.BG_COLOR_NONE = 0;
+/**
+ * The solid of ccui.Layout's background color type, it will use a LayerColor to draw the background.
+ * @constant
+ * @type {number}
+ */
+ccui.Layout.BG_COLOR_SOLID = 1;
+/**
+ * The gradient of ccui.Layout's background color type, it will use a LayerGradient to draw the background.
+ * @constant
+ * @type {number}
+ */
+ccui.Layout.BG_COLOR_GRADIENT = 2;
+
+//Layout type
+/**
+ * The absolute of ccui.Layout's layout type.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.ABSOLUTE = 0;
+/**
+ * The vertical of ccui.Layout's layout type.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.LINEAR_VERTICAL = 1;
+/**
+ * The horizontal of ccui.Layout's layout type.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.LINEAR_HORIZONTAL = 2;
+/**
+ * The relative of ccui.Layout's layout type.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.RELATIVE = 3;
+
+//Layout clipping type
+/**
+ * The stencil of ccui.Layout's clipping type.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.CLIPPING_STENCIL = 0;
+/**
+ * The scissor of ccui.Layout's clipping type.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.CLIPPING_SCISSOR = 1;
+
+/**
+ * The zOrder value of ccui.Layout's image background.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.BACKGROUND_IMAGE_ZORDER = -1;
+/**
+ * The zOrder value of ccui.Layout's color background.
+ * @type {number}
+ * @constant
+ */
+ccui.Layout.BACKGROUND_RENDERER_ZORDER = -2;
diff --git a/extensions/ccui/layouts/UILayoutCanvasRenderCmd.js b/extensions/ccui/layouts/UILayoutCanvasRenderCmd.js
new file mode 100644
index 0000000000..7d847ccedd
--- /dev/null
+++ b/extensions/ccui/layouts/UILayoutCanvasRenderCmd.js
@@ -0,0 +1,103 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ ccui.Layout.CanvasRenderCmd = function (renderable) {
+ this._pNodeCmdCtor(renderable);
+ this._needDraw = false;
+
+ this._rendererSaveCmd = null;
+ this._rendererClipCmd = null;
+ this._rendererRestoreCmd = null;
+ };
+
+ var proto = ccui.Layout.CanvasRenderCmd.prototype = Object.create(ccui.ProtectedNode.CanvasRenderCmd.prototype);
+ proto.constructor = ccui.Layout.CanvasRenderCmd;
+ proto._layoutCmdCtor = ccui.Layout.CanvasRenderCmd;
+
+ proto._onRenderSaveCmd = function (ctx, scaleX, scaleY) {
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+ wrapper.save();
+ wrapper.save();
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ var buffer = this._node._clippingStencil._renderCmd._buffer;
+
+ for (var i = 0, bufLen = buffer.length; i < bufLen; i++) {
+ var element = buffer[i], vertices = element.verts;
+ var firstPoint = vertices[0];
+ context.beginPath();
+ context.moveTo(firstPoint.x, -firstPoint.y);
+ for (var j = 1, len = vertices.length; j < len; j++)
+ context.lineTo(vertices[j].x, -vertices[j].y);
+ context.closePath();
+ }
+ };
+
+ proto._onRenderClipCmd = function (ctx) {
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+ wrapper.restore();
+ context.clip();
+ };
+
+ proto._onRenderRestoreCmd = function (ctx) {
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+
+ wrapper.restore();
+ };
+
+ proto.rebindStencilRendering = function (stencil) {
+ stencil._renderCmd.rendering = this.__stencilDraw;
+ stencil._renderCmd._canUseDirtyRegion = true;
+ };
+
+ proto.__stencilDraw = function (ctx, scaleX, scaleY) { //Only for Canvas
+ //do nothing, rendering in layout
+ };
+
+ proto.stencilClippingVisit = proto.scissorClippingVisit = function (parentCmd) {
+ var node = this._node;
+ if (!node._clippingStencil || !node._clippingStencil.isVisible())
+ return;
+
+ if (!this._rendererSaveCmd) {
+ this._rendererSaveCmd = new cc.CustomRenderCmd(this, this._onRenderSaveCmd);
+ this._rendererClipCmd = new cc.CustomRenderCmd(this, this._onRenderClipCmd);
+ this._rendererRestoreCmd = new cc.CustomRenderCmd(this, this._onRenderRestoreCmd);
+ }
+
+ cc.renderer.pushRenderCommand(this._rendererSaveCmd);
+ node._clippingStencil.visit(this);
+
+ cc.renderer.pushRenderCommand(this._rendererClipCmd);
+ };
+
+ proto.postStencilVisit = proto.postScissorVisit = function () {
+ cc.renderer.pushRenderCommand(this._rendererRestoreCmd);
+ };
+
+ ccui.Layout.CanvasRenderCmd._getSharedCache = function () {
+ return (cc.ClippingNode._sharedCache) || (cc.ClippingNode._sharedCache = document.createElement("canvas"));
+ };
+})();
diff --git a/extensions/ccui/layouts/UILayoutComponent.js b/extensions/ccui/layouts/UILayoutComponent.js
new file mode 100644
index 0000000000..3a910f690a
--- /dev/null
+++ b/extensions/ccui/layouts/UILayoutComponent.js
@@ -0,0 +1,598 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+ccui.LayoutComponent_ReferencePoint = {
+ BOTTOM_LEFT: 0,
+ TOP_LEFT: 1,
+ BOTTOM_RIGHT: 2,
+ TOP_RIGHT: 3
+};
+ccui.LayoutComponent_PositionType = {
+ Position: 0,
+ RelativePosition: 1,
+ PreRelativePosition: 2,
+ PreRelativePositionEnable: 3
+};
+ccui.LayoutComponent_SizeType = {
+ Size: 0,
+ PreSize: 1,
+ PreSizeEnable: 2
+};
+
+//refactor since v3.3
+ccui.LayoutComponent = cc.Component.extend({
+ _horizontalEdge: 0,
+ _verticalEdge: 0,
+
+ _leftMargin: 0,
+ _rightMargin: 0,
+ _bottomMargin: 0,
+ _topMargin: 0,
+
+ _usingPositionPercentX: false,
+ _positionPercentX: 0,
+ _usingPositionPercentY: false,
+ _positionPercentY: 0,
+
+ _usingStretchWidth: false,
+ _usingStretchHeight: false,
+
+ _percentWidth: 0,
+ _usingPercentWidth: false,
+
+ _percentHeight: 0,
+ _usingPercentHeight: false,
+
+ _actived: true,
+ _isPercentOnly: false,
+
+ ctor: function () {
+ this._name = ccui.LayoutComponent.NAME;
+ },
+
+ init: function () {
+ var ret = true;
+
+ if (!cc.Component.prototype.init.call(this)) {
+ return false;
+ }
+
+ //put layout component initalized code here
+
+ return ret;
+ },
+
+ getPercentContentSize: function () {
+ return cc.p(this._percentWidth, this._percentHeight);
+ },
+ setPercentContentSize: function (percent) {
+ this.setPercentWidth(percent.x);
+ this.setPercentHeight(percent.y);
+ },
+
+ setUsingPercentContentSize: function (isUsed) {
+ this._usingPercentWidth = this._usingPercentHeight = isUsed;
+ },
+
+ //old
+ SetActiveEnable: function (enable) {
+ this._actived = enable;
+ },
+
+ //v3.3
+ getUsingPercentContentSize: function () {
+ return this._usingPercentWidth && this._usingPercentHeight;
+ },
+
+ //position & margin
+ getAnchorPosition: function () {
+ return this._owner.getAnchorPoint();
+ },
+
+ setAnchorPosition: function (point, y) {
+ var oldRect = this._owner.getBoundingBox();
+ this._owner.setAnchorPoint(point, y);
+ var newRect = this._owner.getBoundingBox();
+ var offSetX = oldRect.x - newRect.x, offSetY = oldRect.y - newRect.y;
+
+ var ownerPosition = this._owner.getPosition();
+ ownerPosition.x += offSetX;
+ ownerPosition.y += offSetY;
+ this.setPosition(ownerPosition);
+ },
+
+ getPosition: function () {
+ return this._owner.getPosition();
+ },
+
+ setPosition: function (position, y) {
+ var parent = this._getOwnerParent(), x;
+ if (parent != null) {
+ if (y === undefined) {
+ x = position.x;
+ y = position.y;
+ } else
+ x = position;
+ var parentSize = parent.getContentSize();
+
+ if (parentSize.width !== 0)
+ this._positionPercentX = x / parentSize.width;
+ else {
+ this._positionPercentX = 0;
+ if (this._usingPositionPercentX)
+ x = 0;
+ }
+
+ if (parentSize.height !== 0)
+ this._positionPercentY = y / parentSize.height;
+ else {
+ this._positionPercentY = 0;
+ if (this._usingPositionPercentY)
+ y = 0;
+ }
+
+ this._owner.setPosition(x, y);
+ this._refreshHorizontalMargin();
+ this._refreshVerticalMargin();
+ } else
+ this._owner.setPosition(position, y);
+ },
+
+ isPositionPercentXEnabled: function () {
+ return this._usingPositionPercentX;
+ },
+ setPositionPercentXEnabled: function (isUsed) {
+ this._usingPositionPercentX = isUsed;
+ if (this._usingPositionPercentX)
+ this._horizontalEdge = ccui.LayoutComponent.horizontalEdge.NONE;
+ },
+
+ getPositionPercentX: function () {
+ return this._positionPercentX;
+ },
+ setPositionPercentX: function (percentMargin) {
+ this._positionPercentX = percentMargin;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ this._owner.setPositionX(parent.width * this._positionPercentX);
+ this._refreshHorizontalMargin();
+ }
+ },
+
+ isPositionPercentYEnabled: function () {
+ return this._usingPositionPercentY;
+ },
+ setPositionPercentYEnabled: function (isUsed) {
+ this._usingPositionPercentY = isUsed;
+ if (this._usingPositionPercentY)
+ this._verticalEdge = ccui.LayoutComponent.verticalEdge.NONE;
+ },
+
+ getPositionPercentY: function () {
+ return this._positionPercentY;
+ },
+ setPositionPercentY: function (percentMargin) {
+ this._positionPercentY = percentMargin;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ this._owner.setPositionY(parent.height * this._positionPercentY);
+ this._refreshVerticalMargin();
+ }
+ },
+
+ getHorizontalEdge: function () {
+ return this._horizontalEdge;
+ },
+ setHorizontalEdge: function (hEdge) {
+ this._horizontalEdge = hEdge;
+ if (this._horizontalEdge !== ccui.LayoutComponent.horizontalEdge.NONE)
+ this._usingPositionPercentX = false;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ var ownerPoint = this._owner.getPosition();
+ var parentSize = parent.getContentSize();
+ if (parentSize.width !== 0)
+ this._positionPercentX = ownerPoint.x / parentSize.width;
+ else {
+ this._positionPercentX = 0;
+ ownerPoint.x = 0;
+ if (this._usingPositionPercentX)
+ this._owner.setPosition(ownerPoint);
+ }
+ this._refreshHorizontalMargin();
+ }
+ },
+
+ getVerticalEdge: function () {
+ return this._verticalEdge;
+ },
+ setVerticalEdge: function (vEdge) {
+ this._verticalEdge = vEdge;
+ if (this._verticalEdge !== ccui.LayoutComponent.verticalEdge.NONE)
+ this._usingPositionPercentY = false;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ var ownerPoint = this._owner.getPosition();
+ var parentSize = parent.getContentSize();
+ if (parentSize.height !== 0)
+ this._positionPercentY = ownerPoint.y / parentSize.height;
+ else {
+ this._positionPercentY = 0;
+ ownerPoint.y = 0;
+ if (this._usingPositionPercentY)
+ this._owner.setPosition(ownerPoint);
+ }
+ this._refreshVerticalMargin();
+ }
+ },
+
+ getLeftMargin: function () {
+ return this._leftMargin;
+ },
+ setLeftMargin: function (margin) {
+ this._leftMargin = margin;
+ },
+
+ getRightMargin: function () {
+ return this._rightMargin;
+ },
+ setRightMargin: function (margin) {
+ this._rightMargin = margin;
+ },
+
+ getTopMargin: function () {
+ return this._topMargin;
+ },
+ setTopMargin: function (margin) {
+ this._topMargin = margin;
+ },
+
+ getBottomMargin: function () {
+ return this._bottomMargin;
+ },
+ setBottomMargin: function (margin) {
+ this._bottomMargin = margin;
+ },
+
+ //size &
+ getSize: function () {
+ return this.getOwner().getContentSize();
+ },
+ setSize: function (size) {
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ var ownerSize = size, parentSize = parent.getContentSize();
+
+ if (parentSize.width !== 0)
+ this._percentWidth = ownerSize.width / parentSize.width;
+ else {
+ this._percentWidth = 0;
+ if (this._usingPercentWidth)
+ ownerSize.width = 0;
+ }
+
+ if (parentSize.height !== 0)
+ this._percentHeight = ownerSize.height / parentSize.height;
+ else {
+ this._percentHeight = 0;
+ if (this._usingPercentHeight)
+ ownerSize.height = 0;
+ }
+
+ this._owner.setContentSize(ownerSize);
+
+ this._refreshHorizontalMargin();
+ this._refreshVerticalMargin();
+ }
+ else
+ this._owner.setContentSize(size);
+ },
+
+ isPercentWidthEnabled: function () {
+ return this._usingPercentWidth;
+ },
+ setPercentWidthEnabled: function (isUsed) {
+ this._usingPercentWidth = isUsed;
+ if (this._usingPercentWidth)
+ this._usingStretchWidth = false;
+ },
+
+ getSizeWidth: function () {
+ return this._owner.width;
+ },
+ setSizeWidth: function (width) {
+ var ownerSize = this._owner.getContentSize();
+ ownerSize.width = width;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ var parentSize = parent.getContentSize();
+ if (parentSize.width !== 0)
+ this._percentWidth = ownerSize.width / parentSize.width;
+ else {
+ this._percentWidth = 0;
+ if (this._usingPercentWidth)
+ ownerSize.width = 0;
+ }
+ this._owner.setContentSize(ownerSize);
+ this._refreshHorizontalMargin();
+ } else
+ this._owner.setContentSize(ownerSize);
+ },
+
+ getPercentWidth: function () {
+ return this._percentWidth;
+ },
+ setPercentWidth: function (percentWidth) {
+ this._percentWidth = percentWidth;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ var ownerSize = this._owner.getContentSize();
+ ownerSize.width = parent.width * this._percentWidth;
+ this._owner.setContentSize(ownerSize);
+ this._refreshHorizontalMargin();
+ }
+ },
+
+ isPercentHeightEnabled: function () {
+ return this._usingPercentHeight;
+ },
+ setPercentHeightEnabled: function (isUsed) {
+ this._usingPercentHeight = isUsed;
+ if (this._usingPercentHeight)
+ this._usingStretchHeight = false;
+ },
+
+ getSizeHeight: function () {
+ return this._owner.height;
+ },
+ setSizeHeight: function (height) {
+ var ownerSize = this._owner.getContentSize();
+ ownerSize.height = height;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ var parentSize = parent.getContentSize();
+ if (parentSize.height !== 0)
+ this._percentHeight = ownerSize.height / parentSize.height;
+ else {
+ this._percentHeight = 0;
+ if (this._usingPercentHeight)
+ ownerSize.height = 0;
+ }
+ this._owner.setContentSize(ownerSize);
+ this._refreshVerticalMargin();
+ }
+ else
+ this._owner.setContentSize(ownerSize);
+ },
+
+ getPercentHeight: function () {
+ return this._percentHeight;
+ },
+ setPercentHeight: function (percentHeight) {
+ this._percentHeight = percentHeight;
+
+ var parent = this._getOwnerParent();
+ if (parent !== null) {
+ var ownerSize = this._owner.getContentSize();
+ ownerSize.height = parent.height * this._percentHeight;
+ this._owner.setContentSize(ownerSize);
+ this._refreshVerticalMargin();
+ }
+ },
+
+ isStretchWidthEnabled: function () {
+ return this._usingStretchWidth;
+ },
+ setStretchWidthEnabled: function (isUsed) {
+ this._usingStretchWidth = isUsed;
+ if (this._usingStretchWidth)
+ this._usingPercentWidth = false;
+ },
+
+ isStretchHeightEnabled: function () {
+ return this._usingStretchHeight;
+ },
+ setStretchHeightEnabled: function (isUsed) {
+ this._usingStretchHeight = isUsed;
+ if (this._usingStretchHeight)
+ this._usingPercentHeight = false;
+ },
+
+ setPercentOnlyEnabled: function(enable){
+ this._isPercentOnly = enable;
+ },
+
+ setActiveEnabled: function (enable) {
+ this._actived = enable;
+ },
+ refreshLayout: function () {
+ if(!this._actived)
+ return;
+
+ var parent = this._getOwnerParent();
+ if (parent === null)
+ return;
+
+ var parentSize = parent.getContentSize(), locOwner = this._owner;
+ var ownerAnchor = locOwner.getAnchorPoint(), ownerSize = locOwner.getContentSize();
+ var ownerPosition = locOwner.getPosition();
+
+ switch (this._horizontalEdge) {
+ case ccui.LayoutComponent.horizontalEdge.NONE:
+ if (this._usingStretchWidth && !this._isPercentOnly) {
+ ownerSize.width = parentSize.width * this._percentWidth;
+ ownerPosition.x = this._leftMargin + ownerAnchor.x * ownerSize.width;
+ } else {
+ if (this._usingPositionPercentX)
+ ownerPosition.x = parentSize.width * this._positionPercentX;
+ if (this._usingPercentWidth)
+ ownerSize.width = parentSize.width * this._percentWidth;
+ }
+ break;
+ case ccui.LayoutComponent.horizontalEdge.LEFT:
+ if(this._isPercentOnly)
+ break;
+ if (this._usingPercentWidth || this._usingStretchWidth)
+ ownerSize.width = parentSize.width * this._percentWidth;
+ ownerPosition.x = this._leftMargin + ownerAnchor.x * ownerSize.width;
+ break;
+ case ccui.LayoutComponent.horizontalEdge.RIGHT:
+ if(this._isPercentOnly)
+ break;
+ if (this._usingPercentWidth || this._usingStretchWidth)
+ ownerSize.width = parentSize.width * this._percentWidth;
+ ownerPosition.x = parentSize.width - (this._rightMargin + (1 - ownerAnchor.x) * ownerSize.width);
+ break;
+ case ccui.LayoutComponent.horizontalEdge.CENTER:
+ if(this._isPercentOnly)
+ break;
+ if (this._usingStretchWidth) {
+ ownerSize.width = parentSize.width - this._leftMargin - this._rightMargin;
+ if (ownerSize.width < 0)
+ ownerSize.width = 0;
+ ownerPosition.x = this._leftMargin + ownerAnchor.x * ownerSize.width;
+ } else {
+ if (this._usingPercentWidth)
+ ownerSize.width = parentSize.width * this._percentWidth;
+ ownerPosition.x = parentSize.width * this._positionPercentX;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (this._verticalEdge) {
+ case ccui.LayoutComponent.verticalEdge.NONE:
+ if (this._usingStretchHeight && !this._isPercentOnly) {
+ ownerSize.height = parentSize.height * this._percentHeight;
+ ownerPosition.y = this._bottomMargin + ownerAnchor.y * ownerSize.height;
+ } else {
+ if (this._usingPositionPercentY)
+ ownerPosition.y = parentSize.height * this._positionPercentY;
+ if (this._usingPercentHeight)
+ ownerSize.height = parentSize.height * this._percentHeight;
+ }
+ break;
+ case ccui.LayoutComponent.verticalEdge.BOTTOM:
+ if(this._isPercentOnly)
+ break;
+ if (this._usingPercentHeight || this._usingStretchHeight)
+ ownerSize.height = parentSize.height * this._percentHeight;
+ ownerPosition.y = this._bottomMargin + ownerAnchor.y * ownerSize.height;
+ break;
+ case ccui.LayoutComponent.verticalEdge.TOP:
+ if(this._isPercentOnly)
+ break;
+ if (this._usingPercentHeight || this._usingStretchHeight)
+ ownerSize.height = parentSize.height * this._percentHeight;
+ ownerPosition.y = parentSize.height - (this._topMargin + (1 - ownerAnchor.y) * ownerSize.height);
+ break;
+ case ccui.LayoutComponent.verticalEdge.CENTER:
+ if(this._isPercentOnly)
+ break;
+ if (this._usingStretchHeight) {
+ ownerSize.height = parentSize.height - this._topMargin - this._bottomMargin;
+ if (ownerSize.height < 0)
+ ownerSize.height = 0;
+ ownerPosition.y = this._bottomMargin + ownerAnchor.y * ownerSize.height;
+ } else {
+ if(this._usingPercentHeight)
+ ownerSize.height = parentSize.height * this._percentHeight;
+ ownerPosition.y = parentSize.height * this._positionPercentY;
+ }
+ break;
+ default:
+ break;
+ }
+
+ locOwner.setPosition(ownerPosition);
+ locOwner.setContentSize(ownerSize);
+
+ if(locOwner instanceof ccui.PageView){
+ locOwner.forceDoLayout();
+
+ var layoutVector = locOwner.getPages();
+ for(var i=0; i 0) {
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ this._widget = locChildren[i];
+
+ var layoutParameter = this._widget.getLayoutParameter();
+ if (layoutParameter){
+ if (layoutParameter._put)
+ continue;
+
+ var ret = this._calculateFinalPositionWithRelativeWidget(layout);
+ if (!ret)
+ continue;
+
+ this._calculateFinalPositionWithRelativeAlign();
+
+ this._widget.setPosition(this._finalPositionX, this._finalPositionY);
+ layoutParameter._put = true;
+ }
+ }
+ this._unlayoutChildCount--;
+ }
+ this._widgetChildren.length = 0;
+ },
+
+ _getAllWidgets: function (layout) {
+ var container = layout._getLayoutElements();
+ var locWidgetChildren = this._widgetChildren;
+ locWidgetChildren.length = 0;
+ for (var i = 0, len = container.length; i < len; i++) {
+ var child = container[i];
+ if (child && child instanceof ccui.Widget) {
+ var layoutParameter = child.getLayoutParameter();
+ layoutParameter._put = false;
+ this._unlayoutChildCount++;
+ locWidgetChildren.push(child);
+ }
+ }
+ return locWidgetChildren;
+ },
+
+ _getRelativeWidget: function (widget) {
+ var relativeWidget = null;
+ var layoutParameter = widget.getLayoutParameter();
+ var relativeName = layoutParameter.getRelativeToWidgetName();
+
+ if (relativeName && relativeName.length !== 0) {
+ var locChildren = this._widgetChildren;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var child = locChildren[i];
+ if (child){
+ var rlayoutParameter = child.getLayoutParameter();
+ if (rlayoutParameter && rlayoutParameter.getRelativeName() === relativeName) {
+ relativeWidget = child;
+ this._relativeWidgetLP = rlayoutParameter;
+ break;
+ }
+ }
+ }
+ }
+ return relativeWidget;
+ },
+
+ _calculateFinalPositionWithRelativeWidget: function (layout) {
+ var locWidget = this._widget;
+ var ap = locWidget.getAnchorPoint();
+ var cs = locWidget.getContentSize();
+
+ this._finalPositionX = 0.0;
+ this._finalPositionY = 0.0;
+
+ var relativeWidget = this._getRelativeWidget(locWidget);
+ var layoutParameter = locWidget.getLayoutParameter();
+ var align = layoutParameter.getAlign();
+ var layoutSize = layout._getLayoutContentSize();
+
+ switch (align) {
+ case ccui.RelativeLayoutParameter.NONE:
+ case ccui.RelativeLayoutParameter.PARENT_TOP_LEFT:
+ this._finalPositionX = ap.x * cs.width;
+ this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height);
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL:
+ this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x);
+ this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height);
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT:
+ this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width);
+ this._finalPositionY = layoutSize.height - ((1.0 - ap.y) * cs.height);
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL:
+ this._finalPositionX = ap.x * cs.width;
+ this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y);
+ break;
+ case ccui.RelativeLayoutParameter.CENTER_IN_PARENT:
+ this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x);
+ this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y);
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL:
+ this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width);
+ this._finalPositionY = layoutSize.height * 0.5 - cs.height * (0.5 - ap.y);
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM:
+ this._finalPositionX = ap.x * cs.width;
+ this._finalPositionY = ap.y * cs.height;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL:
+ this._finalPositionX = layoutSize.width * 0.5 - cs.width * (0.5 - ap.x);
+ this._finalPositionY = ap.y * cs.height;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM:
+ this._finalPositionX = layoutSize.width - ((1.0 - ap.x) * cs.width);
+ this._finalPositionY = ap.y * cs.height;
+ break;
+
+ case ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height;
+ this._finalPositionX = relativeWidget.getLeftBoundary() + ap.x * cs.width;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ var rbs = relativeWidget.getContentSize();
+ this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height;
+ this._finalPositionX = relativeWidget.getLeftBoundary() + rbs.width * 0.5 + ap.x * cs.width - cs.width * 0.5;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getTopBoundary() + ap.y * cs.height;
+ this._finalPositionX = relativeWidget.getRightBoundary() - (1.0 - ap.x) * cs.width;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getTopBoundary() - (1.0 - ap.y) * cs.height;
+ this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ var rbs = relativeWidget.getContentSize();
+ this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width;
+ this._finalPositionY = relativeWidget.getBottomBoundary() + rbs.height * 0.5 + ap.y * cs.height - cs.height * 0.5;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getBottomBoundary() + ap.y * cs.height;
+ this._finalPositionX = relativeWidget.getLeftBoundary() - (1.0 - ap.x) * cs.width;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getTopBoundary() - (1.0 - ap.y) * cs.height;
+ this._finalPositionX = relativeWidget.getRightBoundary() + ap.x * cs.width;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ var rbs = relativeWidget.getContentSize();
+ var locationRight = relativeWidget.getRightBoundary();
+ this._finalPositionX = locationRight + ap.x * cs.width;
+ this._finalPositionY = relativeWidget.getBottomBoundary() + rbs.height * 0.5 + ap.y * cs.height - cs.height * 0.5;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getBottomBoundary() + ap.y * cs.height;
+ this._finalPositionX = relativeWidget.getRightBoundary() + ap.x * cs.width;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height;
+ this._finalPositionX = relativeWidget.getLeftBoundary() + ap.x * cs.width;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ var rbs = relativeWidget.getContentSize();
+ this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height;
+ this._finalPositionX = relativeWidget.getLeftBoundary() + rbs.width * 0.5 + ap.x * cs.width - cs.width * 0.5;
+ }
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN:
+ if (relativeWidget) {
+ if (this._relativeWidgetLP && !this._relativeWidgetLP._put)
+ return false;
+ this._finalPositionY = relativeWidget.getBottomBoundary() - (1.0 - ap.y) * cs.height;
+ this._finalPositionX = relativeWidget.getRightBoundary() - (1.0 - ap.x) * cs.width;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ },
+
+ _calculateFinalPositionWithRelativeAlign: function () {
+ var layoutParameter = this._widget.getLayoutParameter();
+
+ var mg = layoutParameter.getMargin();
+ var align = layoutParameter.getAlign();
+
+ //handle margin
+ switch (align) {
+ case ccui.RelativeLayoutParameter.NONE:
+ case ccui.RelativeLayoutParameter.PARENT_TOP_LEFT:
+ this._finalPositionX += mg.left;
+ this._finalPositionY -= mg.top;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL:
+ this._finalPositionY -= mg.top;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT:
+ this._finalPositionX -= mg.right;
+ this._finalPositionY -= mg.top;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL:
+ this._finalPositionX += mg.left;
+ break;
+ case ccui.RelativeLayoutParameter.CENTER_IN_PARENT:
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL:
+ this._finalPositionX -= mg.right;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM:
+ this._finalPositionX += mg.left;
+ this._finalPositionY += mg.bottom;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL:
+ this._finalPositionY += mg.bottom;
+ break;
+ case ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM:
+ this._finalPositionX -= mg.right;
+ this._finalPositionY += mg.bottom;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN:
+ this._finalPositionY += mg.bottom;
+ this._finalPositionX += mg.left;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN:
+ this._finalPositionY += mg.bottom;
+ this._finalPositionX -= mg.right;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER:
+ this._finalPositionY += mg.bottom;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN:
+ this._finalPositionX -= mg.right;
+ this._finalPositionY -= mg.top;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN:
+ this._finalPositionX -= mg.right;
+ this._finalPositionY += mg.bottom;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER:
+ this._finalPositionX -= mg.right;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN:
+ this._finalPositionX += mg.left;
+ this._finalPositionY -= mg.top;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN:
+ this._finalPositionX += mg.left;
+ this._finalPositionY += mg.bottom;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER:
+ this._finalPositionX += mg.left;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN:
+ this._finalPositionY -= mg.top;
+ this._finalPositionX += mg.left;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN:
+ this._finalPositionY -= mg.top;
+ this._finalPositionX -= mg.right;
+ break;
+ case ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER:
+ this._finalPositionY -= mg.top;
+ break;
+ default:
+ break;
+ }
+ }
+};
diff --git a/extensions/ccui/layouts/UILayoutParameter.js b/extensions/ccui/layouts/UILayoutParameter.js
new file mode 100644
index 0000000000..2ea2919426
--- /dev/null
+++ b/extensions/ccui/layouts/UILayoutParameter.js
@@ -0,0 +1,576 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * Base class for ccui.Margin
+ * @class
+ * @extends ccui.Class
+ *
+ * @property {Number} left - Left of margin
+ * @property {Number} top - Top of margin
+ * @property {Number} right - right of margin
+ * @property {Number} bottom - bottom of margin
+ */
+ccui.Margin = ccui.Class.extend(/** @lends ccui.Margin# */{
+ left: 0,
+ top: 0,
+ right: 0,
+ bottom: 0,
+ /**
+ * Constructor of ccui.Margin.
+ * @param {Number|ccui.Margin} margin a margin or left
+ * @param {Number} [top]
+ * @param {Number} [right]
+ * @param {Number} [bottom]
+ */
+ ctor: function (margin, top, right, bottom) {
+ if (margin !== undefined && top === undefined) {
+ this.left = margin.left;
+ this.top = margin.top;
+ this.right = margin.right;
+ this.bottom = margin.bottom;
+ }
+ if (bottom !== undefined) {
+ this.left = margin;
+ this.top = top;
+ this.right = right;
+ this.bottom = bottom;
+ }
+ },
+ /**
+ * Sets boundary of margin
+ * @param {Number} l left
+ * @param {Number} t top
+ * @param {Number} r right
+ * @param {Number} b bottom
+ */
+ setMargin: function (l, t, r, b) {
+ this.left = l;
+ this.top = t;
+ this.right = r;
+ this.bottom = b;
+ },
+ /**
+ * Checks target whether equals itself.
+ * @param {ccui.Margin} target
+ * @returns {boolean}
+ */
+ equals: function (target) {
+ return (this.left === target.left && this.top === target.top && this.right === target.right && this.bottom === target.bottom);
+ }
+});
+
+/**
+ * Gets a zero margin object
+ * @function
+ * @returns {ccui.Margin}
+ */
+ccui.MarginZero = function(){
+ return new ccui.Margin(0,0,0,0);
+};
+
+/**
+ * Layout parameter contains a margin and layout parameter type. It uses for ccui.LayoutManager.
+ * @class
+ * @extends ccui.Class
+ */
+ccui.LayoutParameter = ccui.Class.extend(/** @lends ccui.LayoutParameter# */{
+ _margin: null,
+ _layoutParameterType: null,
+
+ /**
+ * The constructor of ccui.LayoutParameter.
+ * @function
+ */
+ ctor: function () {
+ this._margin = new ccui.Margin();
+ this._layoutParameterType = ccui.LayoutParameter.NONE;
+ },
+
+ /**
+ * Sets Margin to LayoutParameter.
+ * @param {ccui.Margin} margin
+ */
+ setMargin: function (margin) {
+ if(cc.isObject(margin)){
+ this._margin.left = margin.left;
+ this._margin.top = margin.top;
+ this._margin.right = margin.right;
+ this._margin.bottom = margin.bottom;
+ }else{
+ this._margin.left = arguments[0];
+ this._margin.top = arguments[1];
+ this._margin.right = arguments[2];
+ this._margin.bottom = arguments[3];
+ }
+ },
+
+ /**
+ * Gets Margin of LayoutParameter.
+ * @returns {ccui.Margin}
+ */
+ getMargin: function () {
+ return this._margin;
+ },
+
+ /**
+ * Gets LayoutParameterType of LayoutParameter.
+ * @returns {Number}
+ */
+ getLayoutType: function () {
+ return this._layoutParameterType;
+ },
+
+ /**
+ * Clones a ccui.LayoutParameter object from itself.
+ * @returns {ccui.LayoutParameter}
+ */
+ clone:function(){
+ var parameter = this._createCloneInstance();
+ parameter._copyProperties(this);
+ return parameter;
+ },
+
+ /**
+ * create clone instance.
+ * @returns {ccui.LayoutParameter}
+ */
+ _createCloneInstance:function(){
+ return new ccui.LayoutParameter();
+ },
+
+ /**
+ * copy properties from model.
+ * @param {ccui.LayoutParameter} model
+ */
+ _copyProperties:function(model){
+ this._margin.bottom = model._margin.bottom;
+ this._margin.left = model._margin.left;
+ this._margin.right = model._margin.right;
+ this._margin.top = model._margin.top;
+ }
+});
+
+/**
+ * allocates and initializes a LayoutParameter.
+ * @constructs
+ * @return {ccui.LayoutParameter}
+ */
+ccui.LayoutParameter.create = function () {
+ return new ccui.LayoutParameter();
+};
+
+// Constants
+//layout parameter type
+/**
+ * The none of ccui.LayoutParameter's type.
+ * @constant
+ * @type {number}
+ */
+ccui.LayoutParameter.NONE = 0;
+/**
+ * The linear of ccui.LayoutParameter's type.
+ * @constant
+ * @type {number}
+ */
+ccui.LayoutParameter.LINEAR = 1;
+/**
+ * The relative of ccui.LayoutParameter's type.
+ * @constant
+ * @type {number}
+ */
+ccui.LayoutParameter.RELATIVE = 2;
+
+/**
+ * The linear of Layout parameter. its parameter type is ccui.LayoutParameter.LINEAR.
+ * @class
+ * @extends ccui.LayoutParameter
+ */
+ccui.LinearLayoutParameter = ccui.LayoutParameter.extend(/** @lends ccui.LinearLayoutParameter# */{
+ _linearGravity: null,
+ /**
+ * The constructor of ccui.LinearLayoutParameter.
+ * @function
+ */
+ ctor: function () {
+ ccui.LayoutParameter.prototype.ctor.call(this);
+ this._linearGravity = ccui.LinearLayoutParameter.NONE;
+ this._layoutParameterType = ccui.LayoutParameter.LINEAR;
+ },
+
+ /**
+ * Sets LinearGravity to LayoutParameter.
+ * @param {Number} gravity
+ */
+ setGravity: function (gravity) {
+ this._linearGravity = gravity;
+ },
+
+ /**
+ * Gets LinearGravity of LayoutParameter.
+ * @returns {Number}
+ */
+ getGravity: function () {
+ return this._linearGravity;
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.LinearLayoutParameter();
+ },
+
+ _copyProperties: function (model) {
+ ccui.LayoutParameter.prototype._copyProperties.call(this, model);
+ if (model instanceof ccui.LinearLayoutParameter)
+ this.setGravity(model._linearGravity);
+ }
+});
+
+/**
+ * allocates and initializes a LinearLayoutParameter.
+ * @constructs
+ * @return {ccui.LinearLayoutParameter}
+ * @deprecated since v3.0, please use new construction instead
+ */
+ccui.LinearLayoutParameter.create = function () {
+ return new ccui.LinearLayoutParameter();
+};
+
+// Constants
+//Linear layout parameter LinearGravity
+/**
+ * The none of ccui.LinearLayoutParameter's linear gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.LinearLayoutParameter.NONE = 0;
+
+/**
+ * The left of ccui.LinearLayoutParameter's linear gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.LinearLayoutParameter.LEFT = 1;
+/**
+ * The top of ccui.LinearLayoutParameter's linear gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.LinearLayoutParameter.TOP = 2;
+/**
+ * The right of ccui.LinearLayoutParameter's linear gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.LinearLayoutParameter.RIGHT = 3;
+/**
+ * The bottom of ccui.LinearLayoutParameter's linear gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.LinearLayoutParameter.BOTTOM = 4;
+/**
+ * The center vertical of ccui.LinearLayoutParameter's linear gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.LinearLayoutParameter.CENTER_VERTICAL = 5;
+/**
+ * The center horizontal of ccui.LinearLayoutParameter's linear gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.LinearLayoutParameter.CENTER_HORIZONTAL = 6;
+
+/**
+ * The relative of layout parameter. Its layout parameter type is ccui.LayoutParameter.RELATIVE.
+ * @class
+ * @extends ccui.LayoutParameter
+ */
+ccui.RelativeLayoutParameter = ccui.LayoutParameter.extend(/** @lends ccui.RelativeLayoutParameter# */{
+ _relativeAlign: null,
+ _relativeWidgetName: "",
+ _relativeLayoutName: "",
+ _put:false,
+ /**
+ * The constructor of ccui.RelativeLayoutParameter
+ * @function
+ */
+ ctor: function () {
+ ccui.LayoutParameter.prototype.ctor.call(this);
+ this._relativeAlign = ccui.RelativeLayoutParameter.NONE;
+ this._relativeWidgetName = "";
+ this._relativeLayoutName = "";
+ this._put = false;
+ this._layoutParameterType = ccui.LayoutParameter.RELATIVE;
+ },
+
+ /**
+ * Sets RelativeAlign parameter for LayoutParameter.
+ * @param {Number} align
+ */
+ setAlign: function (align) {
+ this._relativeAlign = align;
+ },
+
+ /**
+ * Gets RelativeAlign parameter for LayoutParameter.
+ * @returns {Number}
+ */
+ getAlign: function () {
+ return this._relativeAlign;
+ },
+
+ /**
+ * Sets a key for LayoutParameter. Witch widget named this is relative to.
+ * @param {String} name
+ */
+ setRelativeToWidgetName: function (name) {
+ this._relativeWidgetName = name;
+ },
+
+ /**
+ * Gets the key of LayoutParameter. Witch widget named this is relative to.
+ * @returns {string}
+ */
+ getRelativeToWidgetName: function () {
+ return this._relativeWidgetName;
+ },
+
+ /**
+ * Sets a name in Relative Layout for LayoutParameter.
+ * @param {String} name
+ */
+ setRelativeName: function (name) {
+ this._relativeLayoutName = name;
+ },
+
+ /**
+ * Gets a name in Relative Layout of LayoutParameter.
+ * @returns {string}
+ */
+ getRelativeName: function () {
+ return this._relativeLayoutName;
+ },
+
+ _createCloneInstance:function(){
+ return new ccui.RelativeLayoutParameter();
+ },
+
+ _copyProperties:function(model){
+ ccui.LayoutParameter.prototype._copyProperties.call(this, model);
+ if (model instanceof ccui.RelativeLayoutParameter) {
+ this.setAlign(model._relativeAlign);
+ this.setRelativeToWidgetName(model._relativeWidgetName);
+ this.setRelativeName(model._relativeLayoutName);
+ }
+ }
+});
+
+/**
+ * Allocates and initializes a RelativeLayoutParameter.
+ * @function
+ * @deprecated since v3.0, please use new ccui.RelativeLayoutParameter() instead.
+ * @return {ccui.RelativeLayoutParameter}
+ */
+ccui.RelativeLayoutParameter.create = function () {
+ return new ccui.RelativeLayoutParameter();
+};
+
+// Constants
+//Relative layout parameter RelativeAlign
+/**
+ * The none of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.NONE = 0;
+/**
+ * The parent's top left of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_TOP_LEFT = 1;
+/**
+ * The parent's top center horizontal of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_TOP_CENTER_HORIZONTAL = 2;
+/**
+ * The parent's top right of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_TOP_RIGHT = 3;
+/**
+ * The parent's left center vertical of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_LEFT_CENTER_VERTICAL = 4;
+
+/**
+ * The center in parent of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.CENTER_IN_PARENT = 5;
+
+/**
+ * The parent's right center vertical of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_RIGHT_CENTER_VERTICAL = 6;
+/**
+ * The parent's left bottom of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_LEFT_BOTTOM = 7;
+/**
+ * The parent's bottom center horizontal of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_BOTTOM_CENTER_HORIZONTAL = 8;
+/**
+ * The parent's right bottom of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.PARENT_RIGHT_BOTTOM = 9;
+
+/**
+ * The location above left align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_ABOVE_LEFTALIGN = 10;
+/**
+ * The location above center of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_ABOVE_CENTER = 11;
+/**
+ * The location above right align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_ABOVE_RIGHTALIGN = 12;
+/**
+ * The location left of top align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_TOPALIGN = 13;
+/**
+ * The location left of center of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_CENTER = 14;
+/**
+ * The location left of bottom align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_LEFT_OF_BOTTOMALIGN = 15;
+/**
+ * The location right of top align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_TOPALIGN = 16;
+/**
+ * The location right of center of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_CENTER = 17;
+/**
+ * The location right of bottom align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_RIGHT_OF_BOTTOMALIGN = 18;
+/**
+ * The location below left align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_BELOW_LEFTALIGN = 19;
+/**
+ * The location below center of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_BELOW_CENTER = 20;
+/**
+ * The location below right align of ccui.RelativeLayoutParameter's relative align.
+ * @constant
+ * @type {number}
+ */
+ccui.RelativeLayoutParameter.LOCATION_BELOW_RIGHTALIGN = 21;
+
+/**
+ * @ignore
+ */
+ccui.LINEAR_GRAVITY_NONE = 0;
+ccui.LINEAR_GRAVITY_LEFT = 1;
+ccui.LINEAR_GRAVITY_TOP = 2;
+ccui.LINEAR_GRAVITY_RIGHT = 3;
+ccui.LINEAR_GRAVITY_BOTTOM = 4;
+ccui.LINEAR_GRAVITY_CENTER_VERTICAL = 5;
+ccui.LINEAR_GRAVITY_CENTER_HORIZONTAL = 6;
+
+//RelativeAlign
+ccui.RELATIVE_ALIGN_NONE = 0;
+ccui.RELATIVE_ALIGN_PARENT_TOP_LEFT = 1;
+ccui.RELATIVE_ALIGN_PARENT_TOP_CENTER_HORIZONTAL = 2;
+ccui.RELATIVE_ALIGN_PARENT_TOP_RIGHT = 3;
+ccui.RELATIVE_ALIGN_PARENT_LEFT_CENTER_VERTICAL = 4;
+ccui.RELATIVE_ALIGN_PARENT_CENTER = 5;
+ccui.RELATIVE_ALIGN_PARENT_RIGHT_CENTER_VERTICAL = 6;
+ccui.RELATIVE_ALIGN_PARENT_LEFT_BOTTOM = 7;
+ccui.RELATIVE_ALIGN_PARENT_BOTTOM_CENTER_HORIZONTAL = 8;
+ccui.RELATIVE_ALIGN_PARENT_RIGHT_BOTTOM = 9;
+
+ccui.RELATIVE_ALIGN_LOCATION_ABOVE_LEFT = 10;
+ccui.RELATIVE_ALIGN_LOCATION_ABOVE_CENTER = 11;
+ccui.RELATIVE_ALIGN_LOCATION_ABOVE_RIGHT = 12;
+
+ccui.RELATIVE_ALIGN_LOCATION_LEFT_TOP = 13;
+ccui.RELATIVE_ALIGN_LOCATION_LEFT_CENTER = 14;
+ccui.RELATIVE_ALIGN_LOCATION_LEFT_BOTTOM = 15;
+
+ccui.RELATIVE_ALIGN_LOCATION_RIGHT_TOP = 16;
+ccui.RELATIVE_ALIGN_LOCATION_RIGHT_CENTER = 17;
+ccui.RELATIVE_ALIGN_LOCATION_RIGHT_BOTTOM = 18;
+
+ccui.RELATIVE_ALIGN_LOCATION_BELOW_TOP = 19;
+ccui.RELATIVE_ALIGN_LOCATION_BELOW_CENTER = 20;
+ccui.RELATIVE_ALIGN_LOCATION_BELOW_BOTTOM = 21;
\ No newline at end of file
diff --git a/extensions/ccui/layouts/UILayoutWebGLRenderCmd.js b/extensions/ccui/layouts/UILayoutWebGLRenderCmd.js
new file mode 100644
index 0000000000..e83dc0c765
--- /dev/null
+++ b/extensions/ccui/layouts/UILayoutWebGLRenderCmd.js
@@ -0,0 +1,204 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ if (!ccui.ProtectedNode.WebGLRenderCmd)
+ return;
+ ccui.Layout.WebGLRenderCmd = function (renderable) {
+ this._pNodeCmdCtor(renderable);
+ this._needDraw = false;
+
+ this._currentStencilEnabled = 0;
+ this._scissorOldState = false;
+ this._clippingOldRect = null;
+
+ this._mask_layer_le = 0;
+
+ this._beforeVisitCmdStencil = null;
+ this._afterDrawStencilCmd = null;
+ this._afterVisitCmdStencil = null;
+ this._beforeVisitCmdScissor = null;
+ this._afterVisitCmdScissor = null;
+ };
+
+ var proto = ccui.Layout.WebGLRenderCmd.prototype = Object.create(ccui.ProtectedNode.WebGLRenderCmd.prototype);
+ proto.constructor = ccui.Layout.WebGLRenderCmd;
+ proto._layoutCmdCtor = ccui.Layout.CanvasRenderCmd;
+
+ proto._syncStatus = function (parentCmd) {
+ this._originSyncStatus(parentCmd);
+
+ if (parentCmd && (parentCmd._dirtyFlag & cc.Node._dirtyFlags.transformDirty))
+ this._node._clippingRectDirty = true;
+ };
+
+ proto._onBeforeVisitStencil = function (ctx) {
+ var gl = ctx || cc._renderContext;
+
+ ccui.Layout.WebGLRenderCmd._layer++;
+
+ var mask_layer = 0x1 << ccui.Layout.WebGLRenderCmd._layer;
+ var mask_layer_l = mask_layer - 1;
+ this._mask_layer_le = mask_layer | mask_layer_l;
+
+ // manually save the stencil state
+ this._currentStencilEnabled = gl.isEnabled(gl.STENCIL_TEST);
+
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ gl.enable(gl.STENCIL_TEST);
+
+ gl.depthMask(false);
+
+ gl.stencilFunc(gl.NEVER, mask_layer, mask_layer);
+ gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP);
+
+ gl.stencilMask(mask_layer);
+ gl.clear(gl.STENCIL_BUFFER_BIT);
+ };
+
+ proto._onAfterDrawStencil = function (ctx) {
+ var gl = ctx || cc._renderContext;
+ gl.depthMask(true);
+ gl.stencilFunc(gl.EQUAL, this._mask_layer_le, this._mask_layer_le);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+ };
+
+ proto._onAfterVisitStencil = function (ctx) {
+ var gl = ctx || cc._renderContext;
+
+ ccui.Layout.WebGLRenderCmd._layer--;
+
+ if (this._currentStencilEnabled) {
+ var mask_layer = 0x1 << ccui.Layout.WebGLRenderCmd._layer;
+ var mask_layer_l = mask_layer - 1;
+ var mask_layer_le = mask_layer | mask_layer_l;
+
+ gl.stencilMask(mask_layer);
+ gl.stencilFunc(gl.EQUAL, mask_layer_le, mask_layer_le);
+ }
+ else {
+ gl.disable(gl.STENCIL_TEST);
+ }
+ };
+
+ proto._onBeforeVisitScissor = function (ctx) {
+ this._node._clippingRectDirty = true;
+ var clippingRect = this._node._getClippingRect();
+ var gl = ctx || cc._renderContext;
+
+ this._scissorOldState = gl.isEnabled(gl.SCISSOR_TEST);
+
+ if (!this._scissorOldState) {
+ gl.enable(gl.SCISSOR_TEST);
+ cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
+ }
+ else {
+ this._clippingOldRect = cc.view.getScissorRect();
+ if (!cc.rectEqualToRect(this._clippingOldRect, clippingRect))
+ cc.view.setScissorInPoints(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height);
+ }
+ };
+
+ proto._onAfterVisitScissor = function (ctx) {
+ var gl = ctx || cc._renderContext;
+ if (this._scissorOldState) {
+ if (!cc.rectEqualToRect(this._clippingOldRect, this._node._clippingRect)) {
+ cc.view.setScissorInPoints(this._clippingOldRect.x,
+ this._clippingOldRect.y,
+ this._clippingOldRect.width,
+ this._clippingOldRect.height);
+ }
+ }
+ else {
+ gl.disable(gl.SCISSOR_TEST);
+ }
+ };
+
+ proto.rebindStencilRendering = function (stencil) {
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ var node = this._node;
+ this.pNodeTransform(parentCmd, recursive);
+ if (node._clippingStencil)
+ node._clippingStencil._renderCmd.transform(this, recursive);
+ };
+
+ proto.stencilClippingVisit = function (parentCmd) {
+ var node = this._node;
+ if (!node._clippingStencil || !node._clippingStencil.isVisible())
+ return;
+
+ // all the _stencilBits are in use?
+ if (ccui.Layout.WebGLRenderCmd._layer + 1 === cc.stencilBits) {
+ // warn once
+ ccui.Layout.WebGLRenderCmd._visit_once = true;
+ if (ccui.Layout.WebGLRenderCmd._visit_once) {
+ cc.log("Nesting more than " + cc.stencilBits + "stencils is not supported. Everything will be drawn without stencil for this node and its childs.");
+ ccui.Layout.WebGLRenderCmd._visit_once = false;
+ }
+ // draw everything, as if there where no stencil
+ return;
+ }
+
+ if (!this._beforeVisitCmdStencil) {
+ this._beforeVisitCmdStencil = new cc.CustomRenderCmd(this, this._onBeforeVisitStencil);
+ this._afterDrawStencilCmd = new cc.CustomRenderCmd(this, this._onAfterDrawStencil);
+ this._afterVisitCmdStencil = new cc.CustomRenderCmd(this, this._onAfterVisitStencil);
+ }
+
+ cc.renderer.pushRenderCommand(this._beforeVisitCmdStencil);
+
+ //optimize performance for javascript
+ var currentStack = cc.current_stack;
+ currentStack.stack.push(currentStack.top);
+ currentStack.top = this._stackMatrix;
+
+ node._clippingStencil.visit(this);
+
+ cc.renderer.pushRenderCommand(this._afterDrawStencilCmd);
+ };
+
+ proto.postStencilVisit = function () {
+ renderer.pushRenderCommand(cmd._afterVisitCmdStencil);
+ cc.current_stack.top = cc.current_stack.stack.pop();
+ };
+
+ proto.scissorClippingVisit = function (parentCmd) {
+ if (!this._beforeVisitCmdScissor) {
+ this._beforeVisitCmdScissor = new cc.CustomRenderCmd(this, this._onBeforeVisitScissor);
+ this._afterVisitCmdScissor = new cc.CustomRenderCmd(this, this._onAfterVisitScissor);
+ }
+ cc.renderer.pushRenderCommand(this._beforeVisitCmdScissor);
+ };
+
+ proto.postScissorVisit = function () {
+ cc.renderer.pushRenderCommand(this._afterVisitCmdScissor);
+ };
+
+ ccui.Layout.WebGLRenderCmd._layer = -1;
+ ccui.Layout.WebGLRenderCmd._visit_once = null;
+})();
diff --git a/extensions/CocoStudio/Components/CCComRender.js b/extensions/ccui/layouts/UIRelativeBox.js
similarity index 61%
rename from extensions/CocoStudio/Components/CCComRender.js
rename to extensions/ccui/layouts/UIRelativeBox.js
index 899dfdb8c5..064be6ecb3 100644
--- a/extensions/CocoStudio/Components/CCComRender.js
+++ b/extensions/ccui/layouts/UIRelativeBox.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -23,40 +24,32 @@
****************************************************************************/
/**
- * Base class for cc.ComRender
+ * The Relative box for Cocos UI layout. Its layout type is ccui.Layout.RELATIVE.
* @class
- * @extends cc.Component
+ * @extends ccui.Layout
*/
-cc.ComRender = cc.Component.extend({
- _render: null,
- ctor: function (node, comName) {
- cc.Component.prototype.ctor.call(this);
- this._render = node;
- this._name = comName;
- },
-
- onEnter: function () {
- if (this._owner != null) {
- this._owner.addChild(this._render);
+ccui.RelativeBox = ccui.Layout.extend(/** @lends ccui.RelativeBox# */{
+ /**
+ * The constructor of ccui.RelativeBox
+ * @function
+ * @param {cc.Size} [size]
+ */
+ ctor: function(size){
+ ccui.Layout.prototype.ctor.call(this);
+ this.setLayoutType(ccui.Layout.RELATIVE);
+
+ if(size) {
+ this.setContentSize(size);
}
- },
-
- onExit: function () {
- this._render = null;
- },
-
- getNode: function () {
- return this._render;
- },
-
- setNode: function (node) {
- this._render = node;
}
});
-cc.ComRender.create = function (node, comName) {
- var com = new cc.ComRender(node, comName);
- if (com && com.init()) {
- return com;
- }
- return null;
-};
+
+/**
+ * Creates a relative box
+ * @deprecated since v3.0, please use new ccui.RelativeBox(size) instead.
+ * @param {cc.Size} size
+ * @returns {ccui.RelativeBox}
+ */
+ccui.RelativeBox.create = function(size){
+ return new ccui.RelativeBox(size);
+};
\ No newline at end of file
diff --git a/extensions/ccui/layouts/UIVBox.js b/extensions/ccui/layouts/UIVBox.js
new file mode 100644
index 0000000000..d6888befbb
--- /dev/null
+++ b/extensions/ccui/layouts/UIVBox.js
@@ -0,0 +1,67 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The vertical box of Cocos UI. Its layout type is ccui.Layout.LINEAR_VERTICAL.
+ * @class
+ * @extends ccui.Layout
+ */
+ccui.VBox = ccui.Layout.extend(/** @lends ccui.VBox# */{
+ /**
+ * The constructor of ccui.VBox
+ * @function
+ * @param {cc.Size} size
+ */
+ ctor: function(size){
+ ccui.Layout.prototype.ctor.call(this);
+ this.setLayoutType(ccui.Layout.LINEAR_VERTICAL);
+
+ if (size) {
+ this.setContentSize(size);
+ }
+ },
+
+ /**
+ * Initializes a VBox with size.
+ * @param {cc.Size} size
+ * @returns {boolean}
+ */
+ initWithSize: function(size){
+ if(this.init()){
+
+ return true;
+ }
+ return false;
+ }
+});
+
+/**
+ * Creates a VBox
+ * @param {cc.Size} size
+ * @returns {ccui.VBox}
+ */
+ccui.VBox.create = function(size){
+ return new ccui.VBox(size);
+};
\ No newline at end of file
diff --git a/extensions/ccui/system/CocosGUI.js b/extensions/ccui/system/CocosGUI.js
new file mode 100644
index 0000000000..30622d0c97
--- /dev/null
+++ b/extensions/ccui/system/CocosGUI.js
@@ -0,0 +1,62 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The namespace of Cocos UI
+ * @namespace
+ * @name ccui
+ */
+var ccui = ccui || {};
+
+//These classes defines are use for jsDoc
+/**
+ * The same as cc.Class
+ * @class
+ */
+ccui.Class = ccui.Class || cc.Class;
+ccui.Class.extend = ccui.Class.extend || cc.Class.extend;
+
+/**
+ * that same as cc.Node
+ * @class
+ * @extends ccui.Class
+ */
+ccui.Node = ccui.Node || cc.Node;
+ccui.Node.extend = ccui.Node.extend || cc.Node.extend;
+
+
+/**
+ * that same as cc.Node
+ * @class
+ * @extends ccui.Node
+ */
+ccui.ProtectedNode = ccui.ProtectedNode || cc.ProtectedNode;
+ccui.ProtectedNode.extend = ccui.ProtectedNode.extend || cc.ProtectedNode.extend;
+
+/**
+ * Cocos UI version
+ * @type {String}
+ */
+ccui.cocosGUIVersion = "CocosGUI v1.0.0.0";
\ No newline at end of file
diff --git a/extensions/ccui/system/UIHelper.js b/extensions/ccui/system/UIHelper.js
new file mode 100644
index 0000000000..327bf8dca6
--- /dev/null
+++ b/extensions/ccui/system/UIHelper.js
@@ -0,0 +1,179 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//todo maybe need change here
+
+
+/**
+ * ccui.helper is the singleton object which is the Helper object contains some functions for seek widget
+ * @class
+ * @name ccui.helper
+ */
+ccui.helper = {
+ /**
+ * Finds a widget whose tag equals to param tag from root widget.
+ * @param {ccui.Widget} root
+ * @param {number} tag
+ * @returns {ccui.Widget}
+ */
+ seekWidgetByTag: function (root, tag) {
+ if (!root)
+ return null;
+ if (root.getTag() === tag)
+ return root;
+
+ var arrayRootChildren = root.getChildren();
+ var length = arrayRootChildren.length;
+ for (var i = 0; i < length; i++) {
+ var child = arrayRootChildren[i];
+ var res = ccui.helper.seekWidgetByTag(child, tag);
+ if (res !== null)
+ return res;
+ }
+ return null;
+ },
+
+ /**
+ * Finds a widget whose name equals to param name from root widget.
+ * @param {ccui.Widget} root
+ * @param {String} name
+ * @returns {ccui.Widget}
+ */
+ seekWidgetByName: function (root, name) {
+ if (!root)
+ return null;
+ if (root.getName() === name)
+ return root;
+ var arrayRootChildren = root.getChildren();
+ var length = arrayRootChildren.length;
+ for (var i = 0; i < length; i++) {
+ var child = arrayRootChildren[i];
+ var res = ccui.helper.seekWidgetByName(child, name);
+ if (res !== null)
+ return res;
+ }
+ return null;
+ },
+
+ /**
+ * Finds a widget whose name equals to param name from root widget.
+ * RelativeLayout will call this method to find the widget witch is needed.
+ * @param {ccui.Widget} root
+ * @param {String} name
+ * @returns {ccui.Widget}
+ */
+ seekWidgetByRelativeName: function (root, name) {
+ if (!root)
+ return null;
+ var arrayRootChildren = root.getChildren();
+ var length = arrayRootChildren.length;
+ for (var i = 0; i < length; i++) {
+ var child = arrayRootChildren[i];
+ var layoutParameter = child.getLayoutParameter(ccui.LayoutParameter.RELATIVE);
+ if (layoutParameter && layoutParameter.getRelativeName() === name)
+ return child;
+ }
+ return null;
+ },
+
+ /**
+ * Finds a widget whose action tag equals to param name from root widget.
+ * @param {ccui.Widget} root
+ * @param {Number} tag
+ * @returns {ccui.Widget}
+ */
+ seekActionWidgetByActionTag: function (root, tag) {
+ if (!root)
+ return null;
+ if (root.getActionTag() === tag)
+ return root;
+ var arrayRootChildren = root.getChildren();
+ for (var i = 0; i < arrayRootChildren.length; i++) {
+ var child = arrayRootChildren[i];
+ var res = ccui.helper.seekActionWidgetByActionTag(child, tag);
+ if (res !== null)
+ return res;
+ }
+ return null;
+ },
+
+ _activeLayout: true,
+ /**
+ * Refresh object and it's children layout state
+ * @param {cc.Node} rootNode
+ */
+ doLayout: function (rootNode) {
+ if (!this._activeLayout)
+ return;
+ var children = rootNode.getChildren(), node;
+ for(var i = 0, len = children.length;i < len; i++) {
+ node = children[i];
+ var com = node.getComponent(ccui.LayoutComponent.NAME);
+ var parent = node.getParent();
+ if (null != com && null !== parent && com.refreshLayout)
+ com.refreshLayout();
+ }
+ },
+
+ changeLayoutSystemActiveState: function (active) {
+ this._activeLayout = active;
+ },
+
+ /**
+ * restrict capInsetSize, when the capInsets' width is larger than the textureSize, it will restrict to 0,
+ * the height goes the same way as width.
+ * @param {cc.Rect} capInsets
+ * @param {cc.Size} textureSize
+ */
+ restrictCapInsetRect: function (capInsets, textureSize) {
+ var x = capInsets.x, y = capInsets.y;
+ var width = capInsets.width, height = capInsets.height;
+
+ if (textureSize.width < width) {
+ x = 0.0;
+ width = 0.0;
+ }
+ if (textureSize.height < height) {
+ y = 0.0;
+ height = 0.0;
+ }
+ return cc.rect(x, y, width, height);
+ },
+
+ _createSpriteFromBase64: function (base64String, key) {
+ var texture2D = cc.textureCache.getTextureForKey(key);
+
+ if (!texture2D) {
+ var image = new Image();
+ image.src = base64String;
+ cc.textureCache.cacheImage(key, image);
+ texture2D = cc.textureCache.getTextureForKey(key);
+ }
+
+ var sprite = new cc.Sprite(texture2D);
+
+ return sprite;
+ }
+};
diff --git a/extensions/ccui/uiwidgets/UIButton.js b/extensions/ccui/uiwidgets/UIButton.js
new file mode 100644
index 0000000000..4741e2e767
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UIButton.js
@@ -0,0 +1,857 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2015-2016 zilongshanren
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The button controls of Cocos UI.
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {String} titleText - The content string of the button title
+ * @property {String} titleFont - The content string font of the button title
+ * @property {Number} titleFontSize - The content string font size of the button title
+ * @property {String} titleFontName - The content string font name of the button title
+ * @property {cc.Color} titleColor - The content string font color of the button title
+ * @property {Boolean} pressedActionEnabled - Indicate whether button has zoom effect when clicked
+ */
+ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{
+ _buttonScale9Renderer: null,
+ _buttonNormalSpriteFrame: null,
+ _buttonClickedSpriteFrame: null,
+ _buttonDisableSpriteFrame: null,
+ _titleRenderer: null,
+
+ _normalFileName: "",
+ _clickedFileName: "",
+ _disabledFileName: "",
+
+ _prevIgnoreSize: true,
+ _scale9Enabled: false,
+
+ _capInsetsNormal: null,
+
+ _normalTexType: ccui.Widget.LOCAL_TEXTURE,
+ _pressedTexType: ccui.Widget.LOCAL_TEXTURE,
+ _disabledTexType: ccui.Widget.LOCAL_TEXTURE,
+
+ _normalTextureSize: null,
+
+ pressedActionEnabled: false,
+ _titleColor: null,
+
+ _zoomScale: 0.1,
+
+ _normalTextureLoaded: false,
+ _pressedTextureLoaded: false,
+ _disabledTextureLoaded: false,
+
+ _className: "Button",
+ _normalTextureAdaptDirty: true,
+
+ _fontName: "Thonburi",
+ _fontSize: 12,
+ _type: 0,
+
+ /**
+ * Allocates and initializes a UIButton.
+ * Constructor of ccui.Button. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {String} normalImage
+ * @param {String} [selectedImage=""]
+ * @param {String} [disableImage=""]
+ * @param {Number} [texType=ccui.Widget.LOCAL_TEXTURE]
+ * @example
+ * // example
+ * var uiButton = new ccui.Button();
+ */
+ ctor: function (normalImage, selectedImage, disableImage, texType) {
+ this._capInsetsNormal = cc.rect(0, 0, 0, 0);
+ this._normalTextureSize = cc.size(0, 0);
+ ccui.Widget.prototype.ctor.call(this);
+ this.setTouchEnabled(true);
+
+ this._normalLoader = new cc.Sprite.LoadManager();
+ this._clickedLoader = new cc.Sprite.LoadManager();
+ this._disabledLoader = new cc.Sprite.LoadManager();
+
+ if (normalImage) {
+ this.loadTextures(normalImage, selectedImage,disableImage, texType);
+ }
+ },
+
+ _createTitleRendererIfNeeded: function ( ) {
+ if(!this._titleRenderer) {
+ this._titleRenderer = new cc.LabelTTF("");
+ this._titleRenderer.setAnchorPoint(0.5, 0.5);
+ this._titleColor = cc.color.WHITE;
+ this._titleRenderer.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
+ this.addProtectedChild(this._titleRenderer, ccui.Button.TITLE_RENDERER_ZORDER, -1);
+ }
+ },
+
+ _initRenderer: function () {
+ this._buttonScale9Renderer = new ccui.Scale9Sprite();
+
+ this._buttonScale9Renderer.setRenderingType(ccui.Scale9Sprite.RenderingType.SIMPLE);
+
+ this.addProtectedChild(this._buttonScale9Renderer, ccui.Button.DISABLED_RENDERER_ZORDER, -1);
+ },
+
+ /**
+ * Sets if button is using scale9 renderer.
+ * @param {Boolean} able true that using scale9 renderer, false otherwise.
+ */
+ setScale9Enabled: function (able) {
+ if (this._scale9Enabled === able)
+ return;
+
+ this._brightStyle = ccui.Widget.BRIGHT_STYLE_NONE;
+ this._scale9Enabled = able;
+
+ if (this._scale9Enabled) {
+ this._buttonScale9Renderer.setRenderingType(ccui.Scale9Sprite.RenderingType.SLICED);
+ } else {
+ this._buttonScale9Renderer.setRenderingType(ccui.Scale9Sprite.RenderingType.SIMPLE);
+ }
+
+ if (this._scale9Enabled) {
+ var ignoreBefore = this._ignoreSize;
+ this.ignoreContentAdaptWithSize(false);
+ this._prevIgnoreSize = ignoreBefore;
+ } else {
+ this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
+ }
+ this.setCapInsets(this._capInsetsNormal);
+
+ this.setBright(this._bright);
+
+ this._normalTextureAdaptDirty = true;
+ },
+
+ /**
+ * Returns button is using scale9 renderer or not.
+ * @returns {Boolean}
+ */
+ isScale9Enabled: function () {
+ return this._scale9Enabled;
+ },
+
+ /**
+ * Sets whether ignore the widget size
+ * @param {Boolean} ignore true that widget will ignore it's size, use texture size, false otherwise. Default value is true.
+ * @override
+ */
+ ignoreContentAdaptWithSize: function (ignore) {
+ if(this._unifySize){
+ this._updateContentSize();
+ return;
+ }
+ if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
+ ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
+ this._prevIgnoreSize = ignore;
+ }
+ },
+
+ /**
+ * Returns the renderer size.
+ * @returns {cc.Size}
+ */
+ getVirtualRendererSize: function(){
+ if (this._unifySize)
+ return this._getNormalSize();
+
+ if (!this._normalTextureLoaded ) {
+ if(this._titleRenderer && this._titleRenderer.getString().length > 0) {
+ return this._titleRenderer.getContentSize();
+ }
+ }
+ return cc.size(this._normalTextureSize);
+ },
+
+ /**
+ * Load textures for button.
+ * @param {String} normal normal state of texture's filename.
+ * @param {String} selected selected state of texture's filename.
+ * @param {String} disabled disabled state of texture's filename.
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadTextures: function (normal, selected, disabled, texType) {
+ this.loadTextureNormal(normal, texType);
+ this.loadTexturePressed(selected, texType);
+ this.loadTextureDisabled(disabled, texType);
+ },
+
+ _createSpriteFrameWithFile: function (file) {
+ var texture = cc.textureCache.getTextureForKey(file);
+ if (!texture) {
+ texture = cc.textureCache.addImage(file);
+ }
+ if(!texture._textureLoaded) {
+ return texture;
+ }
+
+ var textureSize = texture.getContentSize();
+ var rect = cc.rect(0, 0, textureSize.width, textureSize.height);
+ return new cc.SpriteFrame(texture, rect);
+ },
+
+ _createSpriteFrameWithName: function (name) {
+ var frame = cc.spriteFrameCache.getSpriteFrame(name);
+ if (frame == null) {
+ cc.log("ccui.Scale9Sprite.initWithSpriteFrameName(): can't find the sprite frame by spriteFrameName");
+ return null;
+ }
+
+ return frame;
+ },
+
+ /**
+ * Load normal state texture for button.
+ * @param {String} normal normal state of texture's filename.
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadTextureNormal: function (normal, texType) {
+ if (!normal) return;
+
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._normalFileName = normal;
+ this._normalTexType = texType;
+
+ var normalSpriteFrame;
+ switch (this._normalTexType){
+ case ccui.Widget.LOCAL_TEXTURE:
+ normalSpriteFrame = this._createSpriteFrameWithFile(normal);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ if (normal[0] === "#") {
+ normal = normal.substr(1, normal.length - 1);
+ }
+ normalSpriteFrame = this._createSpriteFrameWithName(normal);
+ break;
+ default:
+ break;
+ }
+
+ if(!normalSpriteFrame) {
+ return;
+ }
+
+ if(!normalSpriteFrame._textureLoaded) {
+ this._normalLoader.clear();
+ this._normalLoader.once(normalSpriteFrame, function () {
+ this.loadTextureNormal(this._normalFileName, this._normalTexType);
+ }, this);
+ return;
+ }
+
+ this._normalTextureLoaded = normalSpriteFrame._textureLoaded;
+ this._buttonNormalSpriteFrame = normalSpriteFrame;
+ this._buttonScale9Renderer.setSpriteFrame(normalSpriteFrame);
+ if (this._scale9Enabled){
+ this._buttonScale9Renderer.setCapInsets(this._capInsetsNormal);
+ }
+
+ // FIXME: https://github.com/cocos2d/cocos2d-x/issues/12249
+ if(!this._ignoreSize && cc.sizeEqualToSize(this._customSize, cc.size(0, 0))) {
+ this._customSize = this._buttonScale9Renderer.getContentSize();
+ }
+
+ this._normalTextureSize = this._buttonScale9Renderer.getContentSize();
+ this._updateChildrenDisplayedRGBA();
+ if (this._unifySize){
+ if (this._scale9Enabled){
+ this._buttonScale9Renderer.setCapInsets(this._capInsetsNormal);
+ this._updateContentSizeWithTextureSize(this._getNormalSize());
+ }
+ }else {
+ this._updateContentSizeWithTextureSize(this._normalTextureSize);
+ }
+
+ this._normalTextureAdaptDirty = true;
+ this._findLayout();
+ },
+
+ /**
+ * Load selected state texture for button.
+ * @param {String} selected selected state of texture's filename.
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadTexturePressed: function (selected, texType) {
+ if (!selected)
+ return;
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._clickedFileName = selected;
+ this._pressedTexType = texType;
+
+ var clickedSpriteFrame;
+ switch (this._pressedTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ clickedSpriteFrame = this._createSpriteFrameWithFile(selected);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ if (selected[0] === "#") {
+ selected = selected.substr(1, selected.length - 1);
+ }
+ clickedSpriteFrame = this._createSpriteFrameWithName(selected);
+ break;
+ default:
+ break;
+ }
+
+ if(!clickedSpriteFrame) return;
+
+ if(!clickedSpriteFrame._textureLoaded) {
+ this._clickedLoader.clear();
+ this._clickedLoader.once(clickedSpriteFrame, function () {
+ this.loadTexturePressed(this._clickedFileName, this._pressedTexType);
+ }, this);
+ return;
+ }
+
+ this._buttonClickedSpriteFrame = clickedSpriteFrame;
+ this._updateChildrenDisplayedRGBA();
+
+ this._pressedTextureLoaded = true;
+ },
+
+ /**
+ * Load dark state texture for button.
+ * @param {String} disabled disabled state of texture's filename.
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadTextureDisabled: function (disabled, texType) {
+ if (!disabled)
+ return;
+
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._disabledFileName = disabled;
+ this._disabledTexType = texType;
+
+ var disabledSpriteframe;
+ switch (this._disabledTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ disabledSpriteframe = this._createSpriteFrameWithFile(disabled);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ if (disabled[0] === "#") {
+ disabled = disabled.substr(1, disabled.length - 1);
+ }
+ disabledSpriteframe = this._createSpriteFrameWithName(disabled);
+ break;
+ default:
+ break;
+ }
+
+ if(!disabledSpriteframe) return;
+
+ if(!disabledSpriteframe._textureLoaded) {
+ this._disabledLoader.clear();
+ this._disabledLoader.once(disabledSpriteframe, function () {
+ this.loadTextureDisabled(this._disabledFileName, this._disabledTexType);
+ }, this);
+ return;
+ }
+
+ this._buttonDisableSpriteFrame = disabledSpriteframe;
+ this._updateChildrenDisplayedRGBA();
+
+ this._disabledTextureLoaded = true;
+ this._findLayout();
+ },
+
+ /**
+ * Sets capinsets for button, if button is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsets: function (capInsets) {
+ this.setCapInsetsNormalRenderer(capInsets);
+ },
+
+ /**
+ * Sets capinsets for button, if button is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsetsNormalRenderer: function (capInsets) {
+ if(!capInsets || !this._scale9Enabled)
+ return;
+
+ var x = capInsets.x, y = capInsets.y;
+ var width = capInsets.width, height = capInsets.height;
+ if (this._normalTextureSize.width < width){
+ x = 0;
+ width = 0;
+ }
+ if (this._normalTextureSize.height < height){
+ y = 0;
+ height = 0;
+ }
+
+ var locInsets = this._capInsetsNormal;
+ locInsets.x = x;
+ locInsets.y = y;
+ locInsets.width = width;
+ locInsets.height = height;
+
+ this._capInsetsNormal = locInsets;
+ this._buttonScale9Renderer.setCapInsets(locInsets);
+ },
+
+ /**
+ * Returns normal renderer cap insets.
+ * @returns {cc.Rect}
+ */
+ getCapInsetsNormalRenderer:function(){
+ return cc.rect(this._capInsetsNormal);
+ },
+
+ /**
+ * Sets capinsets for button, if button is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsetsPressedRenderer: function (capInsets) {
+ this.setCapInsetsNormalRenderer(capInsets);
+ },
+
+ /**
+ * Returns pressed renderer cap insets.
+ * @returns {cc.Rect}
+ */
+ getCapInsetsPressedRenderer: function () {
+ return cc.rect(this._capInsetsNormal);
+ },
+
+ /**
+ * Sets capinsets for button, if button is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsetsDisabledRenderer: function (capInsets) {
+ this.setCapInsetsNormalRenderer(capInsets);
+ },
+
+ /**
+ * Returns disable renderer cap insets.
+ * @returns {cc.Rect}
+ */
+ getCapInsetsDisabledRenderer: function () {
+ return cc.rect(this._capInsetsNormal);
+ },
+
+ _onPressStateChangedToNormal: function () {
+ this._buttonScale9Renderer.setSpriteFrame(this._buttonNormalSpriteFrame);
+
+ this._buttonScale9Renderer.setState( ccui.Scale9Sprite.state.NORMAL);
+
+ if (this._pressedTextureLoaded) {
+ if (this.pressedActionEnabled){
+ this._buttonScale9Renderer.stopAllActions();
+ this._buttonScale9Renderer.setScale(1.0);
+
+ if(this._titleRenderer) {
+ this._titleRenderer.stopAllActions();
+
+ if (this._unifySize){
+ var zoomTitleAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP, 1, 1);
+ this._titleRenderer.runAction(zoomTitleAction);
+ }else{
+ this._titleRenderer.setScaleX(1);
+ this._titleRenderer.setScaleY(1);
+ }
+ }
+
+ }
+ } else {
+ this._buttonScale9Renderer.stopAllActions();
+ this._buttonScale9Renderer.setScale(1.0);
+
+ if (this._scale9Enabled) {
+ this._buttonScale9Renderer.setColor(cc.color.WHITE);
+ }
+
+ if(this._titleRenderer) {
+ this._titleRenderer.stopAllActions();
+
+ this._titleRenderer.setScaleX(1);
+ this._titleRenderer.setScaleY(1);
+ }
+ }
+ },
+
+ _onPressStateChangedToPressed: function () {
+ this._buttonScale9Renderer.setState(ccui.Scale9Sprite.state.NORMAL);
+
+ if (this._pressedTextureLoaded) {
+ this._buttonScale9Renderer.setSpriteFrame(this._buttonClickedSpriteFrame);
+
+ if (this.pressedActionEnabled) {
+ this._buttonScale9Renderer.stopAllActions();
+
+ var zoomAction = cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP,
+ 1.0 + this._zoomScale,
+ 1.0 + this._zoomScale);
+ this._buttonScale9Renderer.runAction(zoomAction);
+
+ if(this._titleRenderer) {
+ this._titleRenderer.stopAllActions();
+ this._titleRenderer.runAction(cc.scaleTo(ccui.Button.ZOOM_ACTION_TIME_STEP,
+ 1 + this._zoomScale,
+ 1 + this._zoomScale));
+ }
+ }
+ } else {
+ this._buttonScale9Renderer.setSpriteFrame(this._buttonClickedSpriteFrame);
+
+ this._buttonScale9Renderer.stopAllActions();
+ this._buttonScale9Renderer.setScale(1.0 + this._zoomScale, 1.0 + this._zoomScale);
+
+ if (this._titleRenderer) {
+ this._titleRenderer.stopAllActions();
+ this._titleRenderer.setScaleX(1 + this._zoomScale);
+ this._titleRenderer.setScaleY(1 + this._zoomScale);
+ }
+ }
+ },
+
+ _onPressStateChangedToDisabled: function () {
+ //if disable resource is null
+ if (!this._disabledTextureLoaded){
+ if (this._normalTextureLoaded) {
+ this._buttonScale9Renderer.setState(ccui.Scale9Sprite.state.GRAY);
+ }
+ }else{
+ this._buttonScale9Renderer.setSpriteFrame(this._buttonDisableSpriteFrame);
+ }
+
+ this._buttonScale9Renderer.setScale(1.0);
+ },
+
+ _updateContentSize: function(){
+ if (this._unifySize){
+ if (this._scale9Enabled)
+ ccui.ProtectedNode.setContentSize(this._customSize);
+ else{
+ var s = this._getNormalSize();
+ ccui.ProtectedNode.setContentSize(s);
+ }
+ this._onSizeChanged();
+ return;
+ }
+
+ if (this._ignoreSize)
+ this.setContentSize(this.getVirtualRendererSize());
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ if(this._titleRenderer) {
+ this._updateTitleLocation();
+ }
+ this._normalTextureAdaptDirty = true;
+ },
+
+ /**
+ * Gets the Virtual Renderer of widget.
+ * @returns {cc.Node}
+ */
+ getVirtualRenderer: function () {
+ return this._buttonScale9Renderer;
+ },
+
+ _normalTextureScaleChangedWithSize: function () {
+ this._buttonScale9Renderer.setContentSize(this._contentSize);
+ this._buttonScale9Renderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
+ },
+
+ _adaptRenderers: function(){
+ if (this._normalTextureAdaptDirty) {
+ this._normalTextureScaleChangedWithSize();
+ this._normalTextureAdaptDirty = false;
+ }
+ },
+
+ _updateTitleLocation: function(){
+ this._titleRenderer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
+ },
+
+ /**
+ * Changes if button can be clicked zoom effect.
+ * @param {Boolean} enabled
+ */
+ setPressedActionEnabled: function (enabled) {
+ this.pressedActionEnabled = enabled;
+ },
+
+ /**
+ * Sets title text to ccui.Button
+ * @param {String} text
+ */
+ setTitleText: function (text) {
+ if(text === this.getTitleText()) return;
+
+ this._createTitleRendererIfNeeded();
+
+ this._titleRenderer.setString(text);
+ if (this._ignoreSize){
+ var s = this.getVirtualRendererSize();
+ this.setContentSize(s);
+ }else{
+ this._titleRenderer._renderCmd._updateTTF();
+ }
+ },
+
+ /**
+ * Returns title text of ccui.Button
+ * @returns {String} text
+ */
+ getTitleText: function () {
+ if(this._titleRenderer) {
+ return this._titleRenderer.getString();
+ }
+ return "";
+ },
+
+ /**
+ * Sets title color to ccui.Button.
+ * @param {cc.Color} color
+ */
+ setTitleColor: function (color) {
+ this._createTitleRendererIfNeeded();
+ this._titleRenderer.setFontFillColor(color);
+ },
+
+ /**
+ * Returns title color of ccui.Button
+ * @returns {cc.Color}
+ */
+ getTitleColor: function () {
+ if (this._titleRenderer) {
+ return this._titleRenderer._getFillStyle();
+ }
+ return cc.color.WHITE;
+ },
+
+ /**
+ * Sets title fontSize to ccui.Button
+ * @param {cc.Size} size
+ */
+ setTitleFontSize: function (size) {
+ this._createTitleRendererIfNeeded();
+
+ this._titleRenderer.setFontSize(size);
+ this._fontSize = size;
+ },
+
+ /**
+ * Returns title fontSize of ccui.Button.
+ * @returns {Number}
+ */
+ getTitleFontSize: function () {
+ if (this._titleRenderer) {
+ return this._titleRenderer.getFontSize();
+ }
+ return this._fontSize;
+ },
+
+ /**
+ * When user pressed the button, the button will zoom to a scale.
+ * The final scale of the button equals (button original scale + _zoomScale)
+ * @since v3.2
+ * @param scale
+ */
+ setZoomScale: function(scale){
+ this._zoomScale = scale;
+ },
+
+ /**
+ * Returns a zoom scale
+ * @since v3.2
+ * @returns {number}
+ */
+ getZoomScale: function(){
+ return this._zoomScale;
+ },
+
+ /**
+ * Returns the normalize of texture size
+ * @since v3.3
+ * @returns {cc.Size}
+ */
+ getNormalTextureSize: function(){
+ return this._normalTextureSize;
+ },
+
+ /**
+ * Sets title fontName to ccui.Button.
+ * @param {String} fontName
+ */
+ setTitleFontName: function (fontName) {
+ this._createTitleRendererIfNeeded();
+
+ this._titleRenderer.setFontName(fontName);
+ this._fontName = fontName;
+ },
+
+ /**
+ * Get the title renderer.
+ * title ttf object.
+ * @returns {cc.LabelTTF}
+ */
+ getTitleRenderer: function(){
+ return this._titleRenderer;
+ },
+
+ /**
+ * Gets title fontName of ccui.Button.
+ * @returns {String}
+ */
+ getTitleFontName: function () {
+ if(this._titleRenderer) {
+ return this._titleRenderer.getFontName();
+ }
+ return this._fontName;
+ },
+
+ _setTitleFont: function (font) {
+ this._titleRenderer.font = font;
+ },
+ _getTitleFont: function () {
+ return this._titleRenderer.font;
+ },
+
+ /**
+ * Returns the "class name" of widget.
+ * @override
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "Button";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.Button();
+ },
+
+ _copySpecialProperties: function (uiButton) {
+ this._prevIgnoreSize = uiButton._prevIgnoreSize;
+ this._capInsetsNormal = uiButton._capInsetsNormal;
+ this.setScale9Enabled(uiButton._scale9Enabled);
+
+ this.loadTextureNormal(uiButton._normalFileName, uiButton._normalTexType);
+ this.loadTexturePressed(uiButton._clickedFileName, uiButton._pressedTexType);
+ this.loadTextureDisabled(uiButton._disabledFileName, uiButton._disabledTexType);
+
+ if(uiButton._titleRenderer && uiButton._titleRenderer._string) {
+ this.setTitleText(uiButton.getTitleText());
+ this.setTitleFontName(uiButton.getTitleFontName());
+ this.setTitleFontSize(uiButton.getTitleFontSize());
+ this.setTitleColor(uiButton.getTitleColor());
+ }
+ this.setPressedActionEnabled(uiButton.pressedActionEnabled);
+ this.setZoomScale(uiButton._zoomScale);
+ },
+
+ _getNormalSize: function(){
+ var titleSize;
+ if (this._titleRenderer !== null)
+ titleSize = this._titleRenderer.getContentSize();
+
+ var imageSize = this._buttonScale9Renderer.getContentSize();
+ var width = titleSize.width > imageSize.width ? titleSize.width : imageSize.width;
+ var height = titleSize.height > imageSize.height ? titleSize.height : imageSize.height;
+
+ return cc.size(width,height);
+ }
+});
+
+var _p = ccui.Button.prototype;
+
+// Extended properties
+/** @expose */
+_p.titleText;
+cc.defineGetterSetter(_p, "titleText", _p.getTitleText, _p.setTitleText);
+/** @expose */
+_p.titleFont;
+cc.defineGetterSetter(_p, "titleFont", _p._getTitleFont, _p._setTitleFont);
+/** @expose */
+_p.titleFontSize;
+cc.defineGetterSetter(_p, "titleFontSize", _p.getTitleFontSize, _p.setTitleFontSize);
+/** @expose */
+_p.titleFontName;
+cc.defineGetterSetter(_p, "titleFontName", _p.getTitleFontName, _p.setTitleFontName);
+/** @expose */
+_p.titleColor;
+cc.defineGetterSetter(_p, "titleColor", _p.getTitleColor, _p.setTitleColor);
+
+_p = null;
+
+/**
+ * allocates and initializes a UIButton.
+ * @deprecated since v3.0, please use new ccui.Button() instead.
+ * @param {string} [normalImage] normal state texture name
+ * @param {string} [selectedImage] selected state texture name
+ * @param {string} [disableImage] disabled state texture name
+ * @param {string} [texType]
+ * @return {ccui.Button}
+ */
+ccui.Button.create = function (normalImage, selectedImage, disableImage, texType) {
+ return new ccui.Button(normalImage, selectedImage, disableImage, texType);
+};
+
+// Constants
+/**
+ * The normal renderer's zOrder value of ccui.Button.
+ * @constant
+ * @type {number}
+ */
+ccui.Button.NORMAL_RENDERER_ZORDER = -2;
+/**
+ * The pressed renderer's zOrder value ccui.Button.
+ * @constant
+ * @type {number}
+ */
+ccui.Button.PRESSED_RENDERER_ZORDER = -2;
+/**
+ * The disabled renderer's zOrder value of ccui.Button.
+ * @constant
+ * @type {number}
+ */
+ccui.Button.DISABLED_RENDERER_ZORDER = -2;
+/**
+ * The title renderer's zOrder value of ccui.Button.
+ * @constant
+ * @type {number}
+ */
+ccui.Button.TITLE_RENDERER_ZORDER = -1;
+
+/**
+ * the zoom action time step of ccui.Button
+ * @constant
+ * @type {number}
+ */
+ccui.Button.ZOOM_ACTION_TIME_STEP = 0.05;
+
+/**
+ * @ignore
+ */
+ccui.Button.SYSTEM = 0;
+ccui.Button.TTF = 1;
diff --git a/extensions/ccui/uiwidgets/UICheckBox.js b/extensions/ccui/uiwidgets/UICheckBox.js
new file mode 100644
index 0000000000..d76b4d560a
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UICheckBox.js
@@ -0,0 +1,722 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The CheckBox control of Cocos UI.
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {Boolean} selected - Indicate whether the check box has been selected
+ */
+ccui.CheckBox = ccui.Widget.extend(/** @lends ccui.CheckBox# */{
+ _backGroundBoxRenderer: null,
+ _backGroundSelectedBoxRenderer: null,
+ _frontCrossRenderer: null,
+ _backGroundBoxDisabledRenderer: null,
+ _frontCrossDisabledRenderer: null,
+
+ _isSelected: true,
+
+ _checkBoxEventListener: null,
+ _checkBoxEventSelector:null,
+
+ _backGroundTexType: ccui.Widget.LOCAL_TEXTURE,
+ _backGroundSelectedTexType: ccui.Widget.LOCAL_TEXTURE,
+ _frontCrossTexType: ccui.Widget.LOCAL_TEXTURE,
+ _backGroundDisabledTexType: ccui.Widget.LOCAL_TEXTURE,
+ _frontCrossDisabledTexType: ccui.Widget.LOCAL_TEXTURE,
+
+ _backGroundFileName: "",
+ _backGroundSelectedFileName: "",
+ _frontCrossFileName: "",
+ _backGroundDisabledFileName: "",
+ _frontCrossDisabledFileName: "",
+ _className: "CheckBox",
+
+ _zoomScale: 0.1,
+ _backgroundTextureScaleX: 0.1,
+ _backgroundTextureScaleY: 0.1,
+
+ _backGroundBoxRendererAdaptDirty:true,
+ _backGroundSelectedBoxRendererAdaptDirty:true,
+ _frontCrossRendererAdaptDirty: true,
+ _backGroundBoxDisabledRendererAdaptDirty: true,
+ _frontCrossDisabledRendererAdaptDirty: true,
+
+ /**
+ * allocates and initializes a UICheckBox.
+ * Constructor of ccui.CheckBox, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {String} backGround
+ * @param {String} backGroundSelected
+ * @param {String} cross
+ * @param {String} backGroundDisabled
+ * @param {String} frontCrossDisabled
+ * @param {Number} [texType=ccui.Widget.LOCAL_TEXTURE]
+ * @example
+ * // example
+ * var uiCheckBox = new ccui.CheckBox();
+ */
+ ctor: function (backGround, backGroundSelected,cross,backGroundDisabled,frontCrossDisabled,texType) {
+ ccui.Widget.prototype.ctor.call(this);
+ this.setTouchEnabled(true);
+ var strNum = 0;
+ for(var i=0; i
+ * Constructor of ccui.LoadingBar, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {string} textureName
+ * @param {Number} percentage
+ * @example
+ * // example
+ * var uiLoadingBar = new ccui.LoadingBar;
+ */
+ ctor: function (textureName, percentage) {
+ this._direction = ccui.LoadingBar.TYPE_LEFT;
+ this._barRendererTextureSize = cc.size(0, 0);
+ this._capInsets = cc.rect(0, 0, 0, 0);
+ ccui.Widget.prototype.ctor.call(this);
+
+ if (textureName !== undefined)
+ this.loadTexture(textureName);
+ if (percentage !== undefined)
+ this.setPercent(percentage);
+ },
+
+ _initRenderer: function () {
+ //todo use Scale9Sprite
+ this._barRenderer = new cc.Sprite();
+ this.addProtectedChild(this._barRenderer, ccui.LoadingBar.RENDERER_ZORDER, -1);
+ this._barRenderer.setAnchorPoint(0.0, 0.5);
+ },
+
+ /**
+ * Changes the progress direction of LoadingBar.
+ * LoadingBarTypeLeft means progress left to right, LoadingBarTypeRight otherwise.
+ * @param {ccui.LoadingBar.TYPE_LEFT | ccui.LoadingBar.TYPE_RIGHT} dir
+ */
+ setDirection: function (dir) {
+ if (this._direction === dir)
+ return;
+ this._direction = dir;
+ switch (this._direction) {
+ case ccui.LoadingBar.TYPE_LEFT:
+ this._barRenderer.setAnchorPoint(0, 0.5);
+ this._barRenderer.setPosition(0, this._contentSize.height * 0.5);
+ if (!this._scale9Enabled)
+ this._barRenderer.setFlippedX(false);
+
+ break;
+ case ccui.LoadingBar.TYPE_RIGHT:
+ this._barRenderer.setAnchorPoint(1, 0.5);
+ this._barRenderer.setPosition(this._totalLength, this._contentSize.height * 0.5);
+ if (!this._scale9Enabled)
+ this._barRenderer.setFlippedX(true);
+
+ break;
+ }
+ },
+
+ /**
+ * Returns the progress direction of LoadingBar.
+ * LoadingBarTypeLeft means progress left to right, LoadingBarTypeRight otherwise.
+ * @returns {ccui.LoadingBar.TYPE_LEFT | ccui.LoadingBar.TYPE_RIGHT}
+ */
+ getDirection: function () {
+ return this._direction;
+ },
+
+ /**
+ * Loads texture for LoadingBar.
+ * @param {String} texture
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadTexture: function (texture, texType) {
+ if (!texture)
+ return;
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._renderBarTexType = texType;
+ this._textureFile = texture;
+ var barRenderer = this._barRenderer;
+
+ var self = this;
+ if (!barRenderer._textureLoaded) {
+ barRenderer.addEventListener("load", function () {
+ self.loadTexture(self._textureFile, self._renderBarTexType);
+ self._setPercent(self._percent);
+ });
+ }
+
+ switch (this._renderBarTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ barRenderer.initWithFile(texture);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ barRenderer.initWithSpriteFrameName(texture);
+ break;
+ default:
+ break;
+ }
+
+ var bz = barRenderer.getContentSize();
+ this._barRendererTextureSize.width = bz.width;
+ this._barRendererTextureSize.height = bz.height;
+
+ switch (this._direction) {
+ case ccui.LoadingBar.TYPE_LEFT:
+ barRenderer.setAnchorPoint(0, 0.5);
+ if (!this._scale9Enabled)
+ barRenderer.setFlippedX(false);
+ break;
+ case ccui.LoadingBar.TYPE_RIGHT:
+ barRenderer.setAnchorPoint(1, 0.5);
+ if (!this._scale9Enabled)
+ barRenderer.setFlippedX(true);
+ break;
+ }
+ if (this._scale9Enabled)
+ barRenderer.setCapInsets(this._capInsets);
+
+ this._updateChildrenDisplayedRGBA();
+ this._barRendererScaleChangedWithSize();
+ this._updateContentSizeWithTextureSize(this._barRendererTextureSize);
+ this._barRendererAdaptDirty = true;
+ this._findLayout();
+ },
+
+ /**
+ * Sets if LoadingBar is using scale9 renderer.
+ * @param {Boolean} enabled
+ */
+ setScale9Enabled: function (enabled) {
+ //todo use setScale9Enabled
+ if (this._scale9Enabled === enabled)
+ return;
+ this._scale9Enabled = enabled;
+ this.removeProtectedChild(this._barRenderer);
+
+ this._barRenderer = this._scale9Enabled ? new ccui.Scale9Sprite() : new cc.Sprite();
+
+ this.loadTexture(this._textureFile, this._renderBarTexType);
+ this.addProtectedChild(this._barRenderer, ccui.LoadingBar.RENDERER_ZORDER, -1);
+ if (this._scale9Enabled) {
+ var ignoreBefore = this._ignoreSize;
+ this.ignoreContentAdaptWithSize(false);
+ this._prevIgnoreSize = ignoreBefore;
+ } else
+ this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
+ this.setCapInsets(this._capInsets);
+ this.setPercent(this._percent);
+ this._barRendererAdaptDirty = true;
+ },
+
+ /**
+ * Returns LoadingBar is using scale9 renderer or not..
+ * @returns {Boolean}
+ */
+ isScale9Enabled: function () {
+ return this._scale9Enabled;
+ },
+
+ /**
+ * Sets capinsets for LoadingBar, if LoadingBar is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsets: function (capInsets) {
+ if (!capInsets)
+ return;
+ var locInsets = this._capInsets;
+ locInsets.x = capInsets.x;
+ locInsets.y = capInsets.y;
+ locInsets.width = capInsets.width;
+ locInsets.height = capInsets.height;
+
+ if (this._scale9Enabled)
+ this._barRenderer.setCapInsets(capInsets);
+ },
+
+ /**
+ * Returns cap insets for loadingBar.
+ * @returns {cc.Rect}
+ */
+ getCapInsets: function () {
+ return cc.rect(this._capInsets);
+ },
+
+ /**
+ * The current progress of loadingBar
+ * @param {number} percent percent value from 1 to 100.
+ */
+ setPercent: function (percent) {
+ if (percent > 100)
+ percent = 100;
+ if (percent < 0)
+ percent = 0;
+ if (percent === this._percent)
+ return;
+ this._percent = percent;
+ this._setPercent(percent);
+ },
+
+ _setPercent: function () {
+ var res, rect, spriteRenderer, spriteTextureRect;
+
+ if (this._totalLength <= 0)
+ return;
+ res = this._percent / 100.0;
+
+ if (this._scale9Enabled)
+ this._setScale9Scale();
+ else {
+ spriteRenderer = this._barRenderer;
+ spriteTextureRect = this._barRendererTextureSize;
+ rect = spriteRenderer.getTextureRect();
+ rect.width = spriteTextureRect.width * res;
+ spriteRenderer.setTextureRect(
+ cc.rect(
+ rect.x,
+ rect.y,
+ spriteTextureRect.width * res,
+ spriteTextureRect.height
+ ),
+ spriteRenderer._rectRotated
+ );
+ }
+ },
+
+ /**
+ * Sets the contentSize of ccui.LoadingBar
+ * @override
+ * @param {Number|cc.Size} contentSize
+ * @param {Number} [height]
+ */
+ setContentSize: function (contentSize, height) {
+ ccui.Widget.prototype.setContentSize.call(this, contentSize, height);
+ this._totalLength = (height === undefined) ? contentSize.width : contentSize;
+ },
+
+ /**
+ * Returns the progress direction of LoadingBar.
+ * @returns {number} percent value from 1 to 100.
+ */
+ getPercent: function () {
+ return this._percent;
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ this._barRendererAdaptDirty = true;
+ },
+
+ _adaptRenderers: function () {
+ if (this._barRendererAdaptDirty) {
+ this._barRendererScaleChangedWithSize();
+ this._barRendererAdaptDirty = false;
+ }
+ },
+
+ /**
+ * Ignore the LoadingBar's custom size, if ignore is true that LoadingBar will ignore it's custom size, use renderer's content size, false otherwise.
+ * @override
+ * @param {Boolean}ignore
+ */
+ ignoreContentAdaptWithSize: function (ignore) {
+ if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
+ ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
+ this._prevIgnoreSize = ignore;
+ }
+ },
+
+ /**
+ * Returns the texture size of renderer.
+ * @returns {cc.Size|*}
+ */
+ getVirtualRendererSize: function () {
+ return cc.size(this._barRendererTextureSize);
+ },
+
+ /**
+ * Returns the renderer of ccui.LoadingBar
+ * @override
+ * @returns {cc.Node}
+ */
+ getVirtualRenderer: function () {
+ return this._barRenderer;
+ },
+
+ _barRendererScaleChangedWithSize: function () {
+ var locBarRender = this._barRenderer, locContentSize = this._contentSize;
+ if(this._unifySize){
+ this._totalLength = this._contentSize.width;
+ this.setPercent(this._percent);
+ }else if (this._ignoreSize) {
+ if (!this._scale9Enabled) {
+ this._totalLength = this._barRendererTextureSize.width;
+ locBarRender.setScale(1.0);
+ }
+ } else {
+ this._totalLength = locContentSize.width;
+ if (this._scale9Enabled) {
+ this._setScale9Scale();
+ locBarRender.setScale(1.0);
+ } else {
+ var textureSize = this._barRendererTextureSize;
+ if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
+ locBarRender.setScale(1.0);
+ return;
+ }
+ var scaleX = locContentSize.width / textureSize.width;
+ var scaleY = locContentSize.height / textureSize.height;
+ locBarRender.setScaleX(scaleX);
+ locBarRender.setScaleY(scaleY);
+ }
+ }
+ switch (this._direction) {
+ case ccui.LoadingBar.TYPE_LEFT:
+ locBarRender.setPosition(0, locContentSize.height * 0.5);
+ break;
+ case ccui.LoadingBar.TYPE_RIGHT:
+ locBarRender.setPosition(this._totalLength, locContentSize.height * 0.5);
+ break;
+ default:
+ break;
+ }
+ },
+
+ _setScale9Scale: function () {
+ var width = (this._percent) / 100 * this._totalLength;
+ this._barRenderer.setPreferredSize(cc.size(width, this._contentSize.height));
+ },
+
+ /**
+ * Returns the "class name" of widget.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "LoadingBar";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.LoadingBar();
+ },
+
+ _copySpecialProperties: function (loadingBar) {
+ if (loadingBar instanceof ccui.LoadingBar) {
+ this._prevIgnoreSize = loadingBar._prevIgnoreSize;
+ this.setScale9Enabled(loadingBar._scale9Enabled);
+ this.loadTexture(loadingBar._textureFile, loadingBar._renderBarTexType);
+ this.setCapInsets(loadingBar._capInsets);
+ this.setPercent(loadingBar._percent);
+ this.setDirection(loadingBar._direction);
+ }
+ }
+});
+
+var _p = ccui.LoadingBar.prototype;
+
+// Extended properties
+/** @expose */
+_p.direction;
+cc.defineGetterSetter(_p, "direction", _p.getDirection, _p.setDirection);
+/** @expose */
+_p.percent;
+cc.defineGetterSetter(_p, "percent", _p.getPercent, _p.setPercent);
+
+_p = null;
+
+/**
+ * Allocates and initializes a UILoadingBar.
+ * @deprecated since v3.0, please use new ccui.LoadingBar() instead.
+ * @param {string} textureName
+ * @param {Number} percentage
+ * @return {ccui.LoadingBar}
+ */
+ccui.LoadingBar.create = function (textureName, percentage) {
+ return new ccui.LoadingBar(textureName, percentage);
+};
+
+// Constants
+//loadingBar Type
+
+/**
+ * The left direction of ccui.LoadingBar.
+ * @constant
+ * @type {number}
+ */
+ccui.LoadingBar.TYPE_LEFT = 0;
+/**
+ * The right direction of ccui.LoadingBar.
+ * @constant
+ * @type {number}
+ */
+ccui.LoadingBar.TYPE_RIGHT = 1;
+
+/**
+ * The zOrder value of ccui.LoadingBar's renderer.
+ * @constant
+ * @type {number}
+ */
+ccui.LoadingBar.RENDERER_ZORDER = -1;
diff --git a/extensions/ccui/uiwidgets/UIRichText.js b/extensions/ccui/uiwidgets/UIRichText.js
new file mode 100644
index 0000000000..c0572561f4
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UIRichText.js
@@ -0,0 +1,681 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * ccui.RichElement is the base class of RichElementText, RichElementImage etc. It has type, tag, color and opacity attributes.
+ * @class
+ * @extends ccui.Class
+ */
+ccui.RichElement = ccui.Class.extend(/** @lends ccui.RichElement# */{
+ _type: 0,
+ _tag: 0,
+ _color: null,
+ _opacity: 0,
+ /**
+ * Constructor of ccui.RichElement
+ */
+ ctor: function (tag, color, opacity) {
+ this._type = 0;
+ this._tag = tag || 0;
+ this._color = cc.color(255, 255, 255, 255);
+ if (color) {
+ this._color.r = color.r;
+ this._color.g = color.g;
+ this._color.b = color.b;
+ }
+ this._opacity = opacity || 0;
+ if (opacity === undefined) {
+ this._color.a = color.a;
+ }
+ else {
+ this._color.a = opacity;
+ }
+ }
+});
+
+/**
+ * The text element for RichText, it has text, fontName, fontSize attributes.
+ * @class
+ * @extends ccui.RichElement
+ */
+ccui.RichElementText = ccui.RichElement.extend(/** @lends ccui.RichElementText# */{
+ _text: "",
+ _fontName: "",
+ _fontSize: 0,
+ /** @type cc.FontDefinition */
+ _fontDefinition: null,
+ /**
+ * Usage Example using FontDefinition:
+ *
+ * var rtEl = new ccui.RichElementText("tag", new cc.FontDefinition({
+ * fillStyle: cc.color.BLACK,
+ * fontName: "Arial",
+ * fontSize: 12,
+ * fontWeight: "bold",
+ * fontStyle: "normal",
+ * lineHeight: 14
+ * }), 255, "Some Text");
+ *
+ * Constructor of ccui.RichElementText
+ * @param {Number} tag
+ * @param {cc.Color|cc.FontDefinition} colorOrFontDef
+ * @param {Number} opacity
+ * @param {String} text
+ * @param {String} fontName
+ * @param {Number} fontSize
+ */
+ ctor: function (tag, colorOrFontDef, opacity, text, fontName, fontSize) {
+ var color = colorOrFontDef;
+ if (colorOrFontDef && colorOrFontDef instanceof cc.FontDefinition) {
+ color = colorOrFontDef.fillStyle;
+ fontName = colorOrFontDef.fontName;
+ fontSize = colorOrFontDef.fontSize;
+ this._fontDefinition = colorOrFontDef;
+ }
+ ccui.RichElement.prototype.ctor.call(this, tag, color, opacity);
+ this._type = ccui.RichElement.TEXT;
+ this._text = text;
+ this._fontName = fontName;
+ this._fontSize = fontSize;
+ }
+});
+
+/**
+ * Create a richElementText
+ * @deprecated since v3.0, please use new ccui.RichElementText() instead.
+ * @param {Number} tag
+ * @param {cc.Color} color
+ * @param {Number} opacity
+ * @param {String} text
+ * @param {String} fontName
+ * @param {Number} fontSize
+ * @returns {ccui.RichElementText}
+ */
+ccui.RichElementText.create = function (tag, color, opacity, text, fontName, fontSize) {
+ return new ccui.RichElementText(tag, color, opacity, text, fontName, fontSize);
+};
+
+/**
+ * The image element for RichText, it has filePath, textureRect, textureType attributes.
+ * @class
+ * @extends ccui.RichElement
+ */
+ccui.RichElementImage = ccui.RichElement.extend(/** @lends ccui.RichElementImage# */{
+ _filePath: "",
+ _textureRect: null,
+ _textureType: 0,
+
+ /**
+ * Constructor of ccui.RichElementImage
+ * @param {Number} tag
+ * @param {cc.Color} color
+ * @param {Number} opacity
+ * @param {String} filePath
+ */
+ ctor: function (tag, color, opacity, filePath) {
+ ccui.RichElement.prototype.ctor.call(this, tag, color, opacity);
+ this._type = ccui.RichElement.IMAGE;
+ this._filePath = filePath || "";
+ this._textureRect = cc.rect(0, 0, 0, 0);
+ this._textureType = 0;
+ }
+});
+
+/**
+ * Create a richElementImage
+ * @deprecated since v3.0, please use new ccui.RichElementImage() instead.
+ * @param {Number} tag
+ * @param {cc.Color} color
+ * @param {Number} opacity
+ * @param {String} filePath
+ * @returns {ccui.RichElementImage}
+ */
+ccui.RichElementImage.create = function (tag, color, opacity, filePath) {
+ return new ccui.RichElementImage(tag, color, opacity, filePath);
+};
+
+/**
+ * The custom node element for RichText.
+ * @class
+ * @extends ccui.RichElement
+ */
+ccui.RichElementCustomNode = ccui.RichElement.extend(/** @lends ccui.RichElementCustomNode# */{
+ _customNode: null,
+
+ /**
+ * Constructor of ccui.RichElementCustomNode
+ * @param {Number} tag
+ * @param {cc.Color} color
+ * @param {Number} opacity
+ * @param {cc.Node} customNode
+ */
+ ctor: function (tag, color, opacity, customNode) {
+ ccui.RichElement.prototype.ctor.call(this, tag, color, opacity);
+ this._type = ccui.RichElement.CUSTOM;
+ this._customNode = customNode || null;
+ }
+});
+
+/**
+ * Create a richElementCustomNode
+ * @deprecated since v3.0, please use new ccui.RichElementCustomNode() instead.
+ * @param {Number} tag
+ * @param {Number} color
+ * @param {Number} opacity
+ * @param {cc.Node} customNode
+ * @returns {ccui.RichElementCustomNode}
+ */
+ccui.RichElementCustomNode.create = function (tag, color, opacity, customNode) {
+ return new ccui.RichElementCustomNode(tag, color, opacity, customNode);
+};
+
+/**
+ * The rich text control of Cocos UI. It receives text, image, and custom node as its children to display.
+ * @class
+ * @extends ccui.Widget
+ */
+ccui.RichText = ccui.Widget.extend(/** @lends ccui.RichText# */{
+ _formatTextDirty: false,
+ _richElements: null,
+ _elementRenders: null,
+ _leftSpaceWidth: 0,
+ _verticalSpace: 0,
+ _elementRenderersContainer: null,
+ _lineBreakOnSpace: false,
+ _textHorizontalAlignment: null,
+ _textVerticalAlignment: null,
+
+ /**
+ * create a rich text
+ * Constructor of ccui.RichText. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @example
+ * var uiRichText = new ccui.RichTex();
+ */
+ ctor: function () {
+ ccui.Widget.prototype.ctor.call(this);
+ this._formatTextDirty = false;
+ this._richElements = [];
+ this._elementRenders = [];
+ this._leftSpaceWidth = 0;
+ this._verticalSpace = 0;
+ this._textHorizontalAlignment = cc.TEXT_ALIGNMENT_LEFT;
+ this._textVerticalAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
+ },
+
+ _initRenderer: function () {
+ this._elementRenderersContainer = new cc.Node();
+ this._elementRenderersContainer.setAnchorPoint(0.5, 0.5);
+ this.addProtectedChild(this._elementRenderersContainer, 0, -1);
+ },
+
+ /**
+ * Insert a element
+ * @param {ccui.RichElement} element
+ * @param {Number} index
+ */
+ insertElement: function (element, index) {
+ this._richElements.splice(index, 0, element);
+ this._formatTextDirty = true;
+ },
+
+ /**
+ * Push a element
+ * @param {ccui.RichElement} element
+ */
+ pushBackElement: function (element) {
+ this._richElements.push(element);
+ this._formatTextDirty = true;
+ },
+
+ /**
+ * Remove element
+ * @param {ccui.RichElement} element
+ */
+ removeElement: function (element) {
+ if (cc.isNumber(element))
+ this._richElements.splice(element, 1);
+ else
+ cc.arrayRemoveObject(this._richElements, element);
+ this._formatTextDirty = true;
+ },
+
+ /**
+ * Formats the richText's content.
+ */
+ formatText: function () {
+ if (this._formatTextDirty) {
+ this._elementRenderersContainer.removeAllChildren();
+ this._elementRenders.length = 0;
+ var i, element, locRichElements = this._richElements;
+ if (this._ignoreSize) {
+ this._addNewLine();
+ for (i = 0; i < locRichElements.length; i++) {
+ element = locRichElements[i];
+ var elementRenderer = null;
+ switch (element._type) {
+ case ccui.RichElement.TEXT:
+ if (element._fontDefinition)
+ elementRenderer = new cc.LabelTTF(element._text, element._fontDefinition);
+ else //todo: There may be ambiguous
+ elementRenderer = new cc.LabelTTF(element._text, element._fontName, element._fontSize);
+ break;
+ case ccui.RichElement.IMAGE:
+ elementRenderer = new cc.Sprite(element._filePath);
+ break;
+ case ccui.RichElement.CUSTOM:
+ elementRenderer = element._customNode;
+ break;
+ default:
+ break;
+ }
+ elementRenderer.setColor(element._color);
+ elementRenderer.setOpacity(element._color.a);
+ this._pushToContainer(elementRenderer);
+ }
+ } else {
+ this._addNewLine();
+ for (i = 0; i < locRichElements.length; i++) {
+ element = locRichElements[i];
+ switch (element._type) {
+ case ccui.RichElement.TEXT:
+ if (element._fontDefinition)
+ this._handleTextRenderer(element._text, element._fontDefinition, element._fontDefinition.fontSize, element._fontDefinition.fillStyle);
+ else
+ this._handleTextRenderer(element._text, element._fontName, element._fontSize, element._color);
+ break;
+ case ccui.RichElement.IMAGE:
+ this._handleImageRenderer(element._filePath, element._color, element._color.a);
+ break;
+ case ccui.RichElement.CUSTOM:
+ this._handleCustomRenderer(element._customNode);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ this.formatRenderers();
+ this._formatTextDirty = false;
+ }
+ },
+ /**
+ * Prepare the child LabelTTF based on line breaking
+ * @param {String} text
+ * @param {String|cc.FontDefinition} fontNameOrFontDef
+ * @param {Number} fontSize
+ * @param {cc.Color} color
+ * @private
+ */
+ _handleTextRenderer: function (text, fontNameOrFontDef, fontSize, color) {
+ if (text === "")
+ return;
+
+ if (text === "\n") { //Force Line Breaking
+ this._addNewLine();
+ return;
+ }
+
+ var textRenderer = fontNameOrFontDef instanceof cc.FontDefinition ? new cc.LabelTTF(text, fontNameOrFontDef) : new cc.LabelTTF(text, fontNameOrFontDef, fontSize);
+ var textRendererWidth = textRenderer.getContentSize().width;
+ this._leftSpaceWidth -= textRendererWidth;
+ if (this._leftSpaceWidth < 0) {
+ var overstepPercent = (-this._leftSpaceWidth) / textRendererWidth;
+ var curText = text;
+ var stringLength = curText.length;
+ var leftLength = stringLength * (1 - overstepPercent);
+ var leftWords = curText.substr(0, leftLength);
+ var cutWords = curText.substr(leftLength, curText.length - 1);
+ var validLeftLength = leftLength > 0;
+
+ if (this._lineBreakOnSpace) {
+ var lastSpaceIndex = leftWords.lastIndexOf(' ');
+ leftLength = lastSpaceIndex === -1 ? leftLength : lastSpaceIndex + 1;
+ cutWords = curText.substr(leftLength, curText.length - 1);
+ validLeftLength = leftLength > 0 && cutWords !== " ";
+ }
+
+ if (validLeftLength) {
+ var leftRenderer = null;
+ if (fontNameOrFontDef instanceof cc.FontDefinition) {
+ leftRenderer = new cc.LabelTTF(leftWords.substr(0, leftLength), fontNameOrFontDef);
+ leftRenderer.setOpacity(fontNameOrFontDef.fillStyle.a); //TODO: Verify that might not be needed...
+ } else {
+ leftRenderer = new cc.LabelTTF(leftWords.substr(0, leftLength), fontNameOrFontDef, fontSize);
+ leftRenderer.setColor(color);
+ leftRenderer.setOpacity(color.a);
+ }
+ this._pushToContainer(leftRenderer);
+ }
+
+ this._addNewLine();
+ this._handleTextRenderer(cutWords, fontNameOrFontDef, fontSize, color);
+ } else {
+ if (fontNameOrFontDef instanceof cc.FontDefinition) {
+ textRenderer.setOpacity(fontNameOrFontDef.fillStyle.a); //TODO: Verify that might not be needed...
+ } else {
+ textRenderer.setColor(color);
+ textRenderer.setOpacity(color.a);
+ }
+ this._pushToContainer(textRenderer);
+ }
+ },
+
+ _handleImageRenderer: function (filePath, color, opacity) {
+ var imageRenderer = new cc.Sprite(filePath);
+ this._handleCustomRenderer(imageRenderer);
+ },
+
+ _handleCustomRenderer: function (renderer) {
+ var imgSize = renderer.getContentSize();
+ this._leftSpaceWidth -= imgSize.width;
+ if (this._leftSpaceWidth < 0) {
+ this._addNewLine();
+ this._pushToContainer(renderer);
+ this._leftSpaceWidth -= imgSize.width;
+ } else
+ this._pushToContainer(renderer);
+ },
+
+ _addNewLine: function () {
+ this._leftSpaceWidth = this._customSize.width;
+ this._elementRenders.push([]);
+ },
+
+ /**
+ * Formats richText's renderer.
+ */
+ formatRenderers: function () {
+ var newContentSizeHeight = 0, locRenderersContainer = this._elementRenderersContainer;
+ var locElementRenders = this._elementRenders;
+ var i, j, row, nextPosX, l;
+ var lineHeight, offsetX;
+ if (this._ignoreSize) {
+ var newContentSizeWidth = 0;
+ row = locElementRenders[0];
+ nextPosX = 0;
+
+ for (j = 0; j < row.length; j++) {
+ l = row[j];
+ l.setAnchorPoint(cc.p(0, 0));
+ l.setPosition(nextPosX, 0);
+ locRenderersContainer.addChild(l, 1, j);
+
+ lineHeight = l.getLineHeight ? l.getLineHeight() : newContentSizeHeight;
+
+ var iSize = l.getContentSize();
+ newContentSizeWidth += iSize.width;
+ newContentSizeHeight = Math.max(Math.min(newContentSizeHeight, lineHeight), iSize.height);
+ nextPosX += iSize.width;
+ }
+
+ //Text flow horizontal alignment:
+ if (this._textHorizontalAlignment !== cc.TEXT_ALIGNMENT_LEFT) {
+ offsetX = 0;
+ if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_RIGHT)
+ offsetX = this._contentSize.width - nextPosX;
+ else if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_CENTER)
+ offsetX = (this._contentSize.width - nextPosX) / 2;
+
+ for (j = 0; j < row.length; j++)
+ row[j].x += offsetX;
+ }
+
+ locRenderersContainer.setContentSize(newContentSizeWidth, newContentSizeHeight);
+ } else {
+ var maxHeights = [];
+ for (i = 0; i < locElementRenders.length; i++) {
+ row = locElementRenders[i];
+ var maxHeight = 0;
+ for (j = 0; j < row.length; j++) {
+ l = row[j];
+ lineHeight = l.getLineHeight ? l.getLineHeight() : l.getContentSize().height;
+ maxHeight = Math.max(Math.min(l.getContentSize().height, lineHeight), maxHeight);
+ }
+ maxHeights[i] = maxHeight;
+ newContentSizeHeight += maxHeights[i];
+ }
+
+ var nextPosY = this._customSize.height;
+
+ for (i = 0; i < locElementRenders.length; i++) {
+ row = locElementRenders[i];
+ nextPosX = 0;
+ nextPosY -= (maxHeights[i] + this._verticalSpace);
+
+ for (j = 0; j < row.length; j++) {
+ l = row[j];
+ l.setAnchorPoint(cc.p(0, 0));
+ l.setPosition(cc.p(nextPosX, nextPosY));
+ locRenderersContainer.addChild(l, 1);
+ nextPosX += l.getContentSize().width;
+ }
+ //Text flow alignment(s)
+ if (this._textHorizontalAlignment !== cc.TEXT_ALIGNMENT_LEFT || this._textVerticalAlignment !== cc.VERTICAL_TEXT_ALIGNMENT_TOP) {
+ offsetX = 0;
+ if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_RIGHT)
+ offsetX = this._contentSize.width - nextPosX;
+ else if (this._textHorizontalAlignment === cc.TEXT_ALIGNMENT_CENTER)
+ offsetX = (this._contentSize.width - nextPosX) / 2;
+
+ var offsetY = 0;
+ if (this._textVerticalAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM)
+ offsetY = this._customSize.height - newContentSizeHeight;
+ else if (this._textVerticalAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER)
+ offsetY = (this._customSize.height - newContentSizeHeight) / 2;
+
+ for (j = 0; j < row.length; j++) {
+ l = row[j];
+ l.x += offsetX;
+ l.y -= offsetY;
+ }
+ }
+ }
+
+ locRenderersContainer.setContentSize(this._contentSize);
+ }
+
+ var length = locElementRenders.length;
+ for (i = 0; i < length; i++) {
+ locElementRenders[i].length = 0;
+ }
+ this._elementRenders.length = 0;
+
+ this.setContentSize(this._ignoreSize ? this.getVirtualRendererSize() : this._customSize);
+ this._updateContentSizeWithTextureSize(this._contentSize);
+
+ locRenderersContainer.setPosition(this._contentSize.width * 0.5, this._contentSize.height * 0.5);
+ },
+
+ _pushToContainer: function (renderer) {
+ if (this._elementRenders.length <= 0)
+ return;
+ this._elementRenders[this._elementRenders.length - 1].push(renderer);
+ },
+
+ _adaptRenderers: function () {
+ this.formatText();
+ },
+
+ /**
+ * Sets vertical space
+ * @param {Number} space
+ */
+ setVerticalSpace: function (space) {
+ this._verticalSpace = space;
+ },
+
+ /**
+ * Sets anchor point
+ * @override
+ * @param {cc.Point} pt
+ */
+ setAnchorPoint: function (pt) {
+ ccui.Widget.prototype.setAnchorPoint.call(this, pt);
+ this._elementRenderersContainer.setAnchorPoint(pt);
+ },
+ _setAnchorX: function (x) {
+ ccui.Widget.prototype._setAnchorX.call(this, x);
+ this._elementRenderersContainer._setAnchorX(x);
+ },
+ _setAnchorY: function (y) {
+ ccui.Widget.prototype._setAnchorY.call(this, y);
+ this._elementRenderersContainer._setAnchorY(y);
+ },
+
+ /**
+ * Returns the renderer container's content size.
+ * @override
+ * @returns {cc.Size}
+ */
+ getVirtualRendererSize: function () {
+ return this._elementRenderersContainer.getContentSize();
+ },
+
+ /**
+ * Ignore the richText's custom size, If ignore is true that richText will ignore it's custom size, use renderer's content size, false otherwise.
+ * @param {Boolean} ignore
+ * @override
+ */
+ ignoreContentAdaptWithSize: function (ignore) {
+ if (this._ignoreSize !== ignore) {
+ this._formatTextDirty = true;
+ ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
+ }
+ },
+
+ /**
+ * Gets the content size of ccui.RichText
+ * @override
+ * @return {cc.Size}
+ */
+ getContentSize: function () {
+ this.formatText();
+ return cc.Node.prototype.getContentSize.call(this);
+ },
+ _getWidth: function () {
+ this.formatText();
+ return cc.Node.prototype._getWidth.call(this);
+ },
+ _getHeight: function () {
+ this.formatText();
+ return cc.Node.prototype._getHeight.call(this);
+ },
+
+ setContentSize: function (contentSize, height) {
+ var locWidth = (height === undefined) ? contentSize.width : contentSize;
+ var locHeight = (height === undefined) ? contentSize.height : height;
+ ccui.Widget.prototype.setContentSize.call(this, locWidth, locHeight);
+ this._formatTextDirty = true;
+ },
+
+ /**
+ * Returns the class name of ccui.RichText.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "RichText";
+ },
+ /**
+ * Allow child renderer to be affected by ccui.RichText's opacity
+ * @param {boolean} value
+ */
+ setCascadeOpacityEnabled: function (value) {
+ ccui.Widget.prototype.setCascadeOpacityEnabled.call(this, value);
+ this._elementRenderersContainer.setCascadeOpacityEnabled(value);
+ },
+ /**
+ * This allow the RichText layout to break line on space only like in Latin text format
+ * by default the property is false, which break the line on characters
+ * @param value
+ */
+ setLineBreakOnSpace: function (value) {
+ this._lineBreakOnSpace = value;
+ this._formatTextDirty = true;
+ this.formatText();
+ },
+ /**
+ * Set the renderer horizontal flow alignment for the Control
+ * although it is named TextHorizontalAlignment, it should work with all type of renderer too.
+ * NOTE: we should rename this to setHorizontalAlignment directly
+ *
+ * @example
+ * var richText = new ccui.RichText();
+ * richText.setTextHorizontalAlignment(cc.Text_ALIGNMENT_RIGHT);
+ *
+ * @param {Number} value - example cc.TEXT_ALIGNMENT_RIGHT
+ */
+ setTextHorizontalAlignment: function (value) {
+ if (value !== this._textHorizontalAlignment) {
+ this._textHorizontalAlignment = value;
+ this.formatText();
+ }
+ },
+ /**
+ * Set the renderer vertical flow alignment for the Control
+ * although it is named TextVerticalAlignment, it should work with all type of renderer too.
+ *
+ * @example
+ * var richText = new ccui.RichText();
+ * richText.setTextVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
+ *
+ * @param {Number} value - example cc.VERTICAL_TEXT_ALIGNMENT_CENTER
+ */
+ setTextVerticalAlignment: function (value) {
+ if (value !== this._textVerticalAlignment) {
+ this._textVerticalAlignment = value;
+ this.formatText();
+ }
+ }
+});
+
+/**
+ * create a rich text
+ * @deprecated since v3.0, please use new ccui.RichText() instead.
+ * @returns {RichText}
+ */
+ccui.RichText.create = function () {
+ return new ccui.RichText();
+};
+
+// Constants
+//Rich element type
+/**
+ * The text type of rich element.
+ * @constant
+ * @type {number}
+ */
+ccui.RichElement.TEXT = 0;
+/**
+ * The image type of rich element.
+ * @constant
+ * @type {number}
+ */
+ccui.RichElement.IMAGE = 1;
+/**
+ * The custom type of rich element.
+ * @constant
+ * @type {number}
+ */
+ccui.RichElement.CUSTOM = 2;
diff --git a/extensions/ccui/uiwidgets/UISlider.js b/extensions/ccui/uiwidgets/UISlider.js
new file mode 100644
index 0000000000..c8362ffdd7
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UISlider.js
@@ -0,0 +1,787 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The Slider control of Cocos UI.
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {Number} percent - The current progress of loadingbar
+ */
+ccui.Slider = ccui.Widget.extend(/** @lends ccui.Slider# */{
+ _barRenderer: null,
+ _progressBarRenderer: null,
+ _barTextureSize: null,
+ _progressBarTextureSize: null,
+ _slidBallNormalRenderer: null,
+ _slidBallPressedRenderer: null,
+ _slidBallDisabledRenderer: null,
+ _slidBallRenderer: null,
+ _barLength: 0,
+ _percent: 0,
+ _scale9Enabled: false,
+ _prevIgnoreSize: true,
+ _textureFile: "",
+ _progressBarTextureFile: "",
+ _slidBallNormalTextureFile: "",
+ _slidBallPressedTextureFile: "",
+ _slidBallDisabledTextureFile: "",
+ _capInsetsBarRenderer: null,
+ _capInsetsProgressBarRenderer: null,
+ _sliderEventListener: null,
+ _sliderEventSelector: null,
+ _barTexType: ccui.Widget.LOCAL_TEXTURE,
+ _progressBarTexType: ccui.Widget.LOCAL_TEXTURE,
+ _ballNTexType: ccui.Widget.LOCAL_TEXTURE,
+ _ballPTexType: ccui.Widget.LOCAL_TEXTURE,
+ _ballDTexType: ccui.Widget.LOCAL_TEXTURE,
+ _isTextureLoaded: false,
+ _className: "Slider",
+ _barRendererAdaptDirty: true,
+ _progressBarRendererDirty: true,
+ _unifySize: false,
+ _zoomScale: 0.1,
+
+ _sliderBallNormalTextureScaleX: 1,
+ _sliderBallNormalTextureScaleY: 1,
+
+ /**
+ * allocates and initializes a UISlider.
+ * Constructor of ccui.Slider. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @example
+ * // example
+ * var uiSlider = new ccui.Slider();
+ */
+ ctor: function (barTextureName, normalBallTextureName, resType) {
+ this._barTextureSize = cc.size(0, 0);
+ this._progressBarTextureSize = cc.size(0, 0);
+ this._capInsetsBarRenderer = cc.rect(0, 0, 0, 0);
+ this._capInsetsProgressBarRenderer = cc.rect(0, 0, 0, 0);
+ ccui.Widget.prototype.ctor.call(this);
+
+ resType = resType || 0;
+ this.setTouchEnabled(true);
+ if (barTextureName) {
+ this.loadBarTexture(barTextureName, resType);
+ }
+ if (normalBallTextureName) {
+ this.loadSlidBallTextures(normalBallTextureName, resType);
+ }
+ },
+
+ _initRenderer: function () {
+ //todo use Scale9Sprite
+ this._barRenderer = new cc.Sprite();
+ this._progressBarRenderer = new cc.Sprite();
+ this._progressBarRenderer.setAnchorPoint(0.0, 0.5);
+ this.addProtectedChild(this._barRenderer, ccui.Slider.BASEBAR_RENDERER_ZORDER, -1);
+ this.addProtectedChild(this._progressBarRenderer, ccui.Slider.PROGRESSBAR_RENDERER_ZORDER, -1);
+ this._slidBallNormalRenderer = new cc.Sprite();
+ this._slidBallPressedRenderer = new cc.Sprite();
+ this._slidBallPressedRenderer.setVisible(false);
+ this._slidBallDisabledRenderer = new cc.Sprite();
+ this._slidBallDisabledRenderer.setVisible(false);
+ this._slidBallRenderer = new cc.Node();
+ this._slidBallRenderer.addChild(this._slidBallNormalRenderer);
+ this._slidBallRenderer.addChild(this._slidBallPressedRenderer);
+ this._slidBallRenderer.addChild(this._slidBallDisabledRenderer);
+ this._slidBallRenderer.setCascadeColorEnabled(true);
+ this._slidBallRenderer.setCascadeOpacityEnabled(true);
+
+ this.addProtectedChild(this._slidBallRenderer, ccui.Slider.BALL_RENDERER_ZORDER, -1);
+ },
+
+ /**
+ * Loads texture for slider bar.
+ * @param {String} fileName
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadBarTexture: function (fileName, texType) {
+ if (!fileName) {
+ return;
+ }
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._textureFile = fileName;
+ this._barTexType = texType;
+ var barRenderer = this._barRenderer;
+
+ var self = this;
+ if (!barRenderer._textureLoaded) {
+ barRenderer.addEventListener("load", function () {
+ self.loadBarTexture(self._textureFile, self._barTexType);
+ });
+ }
+
+ switch (this._barTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ //SetTexture cannot load resource
+ barRenderer.initWithFile(fileName);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ //SetTexture cannot load resource
+ barRenderer.initWithSpriteFrameName(fileName);
+ break;
+ default:
+ break;
+ }
+ this._updateChildrenDisplayedRGBA();
+
+ this._barRendererAdaptDirty = true;
+ this._progressBarRendererDirty = true;
+ this._updateContentSizeWithTextureSize(this._barRenderer.getContentSize());
+ this._findLayout();
+ this._barTextureSize = this._barRenderer.getContentSize();
+ },
+
+ /**
+ * Loads dark state texture for slider progress bar.
+ * @param {String} fileName
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadProgressBarTexture: function (fileName, texType) {
+ if (!fileName) {
+ return;
+ }
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._progressBarTextureFile = fileName;
+ this._progressBarTexType = texType;
+ var progressBarRenderer = this._progressBarRenderer;
+
+ var self = this;
+ if (!progressBarRenderer._textureLoaded) {
+ progressBarRenderer.addEventListener("load", function () {
+ self.loadProgressBarTexture(self._progressBarTextureFile, self._progressBarTexType);
+ });
+ }
+
+ switch (this._progressBarTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ //SetTexture cannot load resource
+ progressBarRenderer.initWithFile(fileName);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ //SetTexture cannot load resource
+ progressBarRenderer.initWithSpriteFrameName(fileName);
+ break;
+ default:
+ break;
+ }
+ this._updateChildrenDisplayedRGBA();
+
+ this._progressBarRenderer.setAnchorPoint(cc.p(0, 0.5));
+ var tz = this._progressBarRenderer.getContentSize();
+ this._progressBarTextureSize = {width: tz.width, height: tz.height};
+ this._progressBarRendererDirty = true;
+ this._findLayout();
+ },
+
+ /**
+ * Sets if slider is using scale9 renderer.
+ * @param {Boolean} able
+ */
+ setScale9Enabled: function (able) {
+ //todo use setScale9Enabled
+ if (this._scale9Enabled === able)
+ return;
+
+ this._scale9Enabled = able;
+ this.removeProtectedChild(this._barRenderer, true);
+ this.removeProtectedChild(this._progressBarRenderer, true);
+ this._barRenderer = null;
+ this._progressBarRenderer = null;
+ if (this._scale9Enabled) {
+ this._barRenderer = new ccui.Scale9Sprite();
+ this._progressBarRenderer = new ccui.Scale9Sprite();
+ } else {
+ this._barRenderer = new cc.Sprite();
+ this._progressBarRenderer = new cc.Sprite();
+ }
+ this.loadBarTexture(this._textureFile, this._barTexType);
+ this.loadProgressBarTexture(this._progressBarTextureFile, this._progressBarTexType);
+ this.addProtectedChild(this._barRenderer, ccui.Slider.BASEBAR_RENDERER_ZORDER, -1);
+ this.addProtectedChild(this._progressBarRenderer, ccui.Slider.PROGRESSBAR_RENDERER_ZORDER, -1);
+ if (this._scale9Enabled) {
+ var ignoreBefore = this._ignoreSize;
+ this.ignoreContentAdaptWithSize(false);
+ this._prevIgnoreSize = ignoreBefore;
+ } else {
+ this.ignoreContentAdaptWithSize(this._prevIgnoreSize);
+ }
+ this.setCapInsetsBarRenderer(this._capInsetsBarRenderer);
+ this.setCapInsetProgressBarRenderer(this._capInsetsProgressBarRenderer);
+ this._barRendererAdaptDirty = true;
+ this._progressBarRendererDirty = true;
+ },
+
+ /**
+ * Returns slider is using scale9 renderer or not.
+ * @returns {Boolean}
+ */
+ isScale9Enabled: function () {
+ return this._scale9Enabled;
+ },
+
+ /**
+ * override "ignoreContentAdaptWithSize" method of widget.
+ * @param {Boolean} ignore
+ */
+ ignoreContentAdaptWithSize: function (ignore) {
+ if (!this._scale9Enabled || (this._scale9Enabled && !ignore)) {
+ ccui.Widget.prototype.ignoreContentAdaptWithSize.call(this, ignore);
+ this._prevIgnoreSize = ignore;
+ }
+ },
+
+ /**
+ * Sets capinsets for slider, if slider is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsets: function (capInsets) {
+ this.setCapInsetsBarRenderer(capInsets);
+ this.setCapInsetProgressBarRenderer(capInsets);
+ },
+
+ /**
+ * Sets capinsets for slider's renderer, if slider is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsetsBarRenderer: function (capInsets) {
+ if (!capInsets)
+ return;
+ var locInsets = this._capInsetsBarRenderer;
+ locInsets.x = capInsets.x;
+ locInsets.y = capInsets.y;
+ locInsets.width = capInsets.width;
+ locInsets.height = capInsets.height;
+ if (!this._scale9Enabled)
+ return;
+ this._barRenderer.setCapInsets(capInsets);
+ },
+
+ /**
+ * Returns cap insets for slider.
+ * @returns {cc.Rect}
+ */
+ getCapInsetsBarRenderer: function () {
+ return cc.rect(this._capInsetsBarRenderer);
+ },
+
+ /**
+ * Sets capinsets of ProgressBar for slider, if slider is using scale9 renderer.
+ * @param {cc.Rect} capInsets
+ */
+ setCapInsetProgressBarRenderer: function (capInsets) {
+ if (!capInsets)
+ return;
+ var locInsets = this._capInsetsProgressBarRenderer;
+ locInsets.x = capInsets.x;
+ locInsets.y = capInsets.y;
+ locInsets.width = capInsets.width;
+ locInsets.height = capInsets.height;
+ if (!this._scale9Enabled)
+ return;
+ this._progressBarRenderer.setCapInsets(capInsets);
+ },
+
+ /**
+ * Returns cap insets of ProgressBar for slider.
+ * @returns {cc.Rect}
+ */
+ getCapInsetsProgressBarRenderer: function () {
+ return cc.rect(this._capInsetsProgressBarRenderer);
+ },
+
+ /**
+ * Loads textures for slider ball.
+ * @param {String} normal
+ * @param {String} pressed
+ * @param {String} disabled
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadSlidBallTextures: function (normal, pressed, disabled, texType) {
+ this.loadSlidBallTextureNormal(normal, texType);
+ this.loadSlidBallTexturePressed(pressed, texType);
+ this.loadSlidBallTextureDisabled(disabled, texType);
+ },
+
+ /**
+ * Loads normal state texture for slider ball.
+ * @param {String} normal
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadSlidBallTextureNormal: function (normal, texType) {
+ if (!normal) {
+ return;
+ }
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._slidBallNormalTextureFile = normal;
+ this._ballNTexType = texType;
+
+ var self = this;
+ if (!this._slidBallNormalRenderer._textureLoaded) {
+ this._slidBallNormalRenderer.addEventListener("load", function () {
+ self.loadSlidBallTextureNormal(self._slidBallNormalTextureFile, self._ballNTexType);
+ });
+ }
+
+ switch (this._ballNTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ //SetTexture cannot load resource
+ this._slidBallNormalRenderer.initWithFile(normal);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ //SetTexture cannot load resource
+ this._slidBallNormalRenderer.initWithSpriteFrameName(normal);
+ break;
+ default:
+ break;
+ }
+ this._updateChildrenDisplayedRGBA();
+ this._findLayout();
+ },
+
+ /**
+ * Loads selected state texture for slider ball.
+ * @param {String} pressed
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadSlidBallTexturePressed: function (pressed, texType) {
+ if (!pressed) {
+ return;
+ }
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._slidBallPressedTextureFile = pressed;
+ this._ballPTexType = texType;
+
+ var self = this;
+ if (!this._slidBallPressedRenderer._textureLoaded) {
+ this._slidBallPressedRenderer.addEventListener("load", function () {
+ self.loadSlidBallTexturePressed(self._slidBallPressedTextureFile, self._ballPTexType);
+ });
+ }
+
+ switch (this._ballPTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ //SetTexture cannot load resource
+ this._slidBallPressedRenderer.initWithFile(pressed);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ //SetTexture cannot load resource
+ this._slidBallPressedRenderer.initWithSpriteFrameName(pressed);
+ break;
+ default:
+ break;
+ }
+ this._updateChildrenDisplayedRGBA();
+ this._findLayout();
+ },
+
+ /**
+ * Load dark state texture for slider ball.
+ * @param {String} disabled
+ * @param {ccui.Widget.LOCAL_TEXTURE|ccui.Widget.PLIST_TEXTURE} texType
+ */
+ loadSlidBallTextureDisabled: function (disabled, texType) {
+ if (!disabled) {
+ return;
+ }
+ texType = texType || ccui.Widget.LOCAL_TEXTURE;
+ this._slidBallDisabledTextureFile = disabled;
+ this._ballDTexType = texType;
+
+ var self = this;
+ if (!this._slidBallDisabledRenderer._textureLoaded) {
+ this._slidBallDisabledRenderer.addEventListener("load", function () {
+ self.loadSlidBallTextureDisabled(self._slidBallDisabledTextureFile, self._ballDTexType);
+ });
+ }
+
+ switch (this._ballDTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ //SetTexture cannot load resource
+ this._slidBallDisabledRenderer.initWithFile(disabled);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ //SetTexture cannot load resource
+ this._slidBallDisabledRenderer.initWithSpriteFrameName(disabled);
+ break;
+ default:
+ break;
+ }
+ this._updateChildrenDisplayedRGBA();
+ this._findLayout();
+ },
+
+ /**
+ * Changes the progress direction of slider.
+ * @param {number} percent
+ */
+ setPercent: function (percent) {
+ if (percent > 100)
+ percent = 100;
+ if (percent < 0)
+ percent = 0;
+ this._percent = percent;
+ var res = percent / 100.0;
+ var dis = this._barLength * res;
+ this._slidBallRenderer.setPosition(dis, this._contentSize.height / 2);
+ if (this._scale9Enabled)
+ this._progressBarRenderer.setPreferredSize(cc.size(dis, this._contentSize.height));
+ else {
+ var spriteRenderer = this._progressBarRenderer;
+ var rect = spriteRenderer.getTextureRect();
+ spriteRenderer.setTextureRect(
+ cc.rect(rect.x, rect.y, dis / spriteRenderer._scaleX, rect.height),
+ spriteRenderer.isTextureRectRotated()
+ );
+ }
+ },
+
+ /**
+ * test the point whether location in loadingBar's bounding box.
+ * @override
+ * @param {cc.Point} pt
+ * @returns {boolean}
+ */
+ hitTest: function (pt) {
+ var nsp = this._slidBallNormalRenderer.convertToNodeSpace(pt);
+ var ballSize = this._slidBallNormalRenderer.getContentSize();
+ var ballRect = cc.rect(0, 0, ballSize.width, ballSize.height);
+ return (nsp.x >= ballRect.x &&
+ nsp.x <= (ballRect.x + ballRect.width) &&
+ nsp.y >= ballRect.y &&
+ nsp.y <= (ballRect.y +ballRect.height));
+ },
+
+ onTouchBegan: function (touch, event) {
+ var pass = ccui.Widget.prototype.onTouchBegan.call(this, touch, event);
+ if (this._hit) {
+ var nsp = this.convertToNodeSpace(this._touchBeganPosition);
+ this.setPercent(this._getPercentWithBallPos(nsp.x));
+ this._percentChangedEvent();
+ }
+ return pass;
+ },
+
+ onTouchMoved: function (touch, event) {
+ var touchPoint = touch.getLocation();
+ var nsp = this.convertToNodeSpace(touchPoint);
+ this.setPercent(this._getPercentWithBallPos(nsp.x));
+ this._percentChangedEvent();
+ },
+
+ onTouchEnded: function (touch, event) {
+ ccui.Widget.prototype.onTouchEnded.call(this, touch, event);
+ },
+
+ onTouchCancelled: function (touch, event) {
+ ccui.Widget.prototype.onTouchCancelled.call(this, touch, event);
+ },
+
+ /**
+ * Returns percent with ball's position.
+ * @param {cc.Point} px
+ * @returns {number}
+ */
+ _getPercentWithBallPos: function (px) {
+ return ((px / this._barLength) * 100);
+ },
+
+ /**
+ * add event listener
+ * @param {Function} selector
+ * @param {Object} [target=]
+ * @deprecated since v3.0, please use addEventListener instead.
+ */
+ addEventListenerSlider: function (selector, target) {
+ this.addEventListener(selector, target);
+ },
+
+ /**
+ * Adds a callback
+ * @param {Function} selector
+ * @param {Object} [target=]
+ */
+ addEventListener: function (selector, target) {
+ this._sliderEventSelector = selector; //when target is undefined, _sliderEventSelector = _eventCallback
+ this._sliderEventListener = target;
+ },
+
+ _percentChangedEvent: function () {
+ if (this._sliderEventSelector) {
+ if (this._sliderEventListener)
+ this._sliderEventSelector.call(this._sliderEventListener, this, ccui.Slider.EVENT_PERCENT_CHANGED);
+ else
+ this._sliderEventSelector(this, ccui.Slider.EVENT_PERCENT_CHANGED); // _eventCallback
+ }
+ if (this._ccEventCallback)
+ this._ccEventCallback(this, ccui.Slider.EVENT_PERCENT_CHANGED);
+ },
+
+ /**
+ * Gets the progress direction of slider.
+ * @returns {number}
+ */
+ getPercent: function () {
+ return this._percent;
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ this._barRendererAdaptDirty = true;
+ this._progressBarRendererDirty = true;
+ },
+
+ _adaptRenderers: function () {
+ if (this._barRendererAdaptDirty) {
+ this._barRendererScaleChangedWithSize();
+ this._barRendererAdaptDirty = false;
+ }
+ if (this._progressBarRendererDirty) {
+ this._progressBarRendererScaleChangedWithSize();
+ this._progressBarRendererDirty = false;
+ }
+ },
+
+ /**
+ * Returns the content size of bar renderer.
+ * @returns {cc.Size}
+ */
+ getVirtualRendererSize: function () {
+ return this._barRenderer.getContentSize();
+ },
+
+ /**
+ * Returns the bar renderer.
+ * @returns {cc.Node}
+ */
+ getVirtualRenderer: function () {
+ return this._barRenderer;
+ },
+
+ _barRendererScaleChangedWithSize: function () {
+ if (this._unifySize) {
+ this._barLength = this._contentSize.width;
+ this._barRenderer.setPreferredSize(this._contentSize);
+ } else if (this._ignoreSize) {
+ this._barRenderer.setScale(1.0);
+ this._barLength = this._contentSize.width;
+ } else {
+ this._barLength = this._contentSize.width;
+ if (this._scale9Enabled) {
+ this._barRenderer.setPreferredSize(this._contentSize);
+ this._barRenderer.setScale(1.0);
+ } else {
+ var btextureSize = this._barTextureSize;
+ if (btextureSize.width <= 0.0 || btextureSize.height <= 0.0) {
+ this._barRenderer.setScale(1.0);
+ } else {
+ var bscaleX = this._contentSize.width / btextureSize.width;
+ var bscaleY = this._contentSize.height / btextureSize.height;
+ this._barRenderer.setScaleX(bscaleX);
+ this._barRenderer.setScaleY(bscaleY);
+ }
+ }
+ }
+ this._barRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
+ this.setPercent(this._percent);
+ },
+
+ _progressBarRendererScaleChangedWithSize: function () {
+ if (this._unifySize) {
+ this._progressBarRenderer.setPreferredSize(this._contentSize);
+ } else if (this._ignoreSize) {
+ if (!this._scale9Enabled) {
+ var ptextureSize = this._progressBarTextureSize;
+ var pscaleX = this._contentSize.width / ptextureSize.width;
+ var pscaleY = this._contentSize.height / ptextureSize.height;
+ this._progressBarRenderer.setScaleX(pscaleX);
+ this._progressBarRenderer.setScaleY(pscaleY);
+ }
+ }
+ else {
+ if (this._scale9Enabled) {
+ this._progressBarRenderer.setPreferredSize(this._contentSize);
+ this._progressBarRenderer.setScale(1);
+ }
+ else {
+ var ptextureSize = this._progressBarTextureSize;
+ if (ptextureSize.width <= 0.0 || ptextureSize.height <= 0.0) {
+ this._progressBarRenderer.setScale(1.0);
+ return;
+ }
+ var pscaleX = this._contentSize.width / ptextureSize.width;
+ var pscaleY = this._contentSize.height / ptextureSize.height;
+ this._progressBarRenderer.setScaleX(pscaleX);
+ this._progressBarRenderer.setScaleY(pscaleY);
+ }
+ }
+ this._progressBarRenderer.setPosition(0.0, this._contentSize.height / 2.0);
+ this.setPercent(this._percent);
+ },
+
+ _onPressStateChangedToNormal: function () {
+ this._slidBallNormalRenderer.setVisible(true);
+ this._slidBallPressedRenderer.setVisible(false);
+ this._slidBallDisabledRenderer.setVisible(false);
+
+ this._slidBallNormalRenderer.setScale(this._sliderBallNormalTextureScaleX, this._sliderBallNormalTextureScaleY);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ this._slidBallNormalRenderer._renderCmd._shaderProgram = this._getNormalGLProgram();
+ } else {
+ // TODO: add canvas support
+ }
+ },
+
+ _onPressStateChangedToPressed: function () {
+ if (!this._slidBallPressedTextureFile) {
+ this._slidBallNormalRenderer.setScale(this._sliderBallNormalTextureScaleX + this._zoomScale, this._sliderBallNormalTextureScaleY + this._zoomScale);
+ } else {
+ this._slidBallNormalRenderer.setVisible(false);
+ this._slidBallPressedRenderer.setVisible(true);
+ this._slidBallDisabledRenderer.setVisible(false);
+ }
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ this._slidBallNormalRenderer._renderCmd._shaderProgram = this._getNormalGLProgram();
+ } else {
+ // TODO: add canvas support
+ }
+ },
+
+ _onPressStateChangedToDisabled: function () {
+ if (this._slidBallDisabledTextureFile) {
+ this._slidBallNormalRenderer.setVisible(false);
+ this._slidBallDisabledRenderer.setVisible(true);
+ } else {
+ this._slidBallNormalRenderer.setVisible(true);
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ this._slidBallNormalRenderer._renderCmd._shaderProgram = this._getGrayGLProgram();
+ } else {
+ // TODO: add canvas support
+ }
+ }
+ this._slidBallNormalRenderer.setScale(this._sliderBallNormalTextureScaleX, this._sliderBallNormalTextureScaleY);
+ this._slidBallPressedRenderer.setVisible(false);
+ },
+
+ setZoomScale: function (scale) {
+ this._zoomScale = scale;
+ },
+
+ getZoomScale: function () {
+ return this._zoomScale;
+ },
+
+ getSlidBallNormalRenderer: function () {
+ return this._slidBallNormalRenderer;
+ },
+
+ getSlidBallPressedRenderer: function () {
+ return this._slidBallPressedRenderer;
+ },
+
+ getSlidBallDisabledRenderer: function () {
+ return this._slidBallDisabledRenderer;
+ },
+
+ getSlidBallRenderer: function () {
+ return this._slidBallRenderer;
+ },
+
+ /**
+ * Returns the "class name" of ccui.LoadingBar.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "Slider";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.Slider();
+ },
+
+ _copySpecialProperties: function (slider) {
+ this._prevIgnoreSize = slider._prevIgnoreSize;
+ this.setScale9Enabled(slider._scale9Enabled);
+ this.loadBarTexture(slider._textureFile, slider._barTexType);
+ this.loadProgressBarTexture(slider._progressBarTextureFile, slider._progressBarTexType);
+ this.loadSlidBallTextureNormal(slider._slidBallNormalTextureFile, slider._ballNTexType);
+ this.loadSlidBallTexturePressed(slider._slidBallPressedTextureFile, slider._ballPTexType);
+ this.loadSlidBallTextureDisabled(slider._slidBallDisabledTextureFile, slider._ballDTexType);
+ this.setPercent(slider.getPercent());
+ this._sliderEventListener = slider._sliderEventListener;
+ this._sliderEventSelector = slider._sliderEventSelector;
+ this._zoomScale = slider._zoomScale;
+ this._ccEventCallback = slider._ccEventCallback;
+
+ }
+});
+
+var _p = ccui.Slider.prototype;
+
+// Extended properties
+/** @expose */
+_p.percent;
+cc.defineGetterSetter(_p, "percent", _p.getPercent, _p.setPercent);
+
+_p = null;
+
+/**
+ * allocates and initializes a UISlider.
+ * @deprecated since v3.0, please use new ccui.Slider() instead.
+ * @return {ccui.Slider}
+ */
+ccui.Slider.create = function (barTextureName, normalBallTextureName, resType) {
+ return new ccui.Slider(barTextureName, normalBallTextureName, resType);
+};
+
+// Constant
+//Slider event type
+/**
+ * The percent change event flag of ccui.Slider.
+ * @constant
+ * @type {number}
+ */
+ccui.Slider.EVENT_PERCENT_CHANGED = 0;
+
+//Render zorder
+/**
+ * The zOrder value of ccui.Slider's base bar renderer.
+ * @constant
+ * @type {number}
+ */
+ccui.Slider.BASEBAR_RENDERER_ZORDER = -3;
+/**
+ * The zOrder value of ccui.Slider's progress bar renderer.
+ * @constant
+ * @type {number}
+ */
+ccui.Slider.PROGRESSBAR_RENDERER_ZORDER = -2;
+/**
+ * The zOrder value of ccui.Slider's ball renderer.
+ * @constant
+ * @type {number}
+ */
+ccui.Slider.BALL_RENDERER_ZORDER = -1;
diff --git a/extensions/ccui/uiwidgets/UIText.js b/extensions/ccui/uiwidgets/UIText.js
new file mode 100644
index 0000000000..5d72e061c4
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UIText.js
@@ -0,0 +1,525 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The text control of Cocos UI.
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {Number} boundingWidth - Width of the bounding area of label, the real content width is limited by boundingWidth
+ * @property {Number} boundingHeight - Height of the bounding area of label, the real content height is limited by boundingHeight
+ * @property {String} string - The content string of the label
+ * @property {Number} stringLength - <@readonly> The content string length of the label
+ * @property {String} font - The label font with a style string: e.g. "18px Verdana"
+ * @property {String} fontName - The label font name
+ * @property {Number} fontSize - The label font size
+ * @property {Number} textAlign - Horizontal Alignment of label, cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT
+ * @property {Number} verticalAlign - Vertical Alignment of label: cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM
+ * @property {Boolean} touchScaleEnabled - Indicate whether the label will scale when touching
+ */
+ccui.Text = ccui.Widget.extend(/** @lends ccui.Text# */{
+ _touchScaleChangeEnabled: false,
+ _normalScaleValueX: 1,
+ _normalScaleValueY: 1,
+ _fontName: "Arial",
+ _fontSize: 16,
+ _onSelectedScaleOffset: 0.5,
+ _labelRenderer: null,
+ _textAreaSize: null,
+ _textVerticalAlignment: 0,
+ _textHorizontalAlignment: 0,
+ _className: "Text",
+ _type: null,
+ _labelRendererAdaptDirty: true,
+
+ /**
+ * allocates and initializes a UILabel.
+ * Constructor of ccui.Text. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {String} textContent
+ * @param {String} fontName
+ * @param {Number} fontSize
+ * @example
+ * // example
+ * var uiLabel = new ccui.Text();
+ */
+ ctor: function (textContent, fontName, fontSize) {
+ this._type = ccui.Text.Type.SYSTEM;
+ this._textAreaSize = cc.size(0, 0);
+ ccui.Widget.prototype.ctor.call(this);
+
+ if (fontSize !== undefined) {
+ this.setFontName(fontName);
+ this.setFontSize(fontSize);
+ this.setString(textContent);
+ } else {
+ this.setFontName(this._fontName);
+ }
+ },
+
+ _initRenderer: function () {
+ this._labelRenderer = new cc.LabelTTF();
+ this.addProtectedChild(this._labelRenderer, ccui.Text.RENDERER_ZORDER, -1);
+ },
+
+ /**
+ * Changes the value of ccui.Text.
+ * @deprecated since v3.0, please use setString() instead.
+ * @param {String} text
+ */
+ setText: function (text) {
+ cc.log("Please use the setString");
+ this.setString(text);
+ },
+
+ /**
+ * Changes the value of ccui.Text.
+ * @param {String} text
+ */
+ setString: function (text) {
+ if(text === this._labelRenderer.getString()) return;
+ this._setString(text);
+
+ this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
+ },
+
+ _setString: function (text) {
+ this._labelRenderer.setString(text);
+ this._labelRendererAdaptDirty = true;
+ },
+
+ /**
+ * Gets the string value of ccui.Text.
+ * @deprecated since v3.0, please use getString instead.
+ * @returns {String}
+ */
+ getStringValue: function () {
+ cc.log("Please use the getString");
+ return this._labelRenderer.getString();
+ },
+
+ /**
+ * Gets the string value of ccui.Text.
+ * @returns {String}
+ */
+ getString: function () {
+ return this._labelRenderer.getString();
+ },
+
+ /**
+ * Gets the string length of ccui.Text.
+ * @returns {Number}
+ */
+ getStringLength: function () {
+ return this._labelRenderer.getStringLength();
+ },
+
+ /**
+ * Sets fontSize
+ * @param {Number} size
+ */
+ setFontSize: function (size) {
+ this._setFontSize(size);
+ this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
+ },
+
+ _setFontSize: function (size) {
+ this._labelRenderer.setFontSize(size);
+ this._fontSize = size;
+ this._labelRendererAdaptDirty = true;
+ },
+
+ /**
+ * Returns font Size of ccui.Text
+ * @returns {Number}
+ */
+ getFontSize: function () {
+ return this._fontSize;
+ },
+
+ /**
+ * Sets font name
+ * @return {String} name
+ */
+ setFontName: function (name) {
+ this._setFontName(name);
+ this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
+ },
+
+ _setFontName: function (name) {
+ this._fontName = name;
+ this._labelRenderer.setFontName(name);
+ this._labelRendererAdaptDirty = true;
+ },
+
+ _updateUITextContentSize: function () {
+ this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
+ },
+
+ /**
+ * Returns font name of ccui.Text.
+ * @returns {string}
+ */
+ getFontName: function () {
+ return this._fontName;
+ },
+
+ _setFont: function (font) {
+ var res = cc.LabelTTF._fontStyleRE.exec(font);
+ if (res) {
+ this._fontSize = parseInt(res[1]);
+ this._fontName = res[2];
+ this._labelRenderer._setFont(font);
+ this._labelScaleChangedWithSize();
+ }
+ },
+ _getFont: function () {
+ return this._labelRenderer._getFont();
+ },
+
+ /**
+ * Returns the type of ccui.Text.
+ * @returns {null}
+ */
+ getType: function () {
+ return this._type;
+ },
+
+ /**
+ * Sets text Area Size
+ * @param {cc.Size} size
+ */
+ setTextAreaSize: function (size) {
+ this._setTextAreaSize(size);
+ this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
+ },
+
+ _setTextAreaSize: function (size) {
+ this._labelRenderer.setDimensions(size);
+ if (!this._ignoreSize){
+ this._customSize = size;
+ }
+ this._labelRendererAdaptDirty = true;
+ },
+
+ /**
+ * Returns renderer's dimension.
+ * @returns {cc.Size}
+ */
+ getTextAreaSize: function () {
+ return this._labelRenderer.getDimensions();
+ },
+
+ /**
+ * Sets Horizontal Alignment of cc.LabelTTF
+ * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
+ */
+ setTextHorizontalAlignment: function (alignment) {
+ this._setTextHorizontalAlignment(alignment);
+ this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
+ },
+
+
+ _setTextHorizontalAlignment: function (alignment) {
+ this._labelRenderer.setHorizontalAlignment(alignment);
+ this._labelRendererAdaptDirty = true;
+ },
+
+ /**
+ * Returns Horizontal Alignment of label
+ * @returns {TEXT_ALIGNMENT_LEFT|TEXT_ALIGNMENT_CENTER|TEXT_ALIGNMENT_RIGHT}
+ */
+ getTextHorizontalAlignment: function () {
+ return this._labelRenderer.getHorizontalAlignment();
+ },
+
+ /**
+ * Sets Vertical Alignment of label
+ * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} alignment
+ */
+ setTextVerticalAlignment: function (alignment) {
+ this._setTextVerticalAlignment(alignment);
+ this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
+ },
+
+ _setTextVerticalAlignment: function (alignment) {
+ this._labelRenderer.setVerticalAlignment(alignment);
+ this._labelRendererAdaptDirty = true;
+ },
+ /**
+ * Gets text vertical alignment.
+ * @returns {VERTICAL_TEXT_ALIGNMENT_TOP|VERTICAL_TEXT_ALIGNMENT_CENTER|VERTICAL_TEXT_ALIGNMENT_BOTTOM}
+ */
+ getTextVerticalAlignment: function () {
+ return this._labelRenderer.getVerticalAlignment();
+ },
+
+ /**
+ * Sets the touch scale enabled of label.
+ * @param {Boolean} enable
+ */
+ setTouchScaleChangeEnabled: function (enable) {
+ this._touchScaleChangeEnabled = enable;
+ },
+
+ /**
+ * Gets the touch scale enabled of label.
+ * @returns {Boolean}
+ */
+ isTouchScaleChangeEnabled: function () {
+ return this._touchScaleChangeEnabled;
+ },
+
+ _onPressStateChangedToNormal: function () {
+ if (!this._touchScaleChangeEnabled)
+ return;
+ this._labelRenderer.setScaleX(this._normalScaleValueX);
+ this._labelRenderer.setScaleY(this._normalScaleValueY);
+ },
+
+ _onPressStateChangedToPressed: function () {
+ if (!this._touchScaleChangeEnabled)
+ return;
+ this._labelRenderer.setScaleX(this._normalScaleValueX + this._onSelectedScaleOffset);
+ this._labelRenderer.setScaleY(this._normalScaleValueY + this._onSelectedScaleOffset);
+ },
+
+ _onPressStateChangedToDisabled: function () {
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ this._labelRendererAdaptDirty = true;
+ },
+
+ _adaptRenderers: function () {
+ if (this._labelRendererAdaptDirty) {
+ this._labelScaleChangedWithSize();
+ this._labelRendererAdaptDirty = false;
+ }
+ },
+
+ /**
+ * Returns the renderer's content size.
+ * @override
+ * @returns {cc.Size}
+ */
+ getVirtualRendererSize: function () {
+ return this._labelRenderer.getContentSize();
+ },
+
+ /**
+ * Returns the renderer of ccui.Text.
+ * @returns {cc.Node}
+ */
+ getVirtualRenderer: function () {
+ return this._labelRenderer;
+ },
+
+ //@since v3.3
+ getAutoRenderSize: function () {
+ var virtualSize = this._labelRenderer.getContentSize();
+ if (!this._ignoreSize) {
+ this._labelRenderer.setDimensions(0, 0);
+ virtualSize = this._labelRenderer.getContentSize();
+ this._labelRenderer.setDimensions(this._contentSize.width, this._contentSize.height);
+ }
+ return virtualSize;
+ },
+
+ _labelScaleChangedWithSize: function () {
+ var locContentSize = this._contentSize;
+ if (this._ignoreSize) {
+ this._labelRenderer.setScale(1.0);
+ this._normalScaleValueX = this._normalScaleValueY = 1;
+ } else {
+ this._labelRenderer.setDimensions(cc.size(locContentSize.width, locContentSize.height));
+ var textureSize = this._labelRenderer.getContentSize();
+ if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
+ this._labelRenderer.setScale(1.0);
+ return;
+ }
+ var scaleX = locContentSize.width / textureSize.width;
+ var scaleY = locContentSize.height / textureSize.height;
+ this._labelRenderer.setScaleX(scaleX);
+ this._labelRenderer.setScaleY(scaleY);
+ this._normalScaleValueX = scaleX;
+ this._normalScaleValueY = scaleY;
+ }
+ this._labelRenderer.setPosition(locContentSize.width / 2.0, locContentSize.height / 2.0);
+ },
+
+ /**
+ * Returns the "class name" of ccui.Text.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "Label";
+ },
+
+ /**
+ * Enables shadow style and sets color, offset and blur radius styles.
+ * @param {cc.Color} shadowColor
+ * @param {cc.Size} offset
+ * @param {Number} blurRadius
+ */
+ enableShadow: function (shadowColor, offset, blurRadius) {
+ this._labelRenderer.enableShadow(shadowColor, offset, blurRadius);
+ },
+
+ /**
+ * Enables outline style and sets outline's color and size.
+ * @param {cc.Color} outlineColor
+ * @param {cc.Size} outlineSize
+ */
+ enableOutline: function (outlineColor, outlineSize) {
+ this._labelRenderer.enableStroke(outlineColor, outlineSize);
+ },
+
+ /**
+ * Enables glow color
+ * @param glowColor
+ */
+ enableGlow: function (glowColor) {
+ if (this._type === ccui.Text.Type.TTF)
+ this._labelRenderer.enableGlow(glowColor);
+ },
+
+ /**
+ * Disables renderer's effect.
+ */
+ disableEffect: function () {
+ if (this._labelRenderer.disableEffect)
+ this._labelRenderer.disableEffect();
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.Text();
+ },
+
+ _copySpecialProperties: function (uiLabel) {
+ if (uiLabel instanceof ccui.Text) {
+ this.setFontName(uiLabel._fontName);
+ this.setFontSize(uiLabel.getFontSize());
+ this.setString(uiLabel.getString());
+ this.setTouchScaleChangeEnabled(uiLabel.touchScaleEnabled);
+ this.setTextAreaSize(uiLabel._textAreaSize);
+ this.setTextHorizontalAlignment(uiLabel._labelRenderer.getHorizontalAlignment());
+ this.setTextVerticalAlignment(uiLabel._labelRenderer.getVerticalAlignment());
+ this.setContentSize(uiLabel.getContentSize());
+ this.setTextColor(uiLabel.getTextColor());
+ }
+ },
+
+ _setBoundingWidth: function (value) {
+ this._textAreaSize.width = value;
+ this._labelRenderer._setBoundingWidth(value);
+ this._labelScaleChangedWithSize();
+ },
+ _setBoundingHeight: function (value) {
+ this._textAreaSize.height = value;
+ this._labelRenderer._setBoundingHeight(value);
+ this._labelScaleChangedWithSize();
+ },
+ _getBoundingWidth: function () {
+ return this._textAreaSize.width;
+ },
+ _getBoundingHeight: function () {
+ return this._textAreaSize.height;
+ },
+
+ _changePosition: function () {
+ this._adaptRenderers();
+ },
+
+ setColor: function (color) {
+ cc.ProtectedNode.prototype.setColor.call(this, color);
+ this._labelRenderer.setColor(color);
+ },
+
+ setTextColor: function (color) {
+ this._labelRenderer.setFontFillColor(color);
+ },
+
+ getTextColor: function () {
+ return this._labelRenderer._getFillStyle();
+ }
+});
+
+var _p = ccui.Text.prototype;
+
+// Extended properties
+/** @expose */
+_p.boundingWidth;
+cc.defineGetterSetter(_p, "boundingWidth", _p._getBoundingWidth, _p._setBoundingWidth);
+/** @expose */
+_p.boundingHeight;
+cc.defineGetterSetter(_p, "boundingHeight", _p._getBoundingHeight, _p._setBoundingHeight);
+/** @expose */
+_p.string;
+cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
+/** @expose */
+_p.stringLength;
+cc.defineGetterSetter(_p, "stringLength", _p.getStringLength);
+/** @expose */
+_p.font;
+cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
+/** @expose */
+_p.fontSize;
+cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
+/** @expose */
+_p.fontName;
+cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
+/** @expose */
+_p.textAlign;
+cc.defineGetterSetter(_p, "textAlign", _p.getTextHorizontalAlignment, _p.setTextHorizontalAlignment);
+/** @expose */
+_p.verticalAlign;
+cc.defineGetterSetter(_p, "verticalAlign", _p.getTextVerticalAlignment, _p.setTextVerticalAlignment);
+
+_p = null;
+
+/**
+ * allocates and initializes a UILabel.
+ * @deprecated since v3.0, please use new ccui.Text() instead.
+ * @return {ccui.Text}
+ */
+ccui.Label = ccui.Text.create = function (textContent, fontName, fontSize) {
+ return new ccui.Text(textContent, fontName, fontSize);
+};
+
+/**
+ * The zOrder value of ccui.Text's renderer.
+ * @constant
+ * @type {number}
+ */
+ccui.Text.RENDERER_ZORDER = -1;
+
+/**
+ * @ignore
+ */
+ccui.Text.Type = {
+ SYSTEM: 0,
+ TTF: 1
+};
diff --git a/extensions/ccui/uiwidgets/UITextAtlas.js b/extensions/ccui/uiwidgets/UITextAtlas.js
new file mode 100644
index 0000000000..98c4b89e63
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UITextAtlas.js
@@ -0,0 +1,236 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The text atlas control of Cocos UI.
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {String} string - Content string of the label
+ */
+ccui.TextAtlas = ccui.Widget.extend(/** @lends ccui.TextAtlas# */{
+ _labelAtlasRenderer: null,
+ _stringValue: "",
+ _charMapFileName: "",
+ _itemWidth: 0,
+ _itemHeight: 0,
+ _startCharMap: "",
+ _className: "TextAtlas",
+ _labelAtlasRendererAdaptDirty: null,
+
+ /**
+ * Allocates and initializes a UILabelAtlas.
+ * Constructor of ccui.TextAtlas, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {String} stringValue
+ * @param {String} charMapFile
+ * @param {number} itemWidth
+ * @param {number} itemHeight
+ * @param {String} startCharMap
+ * @example
+ * // example
+ * var uiLabelAtlas = new ccui.TextAtlas();
+ */
+ ctor: function (stringValue, charMapFile, itemWidth, itemHeight, startCharMap) {
+ ccui.Widget.prototype.ctor.call(this);
+ if (startCharMap !== undefined) {
+ this.setProperty(stringValue, charMapFile, itemWidth, itemHeight, startCharMap);
+ }
+ },
+
+ _initRenderer: function () {
+ this._labelAtlasRenderer = new cc.LabelAtlas();
+ this._labelAtlasRenderer.setAnchorPoint(cc.p(0.5, 0.5));
+ this.addProtectedChild(this._labelAtlasRenderer, ccui.TextAtlas.RENDERER_ZORDER, -1);
+
+ this._labelAtlasRenderer.addEventListener('load', function () {
+ this._updateContentSizeWithTextureSize(this._labelAtlasRenderer.getContentSize());
+ this._findLayout();
+ }, this);
+ },
+
+ /**
+ * initializes the UILabelAtlas with a string, a char map file(the atlas), the width and height of each element and the starting char of the atlas
+ * @param {String} stringValue
+ * @param {String} charMapFile
+ * @param {number} itemWidth
+ * @param {number} itemHeight
+ * @param {String} startCharMap
+ */
+ setProperty: function (stringValue, charMapFile, itemWidth, itemHeight, startCharMap) {
+ this._stringValue = stringValue;
+ this._charMapFileName = charMapFile;
+ this._itemWidth = itemWidth;
+ this._itemHeight = itemHeight;
+ this._startCharMap = startCharMap;
+
+ this._labelAtlasRenderer.initWithString(
+ stringValue,
+ this._charMapFileName,
+ this._itemWidth,
+ this._itemHeight,
+ this._startCharMap[0]
+ );
+
+ this._updateContentSizeWithTextureSize(this._labelAtlasRenderer.getContentSize());
+ this._labelAtlasRendererAdaptDirty = true;
+ },
+
+ /**
+ * Sets string value for ui text atlas.
+ * @param {String} value
+ */
+ setString: function (value) {
+ if (value === this._labelAtlasRenderer.getString())
+ return;
+ this._stringValue = value;
+ this._labelAtlasRenderer.setString(value);
+ this._updateContentSizeWithTextureSize(this._labelAtlasRenderer.getContentSize());
+ this._labelAtlasRendererAdaptDirty = true;
+ },
+
+ /**
+ * Sets string value for text atlas.
+ * @deprecated since v3.0, please use setString instead.
+ * @param {String} value
+ */
+ setStringValue: function (value) {
+ cc.log("Please use the setString");
+ this.setString(value);
+ },
+
+ /**
+ * get string value for text atlas.
+ * @deprecated since v3.0, please use getString instead.
+ * @returns {String}
+ */
+ getStringValue: function () {
+ cc.log("Please use the getString");
+ return this.getString();
+ },
+
+ /**
+ * get string value for ui text atlas.
+ * @returns {String}
+ */
+ getString: function () {
+ return this._labelAtlasRenderer.getString();
+ },
+
+ /**
+ * Returns the length of string.
+ * @returns {*|Number|long|int}
+ */
+ getStringLength: function () {
+ return this._labelAtlasRenderer.getStringLength();
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ this._labelAtlasRendererAdaptDirty = true;
+ },
+
+ _adaptRenderers: function () {
+ if (this._labelAtlasRendererAdaptDirty) {
+ this._labelAtlasScaleChangedWithSize();
+ this._labelAtlasRendererAdaptDirty = false;
+ }
+ },
+
+ /**
+ * Returns the renderer's content size
+ * @overrider
+ * @returns {cc.Size}
+ */
+ getVirtualRendererSize: function () {
+ return this._labelAtlasRenderer.getContentSize();
+ },
+
+ /**
+ * Returns the renderer of ccui.TextAtlas.
+ * @returns {cc.Node}
+ */
+ getVirtualRenderer: function () {
+ return this._labelAtlasRenderer;
+ },
+
+ _labelAtlasScaleChangedWithSize: function () {
+ var locRenderer = this._labelAtlasRenderer;
+ if (this._ignoreSize) {
+ locRenderer.setScale(1.0);
+ } else {
+ var textureSize = locRenderer.getContentSize();
+ if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
+ locRenderer.setScale(1.0);
+ return;
+ }
+ locRenderer.setScaleX(this._contentSize.width / textureSize.width);
+ locRenderer.setScaleY(this._contentSize.height / textureSize.height);
+ }
+ locRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
+ },
+
+ /**
+ * Returns the "class name" of ccui.TextAtlas.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "LabelAtlas";
+ },
+
+ _copySpecialProperties: function (labelAtlas) {
+ if (labelAtlas) {
+ this.setProperty(labelAtlas._stringValue, labelAtlas._charMapFileName, labelAtlas._itemWidth, labelAtlas._itemHeight, labelAtlas._startCharMap);
+ }
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.TextAtlas();
+ }
+});
+
+var _p = ccui.TextAtlas.prototype;
+
+// Extended properties
+/** @expose */
+_p.string;
+cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
+
+_p = null;
+
+/**
+ * allocates and initializes a UILabelAtlas.
+ * @deprecated since v3.0, please use new ccui.TextAtlas() instead.
+ * @return {ccui.TextAtlas}
+ */
+ccui.TextAtlas.create = function (stringValue, charMapFile, itemWidth, itemHeight, startCharMap) {
+ return new ccui.TextAtlas(stringValue, charMapFile, itemWidth, itemHeight, startCharMap);
+};
+
+// Constants
+/**
+ * The zOrder value of ccui.TextAtlas's renderer.
+ * @type {number}
+ */
+ccui.TextAtlas.RENDERER_ZORDER = -1;
diff --git a/extensions/ccui/uiwidgets/UITextBMFont.js b/extensions/ccui/uiwidgets/UITextBMFont.js
new file mode 100644
index 0000000000..25c92315cb
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UITextBMFont.js
@@ -0,0 +1,224 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The TextBMFont control of Cocos UI, it rendered by LabelBMFont.
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {String} string - Content string of the label
+ */
+ccui.LabelBMFont = ccui.TextBMFont = ccui.Widget.extend(/** @lends ccui.TextBMFont# */{
+ _labelBMFontRenderer: null,
+ _fntFileHasInit: false,
+ _fntFileName: "",
+ _stringValue: "",
+ _className: "TextBMFont",
+ _labelBMFontRendererAdaptDirty: true,
+
+ /**
+ * Allocates and initializes a TextBMFont.
+ * Constructor of ccui.TextBMFont. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {String} text
+ * @param {String} filename
+ * @example
+ * // example
+ * var uiLabelBMFont = new ccui.TextBMFont();
+ */
+ ctor: function (text, filename) {
+ ccui.Widget.prototype.ctor.call(this);
+ this._loader = new cc.Sprite.LoadManager();
+
+ if (filename !== undefined) {
+ this.setFntFile(filename);
+ this.setString(text);
+ }
+ },
+
+ _initRenderer: function () {
+ this._labelBMFontRenderer = new cc.LabelBMFont();
+ this.addProtectedChild(this._labelBMFontRenderer, ccui.TextBMFont.RENDERER_ZORDER, -1);
+ },
+
+ /**
+ * Initializes a bitmap font atlas with an initial string and the FNT file
+ * @param {String} fileName
+ */
+ setFntFile: function (fileName) {
+ if (!fileName)
+ return;
+ this._fntFileName = fileName;
+
+ this._fntFileHasInit = true;
+ this._labelBMFontRenderer.initWithString(this._stringValue, fileName);
+ this._updateContentSizeWithTextureSize(this._labelBMFontRenderer.getContentSize());
+ this._labelBMFontRendererAdaptDirty = true;
+
+ var _self = this;
+ var locRenderer = _self._labelBMFontRenderer;
+ if (!locRenderer._textureLoaded) {
+ locRenderer.addEventListener("load", function () {
+ _self.setFntFile(_self._fntFileName);
+ });
+ }
+ },
+
+ /**
+ * Sets string value for TextBMFont
+ * @deprecated since v3.0, please use setString instead.
+ * @param {String} value
+ */
+ setText: function (value) {
+ cc.log("Please use the setString");
+ this.setString(value);
+ },
+
+ /**
+ * Sets string value for TextBMFont
+ * @param {String} value
+ */
+ setString: function (value) {
+ this._loader.clear();
+ if (!this._labelBMFontRenderer._textureLoaded) {
+ this._loader.add(this._labelBMFontRenderer, function () {
+ this.setString(value);
+ }, this);
+ return;
+ }
+ if (value === this._labelBMFontRenderer.getString())
+ return;
+ this._stringValue = value;
+ this._labelBMFontRenderer.setString(value);
+ if (!this._fntFileHasInit)
+ return;
+ this._updateContentSizeWithTextureSize(this._labelBMFontRenderer.getContentSize());
+ this._labelBMFontRendererAdaptDirty = true;
+ },
+
+ /**
+ * Returns string value for TextBMFont.
+ * @returns {String}
+ */
+ getString: function () {
+ return this._stringValue;
+ },
+
+ /**
+ * Returns the length of TextBMFont's string.
+ * @returns {Number}
+ */
+ getStringLength: function () {
+ return this._labelBMFontRenderer.getStringLength();
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ this._labelBMFontRendererAdaptDirty = true;
+ },
+
+ _adaptRenderers: function () {
+ if (this._labelBMFontRendererAdaptDirty) {
+ this._labelBMFontScaleChangedWithSize();
+ this._labelBMFontRendererAdaptDirty = false;
+ }
+ },
+
+ /**
+ * Returns TextBMFont's content size
+ * @override
+ * @returns {cc.Size}
+ */
+ getVirtualRendererSize: function () {
+ return this._labelBMFontRenderer.getContentSize();
+ },
+
+ /**
+ * Returns the renderer of TextBMFont
+ * @override
+ * @returns {cc.Node}
+ */
+ getVirtualRenderer: function () {
+ return this._labelBMFontRenderer;
+ },
+
+ _labelBMFontScaleChangedWithSize: function () {
+ var locRenderer = this._labelBMFontRenderer;
+ if (this._ignoreSize)
+ locRenderer.setScale(1.0);
+ else {
+ var textureSize = locRenderer.getContentSize();
+ if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
+ locRenderer.setScale(1.0);
+ return;
+ }
+ locRenderer.setScaleX(this._contentSize.width / textureSize.width);
+ locRenderer.setScaleY(this._contentSize.height / textureSize.height);
+ }
+ locRenderer.setPosition(this._contentSize.width / 2.0, this._contentSize.height / 2.0);
+ },
+
+ /**
+ * Returns the "class name" of ccui.TextBMFont.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "TextBMFont";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.TextBMFont();
+ },
+
+ _copySpecialProperties: function (labelBMFont) {
+ this.setFntFile(labelBMFont._fntFileName);
+ this.setString(labelBMFont._stringValue);
+ }
+});
+
+var _p = ccui.TextBMFont.prototype;
+
+// Extended properties
+/** @expose */
+_p.string;
+cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
+
+_p = null;
+
+/**
+ * allocates and initializes a UILabelBMFont.
+ * @deprecated since v3.0, please use new ccui.TextBMFont() instead.
+ * @return {ccui.TextBMFont}
+ */
+ccui.TextBMFont.create = function (text, filename) {
+ return new ccui.TextBMFont(text, filename);
+};
+
+// Constants
+/**
+ * The zOrder value of TextBMFont's renderer.
+ * @constant
+ * @type {number}
+ */
+ccui.TextBMFont.RENDERER_ZORDER = -1;
diff --git a/extensions/ccui/uiwidgets/UITextField.js b/extensions/ccui/uiwidgets/UITextField.js
new file mode 100644
index 0000000000..7d59983238
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UITextField.js
@@ -0,0 +1,903 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @ignore
+ */
+//it's a private class, it's a renderer of ccui.TextField.
+ccui._TextFieldRenderer = cc.TextFieldTTF.extend({
+ _maxLengthEnabled: false,
+ _maxLength: 0,
+ _passwordEnabled: false,
+ _passwordStyleText: "",
+ _attachWithIME: false,
+ _detachWithIME: false,
+ _insertText: false,
+ _deleteBackward: false,
+ _className: "_TextFieldRenderer",
+
+ ctor: function () {
+ cc.TextFieldTTF.prototype.ctor.call(this);
+ this._maxLengthEnabled = false;
+ this._maxLength = 0;
+ this._passwordEnabled = false;
+ this._passwordStyleText = "*";
+ this._attachWithIME = false;
+ this._detachWithIME = false;
+ this._insertText = false;
+ this._deleteBackward = false;
+ },
+
+ onEnter: function () {
+ cc.TextFieldTTF.prototype.onEnter.call(this);
+ cc.TextFieldTTF.prototype.setDelegate.call(this, this);
+ },
+
+ onTextFieldAttachWithIME: function (sender) {
+ this.setAttachWithIME(true);
+ return false;
+ },
+
+ onTextFieldInsertText: function (sender, text, len) {
+ if (len === 1 && text === "\n")
+ return false;
+
+ this.setInsertText(true);
+ return (this._maxLengthEnabled) && (cc.TextFieldTTF.prototype.getCharCount.call(this) >= this._maxLength);
+ },
+
+ onTextFieldDeleteBackward: function (sender, delText, nLen) {
+ this.setDeleteBackward(true);
+ return false;
+ },
+
+ onTextFieldDetachWithIME: function (sender) {
+ this.setDetachWithIME(true);
+ return false;
+ },
+
+ insertText: function (text, len) {
+ var input_text = text;
+
+ if (text !== "\n"){
+ if (this._maxLengthEnabled){
+ var text_count = this.getString().length;
+ if (text_count >= this._maxLength){
+ // password
+ if (this._passwordEnabled)
+ this.setPasswordText(this.getString());
+ return;
+ }
+ }
+ }
+ cc.TextFieldTTF.prototype.insertText.call(this, input_text, len);
+
+ // password
+ if (this._passwordEnabled && cc.TextFieldTTF.prototype.getCharCount.call(this) > 0)
+ this.setPasswordText(this.getString());
+ },
+
+ deleteBackward: function () {
+ cc.TextFieldTTF.prototype.deleteBackward.call(this);
+
+ if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0 && this._passwordEnabled)
+ this.setPasswordText(this._inputText);
+ },
+
+ openIME: function () {
+ cc.TextFieldTTF.prototype.attachWithIME.call(this);
+ },
+
+ closeIME: function () {
+ cc.TextFieldTTF.prototype.detachWithIME.call(this);
+ },
+
+ setMaxLengthEnabled: function (enable) {
+ this._maxLengthEnabled = enable;
+ },
+
+ isMaxLengthEnabled: function () {
+ return this._maxLengthEnabled;
+ },
+
+ setMaxLength: function (length) {
+ this._maxLength = length;
+ },
+
+ getMaxLength: function () {
+ return this._maxLength;
+ },
+
+ getCharCount: function () {
+ return cc.TextFieldTTF.prototype.getCharCount.call(this);
+ },
+
+ setPasswordEnabled: function (enable) {
+ this._passwordEnabled = enable;
+ },
+
+ isPasswordEnabled: function () {
+ return this._passwordEnabled;
+ },
+
+ setPasswordStyleText: function (styleText) {
+ if (styleText.length > 1)
+ return;
+ var header = styleText.charCodeAt(0);
+ if (header < 33 || header > 126)
+ return;
+ this._passwordStyleText = styleText;
+ },
+
+ setPasswordText: function (text) {
+ var tempStr = "";
+ var text_count = text.length;
+ var max = text_count;
+
+ if (this._maxLengthEnabled && text_count > this._maxLength)
+ max = this._maxLength;
+
+ for (var i = 0; i < max; ++i)
+ tempStr += this._passwordStyleText;
+
+ cc.LabelTTF.prototype.setString.call(this, tempStr);
+ },
+
+ setAttachWithIME: function (attach) {
+ this._attachWithIME = attach;
+ },
+
+ getAttachWithIME: function () {
+ return this._attachWithIME;
+ },
+
+ setDetachWithIME: function (detach) {
+ this._detachWithIME = detach;
+ },
+
+ getDetachWithIME: function () {
+ return this._detachWithIME;
+ },
+
+ setInsertText: function (insert) {
+ this._insertText = insert;
+ },
+
+ getInsertText: function () {
+ return this._insertText;
+ },
+
+ setDeleteBackward: function (deleteBackward) {
+ this._deleteBackward = deleteBackward;
+ },
+
+ getDeleteBackward: function () {
+ return this._deleteBackward;
+ },
+
+ onDraw: function (sender) {
+ return false;
+ }
+});
+
+ccui._TextFieldRenderer.create = function (placeholder, fontName, fontSize) {
+ var ret = new ccui._TextFieldRenderer();
+ if (ret && ret.initWithString("", fontName, fontSize)) {
+ if (placeholder)
+ ret.setPlaceHolder(placeholder);
+ return ret;
+ }
+ return null;
+};
+
+/**
+ *
+ * @class
+ * @extends ccui.Widget
+ *
+ * @property {String} string - The content string of the label
+ * @property {String} placeHolder - The place holder of the text field
+ * @property {String} font - The text field font with a style string: e.g. "18px Verdana"
+ * @property {String} fontName - The text field font name
+ * @property {Number} fontSize - The text field font size
+ * @property {Boolean} maxLengthEnabled - Indicate whether max length limit is enabled
+ * @property {Number} maxLength - The max length of the text field
+ * @property {Boolean} passwordEnabled - Indicate whether the text field is for entering password
+ */
+ccui.TextField = ccui.Widget.extend(/** @lends ccui.TextField# */{
+ _textFieldRenderer: null,
+ _touchWidth: 0,
+ _touchHeight: 0,
+ _useTouchArea: false,
+ _textFieldEventListener: null,
+ _textFieldEventSelector: null,
+ _passwordStyleText: "",
+ _textFieldRendererAdaptDirty: true,
+ _fontName: "",
+ _fontSize: 12,
+
+ _ccEventCallback: null,
+
+ /**
+ * allocates and initializes a UITextField.
+ * Constructor of ccui.TextField. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {string} placeholder
+ * @param {string} fontName
+ * @param {Number} fontSize
+ * @example
+ * // example
+ * var uiTextField = new ccui.TextField();
+ */
+ ctor: function (placeholder, fontName, fontSize) {
+ ccui.Widget.prototype.ctor.call(this);
+ this.setTouchEnabled(true);
+ if (fontName)
+ this.setFontName(fontName);
+ if (fontSize)
+ this.setFontSize(fontSize);
+ if (placeholder)
+ this.setPlaceHolder(placeholder);
+ },
+
+ /**
+ * Calls parent class' onEnter and schedules update function.
+ * @override
+ */
+ onEnter: function () {
+ ccui.Widget.prototype.onEnter.call(this);
+ this.scheduleUpdate();
+ },
+
+ _initRenderer: function () {
+ this._textFieldRenderer = ccui._TextFieldRenderer.create("input words here", "Thonburi", 20);
+ this.addProtectedChild(this._textFieldRenderer, ccui.TextField.RENDERER_ZORDER, -1);
+ },
+
+ /**
+ * Sets touch size of ccui.TextField.
+ * @param {cc.Size} size
+ */
+ setTouchSize: function (size) {
+ this._touchWidth = size.width;
+ this._touchHeight = size.height;
+ },
+
+ /**
+ * Sets whether use touch area.
+ * @param enable
+ */
+ setTouchAreaEnabled: function(enable){
+ this._useTouchArea = enable;
+ },
+
+ /**
+ * Checks a point if is in ccui.TextField's space
+ * @param {cc.Point} pt
+ * @returns {boolean}
+ */
+ hitTest: function(pt){
+ if (this._useTouchArea) {
+ var nsp = this.convertToNodeSpace(pt);
+ var bb = cc.rect(
+ -this._touchWidth * this._anchorPoint.x,
+ -this._touchHeight * this._anchorPoint.y,
+ this._touchWidth, this._touchHeight
+ );
+
+ return ( nsp.x >= bb.x && nsp.x <= bb.x + bb.width &&
+ nsp.y >= bb.y && nsp.y <= bb.y + bb.height );
+ } else
+ return ccui.Widget.prototype.hitTest.call(this, pt);
+ },
+
+ /**
+ * Returns touch size of ccui.TextField.
+ * @returns {cc.Size}
+ */
+ getTouchSize: function () {
+ return cc.size(this._touchWidth, this._touchHeight);
+ },
+
+ /**
+ * Changes the string value of textField.
+ * @deprecated since v3.0, please use setString instead.
+ * @param {String} text
+ */
+ setText: function (text) {
+ cc.log("Please use the setString");
+ this.setString(text);
+ },
+
+ /**
+ * Changes the string value of textField.
+ * @param {String} text
+ */
+ setString: function (text) {
+ if (text == null)
+ return;
+
+ text = String(text);
+ if (this.isMaxLengthEnabled())
+ text = text.substr(0, this.getMaxLength());
+ if (this.isPasswordEnabled()) {
+ this._textFieldRenderer.setPasswordText(text);
+ this._textFieldRenderer.setString("");
+ this._textFieldRenderer.insertText(text, text.length);
+ } else
+ this._textFieldRenderer.setString(text);
+ this._textFieldRendererAdaptDirty = true;
+ this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
+ },
+
+ /**
+ * Sets the placeholder string.
+ * display this string if string equal "".
+ * @param {String} value
+ */
+ setPlaceHolder: function (value) {
+ this._textFieldRenderer.setPlaceHolder(value);
+ this._textFieldRendererAdaptDirty = true;
+ this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
+ },
+
+ /**
+ * Returns the placeholder string.
+ * @returns {String}
+ */
+ getPlaceHolder: function () {
+ return this._textFieldRenderer.getPlaceHolder();
+ },
+
+ /**
+ * Returns the color of ccui.TextField's place holder.
+ * @returns {cc.Color}
+ */
+ getPlaceHolderColor: function(){
+ return this._textFieldRenderer.getPlaceHolderColor();
+ },
+
+ /**
+ * Sets the place holder color to ccui.TextField.
+ * @param color
+ */
+ setPlaceHolderColor: function(color){
+ this._textFieldRenderer.setColorSpaceHolder(color);
+ },
+
+ /**
+ * Sets the text color to ccui.TextField
+ * @param textColor
+ */
+ setTextColor: function(textColor){
+ this._textFieldRenderer.setTextColor(textColor);
+ },
+
+ /**
+ * Sets font size for ccui.TextField.
+ * @param {Number} size
+ */
+ setFontSize: function (size) {
+ this._textFieldRenderer.setFontSize(size);
+ this._fontSize = size;
+ this._textFieldRendererAdaptDirty = true;
+ this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
+ },
+
+ /**
+ * Gets font size of ccui.TextField.
+ * @return {Number} size
+ */
+ getFontSize: function () {
+ return this._fontSize;
+ },
+
+ /**
+ * Sets font name for ccui.TextField
+ * @param {String} name
+ */
+ setFontName: function (name) {
+ this._textFieldRenderer.setFontName(name);
+ this._fontName = name;
+ this._textFieldRendererAdaptDirty = true;
+ this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
+ },
+
+ /**
+ * Returns font name of ccui.TextField.
+ * @return {String} font name
+ */
+ getFontName: function () {
+ return this._fontName;
+ },
+
+ /**
+ * detach with IME
+ */
+ didNotSelectSelf: function () {
+ this._textFieldRenderer.detachWithIME();
+ },
+
+ /**
+ * Returns textField string value
+ * @deprecated since v3.0, please use getString instead.
+ * @returns {String}
+ */
+ getStringValue: function () {
+ cc.log("Please use the getString");
+ return this.getString();
+ },
+
+ /**
+ * Returns string value of ccui.TextField.
+ * @returns {String}
+ */
+ getString: function () {
+ return this._textFieldRenderer.getString();
+ },
+
+ /**
+ * Returns the length of ccui.TextField.
+ * @returns {Number}
+ */
+ getStringLength: function(){
+ return this._textFieldRenderer.getStringLength();
+ },
+
+ /**
+ * The touch began event callback handler.
+ * @param {cc.Point} touchPoint
+ */
+ onTouchBegan: function (touchPoint, unusedEvent) {
+ var self = this;
+ var pass = ccui.Widget.prototype.onTouchBegan.call(self, touchPoint, unusedEvent);
+ if (self._hit) {
+ setTimeout(function(){
+ self._textFieldRenderer.attachWithIME();
+ }, 0);
+ }else{
+ setTimeout(function(){
+ self._textFieldRenderer.detachWithIME();
+ }, 0);
+ }
+ return pass;
+ },
+
+ /**
+ * Sets Whether to open string length limit for ccui.TextField.
+ * @param {Boolean} enable
+ */
+ setMaxLengthEnabled: function (enable) {
+ this._textFieldRenderer.setMaxLengthEnabled(enable);
+ },
+
+ /**
+ * Returns Whether to open string length limit.
+ * @returns {Boolean}
+ */
+ isMaxLengthEnabled: function () {
+ return this._textFieldRenderer.isMaxLengthEnabled();
+ },
+
+ /**
+ * Sets the max length of ccui.TextField. Only when you turn on the string length limit, it is valid.
+ * @param {number} length
+ */
+ setMaxLength: function (length) {
+ this._textFieldRenderer.setMaxLength(length);
+ this.setString(this.getString());
+ },
+
+ /**
+ * Returns the max length of ccui.TextField.
+ * @returns {number} length
+ */
+ getMaxLength: function () {
+ return this._textFieldRenderer.getMaxLength();
+ },
+
+ /**
+ * Sets whether to open setting string as password character.
+ * @param {Boolean} enable
+ */
+ setPasswordEnabled: function (enable) {
+ this._textFieldRenderer.setPasswordEnabled(enable);
+ },
+
+ /**
+ * Returns whether to open setting string as password character.
+ * @returns {Boolean}
+ */
+ isPasswordEnabled: function () {
+ return this._textFieldRenderer.isPasswordEnabled();
+ },
+
+ /**
+ * Sets the password style character, Only when you turn on setting string as password character, it is valid.
+ * @param styleText
+ */
+ setPasswordStyleText: function(styleText){
+ this._textFieldRenderer.setPasswordStyleText(styleText);
+ this._passwordStyleText = styleText;
+
+ this.setString(this.getString());
+ },
+
+ /**
+ * Returns the password style character.
+ * @returns {String}
+ */
+ getPasswordStyleText: function () {
+ return this._passwordStyleText;
+ },
+
+ update: function (dt) {
+ if (this.getDetachWithIME()) {
+ this._detachWithIMEEvent();
+ this.setDetachWithIME(false);
+ }
+ if (this.getAttachWithIME()) {
+ this._attachWithIMEEvent();
+ this.setAttachWithIME(false);
+ }
+ if (this.getInsertText()) {
+ this._textFieldRendererAdaptDirty = true;
+ this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
+
+ this._insertTextEvent();
+ this.setInsertText(false);
+ }
+ if (this.getDeleteBackward()) {
+ this._textFieldRendererAdaptDirty = true;
+ this._updateContentSizeWithTextureSize(this._textFieldRenderer.getContentSize());
+
+ this._deleteBackwardEvent();
+ this.setDeleteBackward(false);
+ }
+ },
+
+ /**
+ * Returns whether attach with IME.
+ * @returns {Boolean}
+ */
+ getAttachWithIME: function () {
+ return this._textFieldRenderer.getAttachWithIME();
+ },
+
+ /**
+ * Sets attach with IME.
+ * @param {Boolean} attach
+ */
+ setAttachWithIME: function (attach) {
+ this._textFieldRenderer.setAttachWithIME(attach);
+ },
+
+ /**
+ * Returns whether detach with IME.
+ * @returns {Boolean}
+ */
+ getDetachWithIME: function () {
+ return this._textFieldRenderer.getDetachWithIME();
+ },
+
+ /**
+ * Sets detach with IME.
+ * @param {Boolean} detach
+ */
+ setDetachWithIME: function (detach) {
+ this._textFieldRenderer.setDetachWithIME(detach);
+ },
+
+ /**
+ * Returns insertText string of ccui.TextField.
+ * @returns {String}
+ */
+ getInsertText: function () {
+ return this._textFieldRenderer.getInsertText();
+ },
+
+ /**
+ * Sets insertText string to ccui.TextField.
+ * @param {String} insertText
+ */
+ setInsertText: function (insertText) {
+ this._textFieldRenderer.setInsertText(insertText);
+ },
+
+ /**
+ * Returns the delete backward of ccui.TextField.
+ * @returns {Boolean}
+ */
+ getDeleteBackward: function () {
+ return this._textFieldRenderer.getDeleteBackward();
+ },
+
+ /**
+ * Sets the delete backward of ccui.TextField.
+ * @param {Boolean} deleteBackward
+ */
+ setDeleteBackward: function (deleteBackward) {
+ this._textFieldRenderer.setDeleteBackward(deleteBackward);
+ },
+
+ _attachWithIMEEvent: function () {
+ if(this._textFieldEventSelector){
+ if (this._textFieldEventListener)
+ this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_ATTACH_WITH_IME);
+ else
+ this._textFieldEventSelector(this, ccui.TextField.EVENT_ATTACH_WITH_IME);
+ }
+ if (this._ccEventCallback){
+ this._ccEventCallback(this, ccui.TextField.EVENT_ATTACH_WITH_IME);
+ }
+ },
+
+ _detachWithIMEEvent: function () {
+ if(this._textFieldEventSelector){
+ if (this._textFieldEventListener)
+ this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DETACH_WITH_IME);
+ else
+ this._textFieldEventSelector(this, ccui.TextField.EVENT_DETACH_WITH_IME);
+ }
+ if (this._ccEventCallback)
+ this._ccEventCallback(this, ccui.TextField.EVENT_DETACH_WITH_IME);
+ },
+
+ _insertTextEvent: function () {
+ if(this._textFieldEventSelector){
+ if (this._textFieldEventListener)
+ this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_INSERT_TEXT);
+ else
+ this._textFieldEventSelector(this, ccui.TextField.EVENT_INSERT_TEXT); //eventCallback
+ }
+ if (this._ccEventCallback)
+ this._ccEventCallback(this, ccui.TextField.EVENT_INSERT_TEXT);
+ },
+
+ _deleteBackwardEvent: function () {
+ if(this._textFieldEventSelector){
+ if (this._textFieldEventListener)
+ this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DELETE_BACKWARD);
+ else
+ this._textFieldEventSelector(this, ccui.TextField.EVENT_DELETE_BACKWARD); //eventCallback
+ }
+ if (this._ccEventCallback)
+ this._ccEventCallback(this, ccui.TextField.EVENT_DELETE_BACKWARD);
+ },
+
+ /**
+ * Adds event listener to cuci.TextField.
+ * @param {Object} [target=]
+ * @param {Function} selector
+ * @deprecated since v3.0, please use addEventListener instead.
+ */
+ addEventListenerTextField: function (selector, target) {
+ this.addEventListener(selector, target);
+ },
+
+ /**
+ * Adds event listener callback.
+ * @param {Object} [target=]
+ * @param {Function} selector
+ */
+ addEventListener: function(selector, target){
+ this._textFieldEventSelector = selector; //when target is undefined, _textFieldEventSelector is ccEventCallback.
+ this._textFieldEventListener = target;
+ },
+
+ _onSizeChanged: function () {
+ ccui.Widget.prototype._onSizeChanged.call(this);
+ this._textFieldRendererAdaptDirty = true;
+ },
+
+ _adaptRenderers: function(){
+ if (this._textFieldRendererAdaptDirty) {
+ this._textfieldRendererScaleChangedWithSize();
+ this._textFieldRendererAdaptDirty = false;
+ }
+ },
+
+ _textfieldRendererScaleChangedWithSize: function () {
+ if (!this._ignoreSize)
+ this._textFieldRenderer.setDimensions(this._contentSize);
+ this._textFieldRenderer.setPosition(this._contentSize.width / 2, this._contentSize.height / 2);
+ },
+
+ //@since v3.3
+ getAutoRenderSize: function(){
+ var virtualSize = this._textFieldRenderer.getContentSize();
+ if (!this._ignoreSize) {
+ this._textFieldRenderer.setDimensions(0, 0);
+ virtualSize = this._textFieldRenderer.getContentSize();
+ this._textFieldRenderer.setDimensions(this._contentSize.width, this._contentSize.height);
+ }
+ return virtualSize;
+ },
+
+ /**
+ * Returns the ccui.TextField's content size.
+ * @returns {cc.Size}
+ */
+ getVirtualRendererSize: function(){
+ return this._textFieldRenderer.getContentSize();
+ },
+
+ /**
+ * Returns the renderer of ccui.TextField.
+ * @returns {cc.Node}
+ */
+ getVirtualRenderer: function () {
+ return this._textFieldRenderer;
+ },
+
+ /**
+ * Returns the "class name" of ccui.TextField.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "TextField";
+ },
+
+ /**
+ * Open keyboard and receive input text.
+ * @return {Boolean}
+ */
+ attachWithIME: function () {
+ this._textFieldRenderer.attachWithIME();
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.TextField();
+ },
+
+ _copySpecialProperties: function (textField) {
+ this.setString(textField._textFieldRenderer.getString());
+ this.setPlaceHolder(textField.getString());
+ this.setFontSize(textField._textFieldRenderer.getFontSize());
+ this.setFontName(textField._textFieldRenderer.getFontName());
+ this.setMaxLengthEnabled(textField.isMaxLengthEnabled());
+ this.setMaxLength(textField.getMaxLength());
+ this.setPasswordEnabled(textField.isPasswordEnabled());
+ this.setPasswordStyleText(textField._passwordStyleText);
+ this.setAttachWithIME(textField.getAttachWithIME());
+ this.setDetachWithIME(textField.getDetachWithIME());
+ this.setInsertText(textField.getInsertText());
+ this.setDeleteBackward(textField.getDeleteBackward());
+ this._ccEventCallback = textField._ccEventCallback;
+ this._textFieldEventListener = textField._textFieldEventListener;
+ this._textFieldEventSelector = textField._textFieldEventSelector;
+ },
+
+ /**
+ * Sets the text area size to ccui.TextField.
+ * @param {cc.Size} size
+ */
+ setTextAreaSize: function(size){
+ this.setContentSize(size);
+ },
+
+ /**
+ * Sets the text horizontal alignment of ccui.TextField.
+ * @param alignment
+ */
+ setTextHorizontalAlignment: function(alignment){
+ this._textFieldRenderer.setHorizontalAlignment(alignment);
+ },
+
+ /**
+ * Sets the text vertical alignment of ccui.TextField.
+ * @param alignment
+ */
+ setTextVerticalAlignment: function(alignment){
+ this._textFieldRenderer.setVerticalAlignment(alignment);
+ },
+ _setFont: function (font) {
+ this._textFieldRenderer._setFont(font);
+ this._textFieldRendererAdaptDirty = true;
+ },
+
+ _getFont: function () {
+ return this._textFieldRenderer._getFont();
+ },
+
+ _changePosition: function(){
+ this._adaptRenderers();
+ }
+});
+
+/**
+ * Creates a ccui.TextField.
+ * @deprecated since v3.0, please use new ccui.TextField() instead.
+ * @param {String} placeholder
+ * @param {String} fontName
+ * @param {Number} fontSize
+ * @returns {ccui.TextField}
+ */
+ccui.TextField.create = function(placeholder, fontName, fontSize){
+ return new ccui.TextField(placeholder, fontName, fontSize);
+};
+
+var _p = ccui.TextField.prototype;
+
+// Extended properties
+/** @expose */
+_p.string;
+cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
+/** @expose */
+_p.placeHolder;
+cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder);
+/** @expose */
+_p.font;
+cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
+/** @expose */
+_p.fontSize;
+cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
+/** @expose */
+_p.fontName;
+cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
+/** @expose */
+_p.maxLengthEnabled;
+cc.defineGetterSetter(_p, "maxLengthEnabled", _p.isMaxLengthEnabled, _p.setMaxLengthEnabled);
+/** @expose */
+_p.maxLength;
+cc.defineGetterSetter(_p, "maxLength", _p.getMaxLength, _p.setMaxLength);
+/** @expose */
+_p.passwordEnabled;
+cc.defineGetterSetter(_p, "passwordEnabled", _p.isPasswordEnabled, _p.setPasswordEnabled);
+
+_p = null;
+
+// Constants
+//TextField event
+/**
+ * The attach with IME event flag of ccui.TextField
+ * @constant
+ * @type {number}
+ */
+ccui.TextField.EVENT_ATTACH_WITH_IME = 0;
+/**
+ * The detach with IME event flag of ccui.TextField
+ * @constant
+ * @type {number}
+ */
+ccui.TextField.EVENT_DETACH_WITH_IME = 1;
+/**
+ * The insert text event flag of ccui.TextField
+ * @constant
+ * @type {number}
+ */
+ccui.TextField.EVENT_INSERT_TEXT = 2;
+/**
+ * The delete backward event flag of ccui.TextField
+ * @constant
+ * @type {number}
+ */
+ccui.TextField.EVENT_DELETE_BACKWARD = 3;
+
+/**
+ * The zOrder value of ccui.TextField's renderer.
+ * @constant
+ * @type {number}
+ */
+ccui.TextField.RENDERER_ZORDER = -1;
\ No newline at end of file
diff --git a/extensions/ccui/uiwidgets/UIVideoPlayer.js b/extensions/ccui/uiwidgets/UIVideoPlayer.js
new file mode 100644
index 0000000000..e4e3351040
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UIVideoPlayer.js
@@ -0,0 +1,562 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @class
+ * @extends ccui.Widget
+ * @brief Displays a video file.
+ *
+ * @note VideoPlayer displays a video file based on DOM element
+ * VideoPlayer will be rendered above all other graphical elements.
+ *
+ * @property {String} path - The video path
+ */
+ccui.VideoPlayer = ccui.Widget.extend(/** @lends ccui.VideoPlayer# */{
+
+ _played: false,
+ _playing: false,
+ _stopped: true,
+
+ ctor: function (path) {
+ ccui.Widget.prototype.ctor.call(this);
+ this._EventList = {};
+ if (path)
+ this.setURL(path);
+ },
+
+ _createRenderCmd: function () {
+ return new ccui.VideoPlayer.RenderCmd(this);
+ },
+
+ visit: function () {
+ var cmd = this._renderCmd,
+ div = cmd._div,
+ container = cc.container,
+ eventManager = cc.eventManager;
+ if (this._visible) {
+ container.appendChild(cmd._video);
+ if (this._listener === null)
+ this._listener = cc.eventManager.addCustomListener(cc.game.EVENT_RESIZE, function () {
+ cmd.resize();
+ });
+ } else {
+ var hasChild = false;
+ if ('contains' in container) {
+ hasChild = container.contains(cmd._video);
+ } else {
+ hasChild = container.compareDocumentPosition(cmd._video) % 16;
+ }
+ if (hasChild)
+ container.removeChild(cmd._video);
+ eventManager.removeListener(cmd._listener);
+ cmd._listener = null;
+ }
+ cmd.updateStatus();
+ cmd.resize();
+ },
+
+ /**
+ * Set the video address
+ * Automatically replace extname
+ * All supported video formats will be added to the video
+ * @param {String} address
+ */
+ setURL: function (address) {
+ this._renderCmd.updateURL(address);
+ },
+
+ /**
+ * Get the video path
+ * @returns {String}
+ */
+ getURL: function () {
+ return this._renderCmd._url;
+ },
+
+ /**
+ * Play the video
+ */
+ play: function () {
+ var self = this,
+ video = this._renderCmd._video;
+ if (video) {
+ this._played = true;
+ video.pause();
+ if (this._stopped !== false || this._playing !== false || this._played !== true)
+ video.currentTime = 0;
+ if (ccui.VideoPlayer._polyfill.autoplayAfterOperation) {
+ setTimeout(function () {
+ video.play();
+ self._playing = true;
+ self._stopped = false;
+ }, 20);
+ } else {
+ video.play();
+ this._playing = true;
+ this._stopped = false;
+ }
+ }
+ },
+
+ /**
+ * Pause the video
+ */
+ pause: function () {
+ var video = this._renderCmd._video;
+ if (video && this._playing === true && this._stopped === false) {
+ video.pause();
+ this._playing = false;
+ }
+ },
+
+ /**
+ * Resume the video
+ */
+ resume: function () {
+ if (this._stopped === false && this._playing === false && this._played === true) {
+ this.play();
+ }
+ },
+
+ /**
+ * Stop the video
+ */
+ stop: function () {
+ var self = this,
+ video = this._renderCmd._video;
+ if (video) {
+ video.pause();
+ video.currentTime = 0;
+ this._playing = false;
+ this._stopped = true;
+ }
+
+ setTimeout(function () {
+ self._dispatchEvent(ccui.VideoPlayer.EventType.STOPPED);
+ }, 0);
+ },
+ /**
+ * Jump to the specified point in time
+ * @param {Number} sec
+ */
+ seekTo: function (sec) {
+ var video = this._renderCmd._video;
+ if (video) {
+ video.currentTime = sec;
+ if (ccui.VideoPlayer._polyfill.autoplayAfterOperation && this.isPlaying()) {
+ setTimeout(function () {
+ video.play();
+ }, 20);
+ }
+ }
+ },
+
+ /**
+ * Whether the video is playing
+ * @returns {boolean}
+ */
+ isPlaying: function () {
+ if (ccui.VideoPlayer._polyfill.autoplayAfterOperation && this._playing) {
+ setTimeout(function () {
+ video.play();
+ }, 20);
+ }
+ return this._playing;
+ },
+
+ /**
+ * Whether to keep the aspect ratio
+ */
+ setKeepAspectRatioEnabled: function (enable) {
+ cc.log("On the web is always keep the aspect ratio");
+ },
+ isKeepAspectRatioEnabled: function () {
+ return false;
+ },
+
+ /**
+ * Set whether the full screen
+ * May appear inconsistent in different browsers
+ * @param {boolean} enable
+ */
+ setFullScreenEnabled: function (enable) {
+ var video = this._renderCmd._video;
+ if (video) {
+ if (enable)
+ cc.screen.requestFullScreen(video);
+ else
+ cc.screen.exitFullScreen(video);
+ }
+ },
+
+ /**
+ * Determine whether already full screen
+ */
+ isFullScreenEnabled: function () {
+ cc.log("Can't know status");
+ },
+
+ /**
+ * The binding event
+ * @param {ccui.VideoPlayer.EventType} event
+ * @param {Function} callback
+ */
+ setEventListener: function (event, callback) {
+ this._EventList[event] = callback;
+ },
+
+ /**
+ * Delete events
+ * @param {ccui.VideoPlayer.EventType} event
+ */
+ removeEventListener: function (event) {
+ this._EventList[event] = null;
+ },
+
+ _dispatchEvent: function (event) {
+ var callback = this._EventList[event];
+ if (callback)
+ callback.call(this, this, this._renderCmd._video.src);
+ },
+
+ /**
+ * Trigger playing events
+ */
+ onPlayEvent: function () {
+ var list = this._EventList[ccui.VideoPlayer.EventType.PLAYING];
+ if (list)
+ for (var i = 0; i < list.length; i++)
+ list[i].call(this, this, this._renderCmd._video.src);
+ },
+
+ setContentSize: function (w, h) {
+ ccui.Widget.prototype.setContentSize.call(this, w, h);
+ if (h === undefined) {
+ h = w.height;
+ w = w.width;
+ }
+ this._renderCmd.changeSize(w, h);
+ },
+
+ cleanup: function () {
+ this._renderCmd.removeDom();
+ this.stopAllActions();
+ this.unscheduleAllCallbacks();
+ },
+
+ onEnter: function () {
+ ccui.Widget.prototype.onEnter.call(this);
+ var list = ccui.VideoPlayer.elements;
+ if (list.indexOf(this) === -1)
+ list.push(this);
+ },
+
+ onExit: function () {
+ ccui.Widget.prototype.onExit.call(this);
+ var list = ccui.VideoPlayer.elements;
+ var index = list.indexOf(this);
+ if (index !== -1)
+ list.splice(index, 1);
+ }
+
+});
+
+// VideoHTMLElement list
+ccui.VideoPlayer.elements = [];
+ccui.VideoPlayer.pauseElements = [];
+
+cc.eventManager.addCustomListener(cc.game.EVENT_HIDE, function () {
+ var list = ccui.VideoPlayer.elements;
+ for (var node, i = 0; i < list.length; i++) {
+ node = list[i];
+ if (list[i]._playing) {
+ node.pause();
+ ccui.VideoPlayer.pauseElements.push(node);
+ }
+ }
+});
+cc.eventManager.addCustomListener(cc.game.EVENT_SHOW, function () {
+ var list = ccui.VideoPlayer.pauseElements;
+ var node = list.pop();
+ while (node) {
+ node.play();
+ node = list.pop();
+ }
+});
+
+/**
+ * The VideoPlayer support list of events
+ * @type {{PLAYING: string, PAUSED: string, STOPPED: string, COMPLETED: string}}
+ */
+ccui.VideoPlayer.EventType = {
+ PLAYING: "play",
+ PAUSED: "pause",
+ STOPPED: "stop",
+ COMPLETED: "complete"
+};
+
+(function (video) {
+ /**
+ * Adapter various machines
+ * @devicePixelRatio Whether you need to consider devicePixelRatio calculated position
+ * @event To get the data using events
+ */
+ video._polyfill = {
+ devicePixelRatio: false,
+ event: "canplay",
+ canPlayType: []
+ };
+
+ (function () {
+ /**
+ * Some old browser only supports Theora encode video
+ * But native does not support this encode,
+ * so it is best to provide mp4 and webm or ogv file
+ */
+ var dom = document.createElement("video");
+ if (dom.canPlayType("video/ogg")) {
+ video._polyfill.canPlayType.push(".ogg");
+ video._polyfill.canPlayType.push(".ogv");
+ }
+ if (dom.canPlayType("video/mp4"))
+ video._polyfill.canPlayType.push(".mp4");
+ if (dom.canPlayType("video/webm"))
+ video._polyfill.canPlayType.push(".webm");
+ })();
+
+ if (cc.sys.OS_IOS === cc.sys.os) {
+ video._polyfill.devicePixelRatio = true;
+ video._polyfill.event = "progress";
+ }
+ if (cc.sys.browserType === cc.sys.BROWSER_TYPE_FIREFOX) {
+ video._polyfill.autoplayAfterOperation = true;
+ }
+
+ var style = document.createElement("style");
+ style.innerHTML = ".cocosVideo:-moz-full-screen{transform:matrix(1,0,0,1,0,0) !important;}" +
+ ".cocosVideo:full-screen{transform:matrix(1,0,0,1,0,0) !important;}" +
+ ".cocosVideo:-webkit-full-screen{transform:matrix(1,0,0,1,0,0) !important;}";
+ document.head.appendChild(style);
+
+})(ccui.VideoPlayer);
+
+(function (polyfill) {
+
+ var RenderCmd = null;
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ RenderCmd = cc.Node.WebGLRenderCmd;
+ } else {
+ RenderCmd = cc.Node.CanvasRenderCmd;
+ }
+
+ ccui.VideoPlayer.RenderCmd = function (node) {
+ this._rootCtor(node);
+ this._listener = null;
+ this._url = "";
+ this.initStyle();
+ };
+
+ var proto = ccui.VideoPlayer.RenderCmd.prototype = Object.create(RenderCmd.prototype);
+ proto.constructor = ccui.VideoPlayer.RenderCmd;
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+ this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
+ };
+
+ proto.updateStatus = function () {
+ polyfill.devicePixelRatio = cc.view.isRetinaEnabled();
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ if (locFlag & flags.transformDirty) {
+ //update the transform
+ this.transform(this.getParentRenderCmd(), true);
+ this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
+ this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty ^ this._dirtyFlag;
+ }
+
+ if (locFlag & flags.orderDirty) {
+ this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
+ }
+ };
+
+ proto.resize = function (view) {
+ view = view || cc.view;
+ var node = this._node,
+ eventManager = cc.eventManager;
+ if (node._parent && node._visible)
+ this.updateMatrix(this._worldTransform, view._scaleX, view._scaleY);
+ else {
+ eventManager.removeListener(this._listener);
+ this._listener = null;
+ }
+ };
+
+ proto.updateMatrix = function (t, scaleX, scaleY) {
+ var node = this._node;
+ if (polyfill.devicePixelRatio) {
+ var dpr = cc.view.getDevicePixelRatio();
+ scaleX = scaleX / dpr;
+ scaleY = scaleY / dpr;
+ }
+ if (this._loaded === false) return;
+ var containerStyle = cc.game.container.style,
+ offsetX = parseInt(containerStyle.paddingLeft),
+ offsetY = parseInt(containerStyle.paddingBottom),
+ cw = node._contentSize.width,
+ ch = node._contentSize.height;
+ var a = t.a * scaleX,
+ b = t.b,
+ c = t.c,
+ d = t.d * scaleY,
+ tx = offsetX + t.tx * scaleX - cw / 2 + cw * node._scaleX / 2 * scaleX,
+ ty = offsetY + t.ty * scaleY - ch / 2 + ch * node._scaleY / 2 * scaleY;
+ var matrix = "matrix(" + a + "," + b + "," + c + "," + d + "," + tx + "," + -ty + ")";
+ this._video.style["transform"] = matrix;
+ this._video.style["-webkit-transform"] = matrix;
+ };
+
+ proto.updateURL = function (path) {
+ var source, video, hasChild, container, extname;
+ var node = this._node;
+
+ if (this._url == path)
+ return;
+
+ this._url = path;
+
+ if (cc.loader.resPath && !/^http/.test(path))
+ path = cc.path.join(cc.loader.resPath, path);
+
+ hasChild = false;
+ container = cc.container;
+ if ('contains' in container) {
+ hasChild = container.contains(this._video);
+ } else {
+ hasChild = container.compareDocumentPosition(this._video) % 16;
+ }
+ if (hasChild)
+ container.removeChild(this._video);
+
+ this._video = document.createElement("video");
+ video = this._video;
+ this.bindEvent();
+ var self = this;
+
+ var cb = function () {
+ if (self._loaded == true)
+ return;
+ self._loaded = true;
+ self.changeSize();
+ self.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ video.removeEventListener(polyfill.event, cb);
+ video.currentTime = 0;
+ video.style["visibility"] = "visible";
+ //IOS does not display video images
+ video.play();
+ if (!node._played) {
+ video.pause();
+ video.currentTime = 0;
+ }
+ };
+ video.addEventListener(polyfill.event, cb);
+
+ //video.controls = "controls";
+ video.preload = "metadata";
+ video.style["visibility"] = "hidden";
+ this._loaded = false;
+ node._played = false;
+ node._playing = false;
+ node._stopped = true;
+ this.initStyle();
+ this._node.visit();
+
+ source = document.createElement("source");
+ source.src = path;
+ video.appendChild(source);
+
+ extname = cc.path.extname(path);
+ for (var i = 0; i < polyfill.canPlayType.length; i++) {
+ if (extname !== polyfill.canPlayType[i]) {
+ source = document.createElement("source");
+ source.src = path.replace(extname, polyfill.canPlayType[i]);
+ video.appendChild(source);
+ }
+ }
+ };
+
+ proto.bindEvent = function () {
+ var self = this,
+ node = this._node,
+ video = this._video;
+ //binding event
+ video.addEventListener("ended", function () {
+ node._renderCmd.updateMatrix(self._worldTransform, cc.view._scaleX, cc.view._scaleY);
+ node._playing = false;
+ node._dispatchEvent(ccui.VideoPlayer.EventType.COMPLETED);
+ });
+ video.addEventListener("play", function () {
+ node._dispatchEvent(ccui.VideoPlayer.EventType.PLAYING);
+ });
+ video.addEventListener("pause", function () {
+ node._dispatchEvent(ccui.VideoPlayer.EventType.PAUSED);
+ });
+ };
+
+ proto.initStyle = function () {
+ if (!this._video) return;
+ var video = this._video;
+ video.style.position = "absolute";
+ video.style.bottom = "0px";
+ video.style.left = "0px";
+ video.className = "cocosVideo";
+ };
+
+ proto.changeSize = function (w, h) {
+ var contentSize = this._node._contentSize;
+ w = w || contentSize.width;
+ h = h || contentSize.height;
+ var video = this._video;
+ if (video) {
+ if (w !== 0)
+ video.width = w;
+ if (h !== 0)
+ video.height = h;
+ }
+ };
+
+ proto.removeDom = function () {
+ var video = this._video;
+ if (video) {
+ var hasChild = false;
+ if ('contains' in cc.container) {
+ hasChild = cc.container.contains(video);
+ } else {
+ hasChild = cc.container.compareDocumentPosition(video) % 16;
+ }
+ if (hasChild)
+ cc.container.removeChild(video);
+ }
+ };
+
+})(ccui.VideoPlayer._polyfill);
diff --git a/extensions/ccui/uiwidgets/UIWebView.js b/extensions/ccui/uiwidgets/UIWebView.js
new file mode 100644
index 0000000000..b301a9580f
--- /dev/null
+++ b/extensions/ccui/uiwidgets/UIWebView.js
@@ -0,0 +1,423 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @class
+ * @extends ccui.Widget
+ * @brief A View that displays web pages.
+ *
+ * @note WebView displays web pages based on DOM element
+ * WebView will be rendered above all other graphical elements.
+ *
+ * @property {String} path - The url to be shown in the web view
+ */
+ccui.WebView = ccui.Widget.extend(/** @lends ccui.WebView# */{
+
+ ctor: function (path) {
+ ccui.Widget.prototype.ctor.call(this);
+ this._EventList = {};
+ if (path)
+ this.loadURL(path);
+ },
+
+ visit: function () {
+ var cmd = this._renderCmd,
+ div = cmd._div,
+ container = cc.container,
+ eventManager = cc.eventManager;
+ if (this._visible) {
+ container.appendChild(div);
+ if (this._listener === null)
+ this._listener = eventManager.addCustomListener(cc.game.EVENT_RESIZE, function () {
+ cmd.resize();
+ });
+ } else {
+ var hasChild = false;
+ if ('contains' in container) {
+ hasChild = container.contains(div);
+ } else {
+ hasChild = container.compareDocumentPosition(div) % 16;
+ }
+ if (hasChild)
+ container.removeChild(div);
+ var list = eventManager._listenersMap[cc.game.EVENT_RESIZE].getFixedPriorityListeners();
+ eventManager._removeListenerInVector(list, cmd._listener);
+ cmd._listener = null;
+ }
+ cmd.updateStatus();
+ cmd.resize(cc.view);
+ },
+
+ setJavascriptInterfaceScheme: function (scheme) {
+ },
+ loadData: function (data, MIMEType, encoding, baseURL) {
+ },
+ loadHTMLString: function (string, baseURL) {
+ },
+
+
+ /**
+ * Load an URL
+ * @param {String} url
+ */
+ loadURL: function (url) {
+ this._renderCmd.updateURL(url);
+ this._dispatchEvent(ccui.WebView.EventType.LOADING);
+ },
+
+ /**
+ * Stop loading
+ */
+ stopLoading: function () {
+ cc.log("Web does not support loading");
+ },
+
+ /**
+ * Reload the WebView
+ */
+ reload: function () {
+ var iframe = this._renderCmd._iframe;
+ if (iframe) {
+ var win = iframe.contentWindow;
+ if (win && win.location)
+ win.location.reload();
+ }
+ },
+
+ /**
+ * Determine whether to go back
+ */
+ canGoBack: function () {
+ cc.log("Web does not support query history");
+ return true;
+ },
+
+ /**
+ * Determine whether to go forward
+ */
+ canGoForward: function () {
+ cc.log("Web does not support query history");
+ return true;
+ },
+
+ /**
+ * go back
+ */
+ goBack: function () {
+ try {
+ if (ccui.WebView._polyfill.closeHistory)
+ return cc.log("The current browser does not support the GoBack");
+ var iframe = this._renderCmd._iframe;
+ if (iframe) {
+ var win = iframe.contentWindow;
+ if (win && win.location)
+ try {
+ win.history.back.call(win);
+ } catch (error) {
+ win.history.back();
+ }
+ }
+ } catch (err) {
+ cc.log(err);
+ }
+ },
+
+ /**
+ * go forward
+ */
+ goForward: function () {
+ try {
+ if (ccui.WebView._polyfill.closeHistory)
+ return cc.log("The current browser does not support the GoForward");
+ var iframe = this._renderCmd._iframe;
+ if (iframe) {
+ var win = iframe.contentWindow;
+ if (win && win.location)
+ try {
+ win.history.forward.call(win);
+ } catch (error) {
+ win.history.forward();
+ }
+ }
+ } catch (err) {
+ cc.log(err);
+ }
+ },
+
+ /**
+ * In the webview execution within a period of js string
+ * @param {String} str
+ */
+ evaluateJS: function (str) {
+ var iframe = this._renderCmd._iframe;
+ if (iframe) {
+ var win = iframe.contentWindow;
+ try {
+ win.eval(str);
+ this._dispatchEvent(ccui.WebView.EventType.JS_EVALUATED);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+ },
+
+ /**
+ * Limited scale
+ */
+ setScalesPageToFit: function () {
+ cc.log("Web does not support zoom");
+ },
+
+ /**
+ * The binding event
+ * @param {ccui.WebView.EventType} event
+ * @param {Function} callback
+ */
+ setEventListener: function (event, callback) {
+ this._EventList[event] = callback;
+ },
+
+ /**
+ * Delete events
+ * @param {ccui.WebView.EventType} event
+ */
+ removeEventListener: function (event) {
+ this._EventList[event] = null;
+ },
+
+ _dispatchEvent: function (event) {
+ var callback = this._EventList[event];
+ if (callback)
+ callback.call(this, this, this._renderCmd._iframe.src);
+ },
+
+ _createRenderCmd: function () {
+ return new ccui.WebView.RenderCmd(this);
+ },
+
+ /**
+ * Set the contentSize
+ * @param {Number} w
+ * @param {Number} h
+ */
+ setContentSize: function (w, h) {
+ ccui.Widget.prototype.setContentSize.call(this, w, h);
+ if (h === undefined) {
+ h = w.height;
+ w = w.width;
+ }
+ this._renderCmd.changeSize(w, h);
+ },
+
+ /**
+ * remove node
+ */
+ cleanup: function () {
+ this._renderCmd.removeDom();
+ this.stopAllActions();
+ this.unscheduleAllCallbacks();
+ }
+});
+
+/**
+ * The WebView support list of events
+ * @type {{LOADING: string, LOADED: string, ERROR: string}}
+ */
+ccui.WebView.EventType = {
+ LOADING: "loading",
+ LOADED: "load",
+ ERROR: "error",
+ JS_EVALUATED: "js"
+};
+
+(function () {
+
+ var polyfill = ccui.WebView._polyfill = {
+ devicePixelRatio: false,
+ enableDiv: false
+ };
+
+ if (cc.sys.os === cc.sys.OS_IOS)
+ polyfill.enableDiv = true;
+
+ if (cc.sys.isMobile) {
+ if (cc.sys.browserType === cc.sys.BROWSER_TYPE_FIREFOX) {
+ polyfill.enableBG = true;
+ }
+ } else {
+ if (cc.sys.browserType === cc.sys.BROWSER_TYPE_IE) {
+ polyfill.closeHistory = true;
+ }
+ }
+
+
+})();
+
+(function (polyfill) {
+
+ var RenderCmd = null;
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ RenderCmd = cc.Node.WebGLRenderCmd;
+ } else {
+ RenderCmd = cc.Node.CanvasRenderCmd;
+ }
+
+ ccui.WebView.RenderCmd = function (node) {
+ this._rootCtor(node);
+
+ this._div = null;
+ this._iframe = null;
+
+ if (polyfill.enableDiv) {
+ this._div = document.createElement("div");
+ this._div.style["-webkit-overflow"] = "auto";
+ this._div.style["-webkit-overflow-scrolling"] = "touch";
+ this._iframe = document.createElement("iframe");
+ this._iframe.style["width"] = "100%";
+ this._iframe.style["height"] = "100%";
+ this._div.appendChild(this._iframe);
+ } else {
+ this._div = this._iframe = document.createElement("iframe");
+ }
+
+ if (polyfill.enableBG)
+ this._div.style["background"] = "#FFF";
+
+ this._iframe.addEventListener("load", function () {
+ node._dispatchEvent(ccui.WebView.EventType.LOADED);
+ });
+ this._iframe.addEventListener("error", function () {
+ node._dispatchEvent(ccui.WebView.EventType.ERROR);
+ });
+ this._div.style["background"] = "#FFF";
+ this._div.style.height = "200px";
+ this._div.style.width = "300px";
+ this._div.style.overflow = "scroll";
+ this._div.style["border"] = "none";
+ this._listener = null;
+ this.initStyle();
+ };
+
+ var proto = ccui.WebView.RenderCmd.prototype = Object.create(RenderCmd.prototype);
+ proto.constructor = ccui.WebView.RenderCmd;
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+ this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
+ };
+
+ proto.updateStatus = function () {
+ polyfill.devicePixelRatio = cc.view.isRetinaEnabled();
+ var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
+ if (locFlag & flags.transformDirty) {
+ //update the transform
+ this.transform(this.getParentRenderCmd(), true);
+ this.updateMatrix(this._worldTransform, cc.view._scaleX, cc.view._scaleY);
+ this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty ^ this._dirtyFlag;
+ }
+
+ if (locFlag & flags.orderDirty) {
+ this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
+ }
+ };
+
+ proto.resize = function (view) {
+ view = view || cc.view;
+ var node = this._node,
+ eventManager = cc.eventManager;
+ if (node._parent && node._visible)
+ this.updateMatrix(this._worldTransform, view._scaleX, view._scaleY);
+ else {
+ var list = eventManager._listenersMap[cc.game.EVENT_RESIZE].getFixedPriorityListeners();
+ eventManager._removeListenerInVector(list, this._listener);
+ this._listener = null;
+ }
+ };
+
+ proto.updateMatrix = function (t, scaleX, scaleY) {
+ var node = this._node;
+ if (polyfill.devicePixelRatio) {
+ var dpr = cc.view.getDevicePixelRatio();
+ scaleX = scaleX / dpr;
+ scaleY = scaleY / dpr;
+ }
+ if (this._loaded === false) return;
+ var containerStyle = cc.game.container.style,
+ offsetX = parseInt(containerStyle.paddingLeft),
+ offsetY = parseInt(containerStyle.paddingBottom),
+ cw = node._contentSize.width,
+ ch = node._contentSize.height;
+ var a = t.a * scaleX,
+ b = t.b,
+ c = t.c,
+ d = t.d * scaleY,
+ tx = offsetX + t.tx * scaleX - cw / 2 + cw * node._scaleX / 2 * scaleX,
+ ty = offsetY + t.ty * scaleY - ch / 2 + ch * node._scaleY / 2 * scaleY;
+ var matrix = "matrix(" + a + "," + b + "," + c + "," + d + "," + tx + "," + -ty + ")";
+ this._div.style["transform"] = matrix;
+ this._div.style["-webkit-transform"] = matrix;
+ };
+
+ proto.initStyle = function () {
+ if (!this._div) return;
+ var div = this._div;
+ div.style.position = "absolute";
+ div.style.bottom = "0px";
+ div.style.left = "0px";
+ };
+
+ proto.updateURL = function (url) {
+ var iframe = this._iframe;
+ iframe.src = url;
+ var self = this;
+ var cb = function () {
+ self._loaded = true;
+ iframe.removeEventListener("load", cb);
+ };
+ iframe.addEventListener("load", cb);
+ };
+
+ proto.changeSize = function (w, h) {
+ var div = this._div;
+ if (div) {
+ div.style["width"] = w + "px";
+ div.style["height"] = h + "px";
+ }
+ };
+
+ proto.removeDom = function () {
+ var div = this._div;
+ if (div) {
+ var hasChild = false;
+ if ('contains' in cc.container) {
+ hasChild = cc.container.contains(div);
+ } else {
+ hasChild = cc.container.compareDocumentPosition(div) % 16;
+ }
+ if (hasChild)
+ cc.container.removeChild(div);
+ }
+ };
+
+})(ccui.WebView._polyfill);
diff --git a/extensions/ccui/uiwidgets/scroll-widget/UIListView.js b/extensions/ccui/uiwidgets/scroll-widget/UIListView.js
new file mode 100644
index 0000000000..3d0f673bc6
--- /dev/null
+++ b/extensions/ccui/uiwidgets/scroll-widget/UIListView.js
@@ -0,0 +1,1085 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The list view control of Cocos UI.
+ * @class
+ * @extends ccui.ScrollView
+ * @example
+ * var listView = new ccui.ListView();
+ * // set list view ex direction
+ * listView.setDirection(ccui.ScrollView.DIR_VERTICAL);
+ * listView.setTouchEnabled(true);
+ * listView.setBounceEnabled(true);
+ * listView.setBackGroundImage("res/cocosui/green_edit.png");
+ * listView.setBackGroundImageScale9Enabled(true);
+ * listView.setContentSize(cc.size(240, 130));
+ * this.addChild(listView);
+ */
+ccui.ListView = ccui.ScrollView.extend(/** @lends ccui.ListView# */{
+ _model: null,
+ _items: null,
+ _gravity: null,
+ _itemsMargin: 0,
+
+ _curSelectedIndex: 0,
+ _refreshViewDirty: true,
+
+ _listViewEventListener: null,
+ _listViewEventSelector: null,
+ _ccListViewEventCallback: null,
+ _magneticAllowedOutOfBoundary: true,
+ _magneticType: 0,
+ _className: "ListView",
+
+ /**
+ * allocates and initializes a UIListView.
+ * Constructor of ccui.ListView, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @example
+ * // example
+ * var aListView = new ccui.ListView();
+ */
+ ctor: function () {
+ this._items = [];
+ ccui.ScrollView.prototype.ctor.call(this);
+ this._gravity = ccui.ListView.GRAVITY_CENTER_VERTICAL;
+ this.setTouchEnabled(true);
+ this.setDirection(ccui.ScrollView.DIR_VERTICAL);
+ },
+
+ /**
+ * Sets a item model for ListView. A model will be cloned for adding default item.
+ * @param {ccui.Widget} model
+ */
+ setItemModel: function (model) {
+ if (!model) {
+ cc.log("Can't set a null to item model!");
+ return;
+ }
+
+ this._model = model;
+ },
+
+ _handleReleaseLogic: function (touch) {
+ ccui.ScrollView.prototype._handleReleaseLogic.call(this, touch);
+
+ if (!this._autoScrolling) {
+ this._startMagneticScroll();
+ }
+ },
+
+ _onItemListChanged: function () {
+ this._outOfBoundaryAmountDirty = true;
+ },
+
+ _updateInnerContainerSize: function () {
+ var i, locItems = this._items, length;
+ switch (this.direction) {
+ case ccui.ScrollView.DIR_VERTICAL:
+ length = locItems.length;
+ var totalHeight = (length - 1) * this._itemsMargin;
+ for (i = 0; i < length; i++) {
+ totalHeight += locItems[i].getContentSize().height;
+ }
+ this.setInnerContainerSize(cc.size(this._contentSize.width, totalHeight));
+ break;
+ case ccui.ScrollView.DIR_HORIZONTAL:
+ length = locItems.length;
+ var totalWidth = (length - 1) * this._itemsMargin;
+ for (i = 0; i < length; i++) {
+ totalWidth += locItems[i].getContentSize().width;
+ }
+ this.setInnerContainerSize(cc.size(totalWidth, this._contentSize.height));
+ break;
+ default:
+ break;
+ }
+ },
+
+ _remedyLayoutParameter: function (item) {
+ cc.assert(null != item, "ListView Item can't be nil!");
+
+ var linearLayoutParameter = item.getLayoutParameter(ccui.LayoutParameter.LINEAR);
+ var isLayoutParameterExists = true;
+ if (!linearLayoutParameter) {
+ linearLayoutParameter = new ccui.LinearLayoutParameter();
+ isLayoutParameterExists = false;
+ }
+ var itemIndex = this.getIndex(item);
+ switch (this.direction) {
+ case ccui.ScrollView.DIR_VERTICAL:
+ this._remedyVerticalLayoutParameter(linearLayoutParameter, itemIndex);
+ break;
+ case ccui.ScrollView.DIR_HORIZONTAL:
+ this._remedyHorizontalLayoutParameter(linearLayoutParameter, itemIndex);
+ break;
+ default:
+ break;
+ }
+ if (!isLayoutParameterExists)
+ item.setLayoutParameter(linearLayoutParameter);
+ },
+
+ //@since v3.3
+ _remedyVerticalLayoutParameter: function (layoutParameter, itemIndex) {
+ cc.assert(null != layoutParameter, "Layout parameter can't be nil!");
+
+ switch (this._gravity) {
+ case ccui.ListView.GRAVITY_LEFT:
+ layoutParameter.setGravity(ccui.LinearLayoutParameter.LEFT);
+ break;
+ case ccui.ListView.GRAVITY_RIGHT:
+ layoutParameter.setGravity(ccui.LinearLayoutParameter.RIGHT);
+ break;
+ case ccui.ListView.GRAVITY_CENTER_HORIZONTAL:
+ layoutParameter.setGravity(ccui.LinearLayoutParameter.CENTER_HORIZONTAL);
+ break;
+ default:
+ break;
+ }
+ if (0 === itemIndex)
+ layoutParameter.setMargin(ccui.MarginZero());
+ else
+ layoutParameter.setMargin(new ccui.Margin(0.0, this._itemsMargin, 0.0, 0.0));
+ },
+
+ //@since v3.3
+ _remedyHorizontalLayoutParameter: function (layoutParameter, itemIndex) {
+ cc.assert(null != layoutParameter, "Layout parameter can't be nil!");
+
+ switch (this._gravity) {
+ case ccui.ListView.GRAVITY_TOP:
+ layoutParameter.setGravity(ccui.LinearLayoutParameter.TOP);
+ break;
+ case ccui.ListView.GRAVITY_BOTTOM:
+ layoutParameter.setGravity(ccui.LinearLayoutParameter.BOTTOM);
+ break;
+ case ccui.ListView.GRAVITY_CENTER_VERTICAL:
+ layoutParameter.setGravity(ccui.LinearLayoutParameter.CENTER_VERTICAL);
+ break;
+ default:
+ break;
+ }
+ if (0 === itemIndex)
+ layoutParameter.setMargin(ccui.MarginZero());
+ else
+ layoutParameter.setMargin(new ccui.Margin(this._itemsMargin, 0.0, 0.0, 0.0));
+ },
+
+ /**
+ * Push back a default item(create by a cloned model) into ListView.
+ */
+ pushBackDefaultItem: function () {
+ if (this._model == null)
+ return;
+ var newItem = this._model.clone();
+ this._remedyLayoutParameter(newItem);
+ this.addChild(newItem);
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Insert a default item(create by a cloned model) into ListView.
+ * @param {Number} index
+ */
+ insertDefaultItem: function (index) {
+ if (this._model == null)
+ return;
+ var newItem = this._model.clone();
+ this._items.splice(index, 0, newItem);
+ ccui.ScrollView.prototype.addChild.call(this, newItem);
+ this._remedyLayoutParameter(newItem);
+
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Push back custom item into ListView.
+ * @param {ccui.Widget} item
+ */
+ pushBackCustomItem: function (item) {
+ this._remedyLayoutParameter(item);
+ this.addChild(item);
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * add child to ListView
+ * @override
+ * @param {cc.Node} widget
+ * @param {Number} [zOrder]
+ * @param {Number|String} [tag] tag or name
+ */
+ addChild: function (widget, zOrder, tag) {
+ if (widget) {
+ zOrder = zOrder || widget.getLocalZOrder();
+ tag = tag || widget.getName();
+ ccui.ScrollView.prototype.addChild.call(this, widget, zOrder, tag);
+ if (widget instanceof ccui.Widget) {
+ this._items.push(widget);
+ this._onItemListChanged();
+ }
+ }
+ },
+
+ /**
+ * remove child from ListView
+ * @override
+ * @param {cc.Node} widget
+ * @param {Boolean} [cleanup=true]
+ */
+ removeChild: function (widget, cleanup) {
+ if (widget) {
+ var index = this._items.indexOf(widget);
+ if (index > -1)
+ this._items.splice(index, 1);
+
+ this._onItemListChanged();
+
+ ccui.ScrollView.prototype.removeChild.call(this, widget, cleanup);
+ }
+ },
+
+ /**
+ * Removes all children from ccui.ListView.
+ */
+ removeAllChildren: function () {
+ this.removeAllChildrenWithCleanup(true);
+ },
+
+ /**
+ * Removes all children from ccui.ListView and do a cleanup all running actions depending on the cleanup parameter.
+ * @param {Boolean} cleanup
+ */
+ removeAllChildrenWithCleanup: function (cleanup) {
+ ccui.ScrollView.prototype.removeAllChildrenWithCleanup.call(this, cleanup);
+ this._items = [];
+
+ this._onItemListChanged();
+ },
+
+ /**
+ * Push back custom item into ccui.ListView.
+ * @param {ccui.Widget} item
+ * @param {Number} index
+ */
+ insertCustomItem: function (item, index) {
+ this._items.splice(index, 0, item);
+
+ this._onItemListChanged();
+ ccui.ScrollView.prototype.addChild.call(this, item);
+ this._remedyLayoutParameter(item);
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Removes a item whose index is same as the parameter.
+ * @param {Number} index
+ */
+ removeItem: function (index) {
+ var item = this.getItem(index);
+ if (item == null)
+ return;
+ this.removeChild(item, true);
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Removes the last item of ccui.ListView.
+ */
+ removeLastItem: function () {
+ this.removeItem(this._items.length - 1);
+ },
+
+ /**
+ * Removes all items from ccui.ListView.
+ */
+ removeAllItems: function () {
+ this.removeAllChildren();
+ },
+
+ /**
+ * Returns a item whose index is same as the parameter.
+ * @param {Number} index
+ * @returns {ccui.Widget}
+ */
+ getItem: function (index) {
+ if (index < 0 || index >= this._items.length)
+ return null;
+ return this._items[index];
+ },
+
+ /**
+ * Returns the item container.
+ * @returns {Array}
+ */
+ getItems: function () {
+ return this._items;
+ },
+
+ /**
+ * Returns the index of item.
+ * @param {ccui.Widget} item the item which need to be checked.
+ * @returns {Number} the index of item.
+ */
+ getIndex: function (item) {
+ if (item == null)
+ return -1;
+ return this._items.indexOf(item);
+ },
+
+ /**
+ * Changes the gravity of ListView.
+ * @param {ccui.ListView.GRAVITY_LEFT|ccui.ListView.GRAVITY_RIGHT|ccui.ListView.GRAVITY_CENTER_HORIZONTAL|ccui.ListView.GRAVITY_BOTTOM|ccui.ListView.GRAVITY_CENTER_VERTICAL} gravity
+ */
+ setGravity: function (gravity) {
+ if (this._gravity === gravity)
+ return;
+ this._gravity = gravity;
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Set magnetic type of ListView.
+ * @param {ccui.ListView.MAGNETIC_NONE|ccui.ListView.MAGNETIC_CENTER,ccui.ListView.MAGNETIC_BOTH_END|ccui.ListView.MAGNETIC_LEFT|ccui.ListView.MAGNETIC_RIGHT|ccui.ListView.MAGNETIC_TOP|ccui.ListView.MAGNETIC_BOTTOM} magneticType
+ */
+ setMagneticType: function (magneticType) {
+ this._magneticType = magneticType;
+ this._onItemListChanged();
+ this._startMagneticScroll();
+ },
+
+ /**
+ * Get magnetic type of ListView.
+ * @returns {number}
+ */
+ getMagneticType: function () {
+ return this._magneticType;
+ },
+
+ /**
+ * Set magnetic allowed out of boundary.
+ * @param {boolean} magneticAllowedOutOfBoundary
+ */
+ setMagneticAllowedOutOfBoundary: function (magneticAllowedOutOfBoundary) {
+ this._magneticAllowedOutOfBoundary = magneticAllowedOutOfBoundary;
+ },
+
+ /**
+ * Query whether the magnetic out of boundary is allowed.
+ * @returns {boolean}
+ */
+ getMagneticAllowedOutOfBoundary: function () {
+ return this._magneticAllowedOutOfBoundary;
+ },
+
+ /**
+ * Changes the margin between each item.
+ * @param {Number} margin
+ */
+ setItemsMargin: function (margin) {
+ if (this._itemsMargin === margin)
+ return;
+ this._itemsMargin = margin;
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Returns the margin between each item.
+ * @returns {Number}
+ */
+ getItemsMargin: function () {
+ return this._itemsMargin;
+ },
+
+ /**
+ * Changes scroll direction of ccui.ListView.
+ * @param {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH} dir
+ */
+ setDirection: function (dir) {
+ switch (dir) {
+ case ccui.ScrollView.DIR_VERTICAL:
+ this.setLayoutType(ccui.Layout.LINEAR_VERTICAL);
+ break;
+ case ccui.ScrollView.DIR_HORIZONTAL:
+ this.setLayoutType(ccui.Layout.LINEAR_HORIZONTAL);
+ break;
+ case ccui.ScrollView.DIR_BOTH:
+ return;
+ default:
+ return;
+ break;
+ }
+ ccui.ScrollView.prototype.setDirection.call(this, dir);
+ },
+
+ _getHowMuchOutOfBoundary: function (addition) {
+ if (addition === undefined)
+ addition = cc.p(0, 0);
+
+ if (!this._magneticAllowedOutOfBoundary || this._items.length === 0) {
+ return ccui.ScrollView.prototype._getHowMuchOutOfBoundary.call(this, addition);
+ }
+ else if (this._magneticType === ccui.ListView.MAGNETIC_NONE || this._magneticType === ccui.ListView.MAGNETIC_BOTH_END) {
+ return ccui.ScrollView.prototype._getHowMuchOutOfBoundary.call(this, addition);
+ }
+ else if (addition.x === 0 && addition.y === 0 && !this._outOfBoundaryAmountDirty) {
+ return this._outOfBoundaryAmount;
+ }
+
+ // If it is allowed to be out of boundary by magnetic, adjust the boundaries according to the magnetic type.
+ var leftBoundary = this._leftBoundary;
+ var rightBoundary = this._rightBoundary;
+ var topBoundary = this._topBoundary;
+ var bottomBoundary = this._bottomBoundary;
+
+ var lastItemIndex = this._items.length - 1;
+ var contentSize = this.getContentSize();
+ var firstItemAdjustment = cc.p(0, 0);
+ var lastItemAdjustment = cc.p(0, 0);
+
+ switch (this._magneticType) {
+ case ccui.ListView.MAGNETIC_CENTER:
+ firstItemAdjustment.x = (contentSize.width - this._items[0].width) / 2;
+ firstItemAdjustment.y = (contentSize.height - this._items[0].height) / 2;
+
+ lastItemAdjustment.x = (contentSize.width - this._items[lastItemIndex].width) / 2;
+ lastItemAdjustment.y = (contentSize.height - this._items[lastItemIndex].height) / 2;
+
+ break;
+ case ccui.ListView.MAGNETIC_LEFT:
+ case ccui.ListView.MAGNETIC_TOP:
+ lastItemAdjustment.x = contentSize.width - this._items[lastItemIndex].width;
+ lastItemAdjustment.y = contentSize.height - this._items[lastItemIndex].height;
+ break;
+ case ccui.ListView.MAGNETIC_RIGHT:
+ case ccui.ListView.MAGNETIC_BOTTOM:
+ firstItemAdjustment.x = contentSize.width - this._items[0].width;
+ firstItemAdjustment.y = contentSize.height - this._items[0].height;
+ break;
+ }
+
+ leftBoundary += firstItemAdjustment.x;
+ rightBoundary -= lastItemAdjustment.x;
+ topBoundary -= firstItemAdjustment.y;
+ bottomBoundary += lastItemAdjustment.y;
+
+
+ // Calculate the actual amount
+ var outOfBoundaryAmount = cc.p(0, 0);
+
+ if (this._innerContainer.getLeftBoundary() + addition.x > leftBoundary) {
+ outOfBoundaryAmount.x = leftBoundary - (this._innerContainer.getLeftBoundary() + addition.x);
+ }
+ else if (this._innerContainer.getRightBoundary() + addition.x < rightBoundary) {
+ outOfBoundaryAmount.x = rightBoundary - (this._innerContainer.getRightBoundary() + addition.x);
+ }
+
+ if (this._innerContainer.getTopBoundary() + addition.y < topBoundary) {
+ outOfBoundaryAmount.y = topBoundary - (this._innerContainer.getTopBoundary() + addition.y);
+ }
+ else if (this._innerContainer.getBottomBoundary() + addition.y > bottomBoundary) {
+ outOfBoundaryAmount.y = bottomBoundary - (this._innerContainer.getBottomBoundary() + addition.y);
+ }
+
+ if (addition.x === 0 && addition.y === 0) {
+ this._outOfBoundaryAmount = outOfBoundaryAmount;
+ this._outOfBoundaryAmountDirty = false;
+ }
+ return outOfBoundaryAmount;
+ },
+
+ _calculateItemPositionWithAnchor: function (item, itemAnchorPoint) {
+ var origin = cc.p(item.getLeftBoundary(), item.getBottomBoundary());
+ var size = item.getContentSize();
+
+ return cc.p(origin.x + size.width * itemAnchorPoint.x, origin.y + size.height * itemAnchorPoint.y);
+ },
+
+ _findClosestItem: function (targetPosition, items, itemAnchorPoint, firstIndex, distanceFromFirst, lastIndex, distanceFromLast) {
+ cc.assert(firstIndex >= 0 && lastIndex < items.length && firstIndex <= lastIndex, "");
+ if (firstIndex === lastIndex) {
+ return items[firstIndex];
+ }
+ if (lastIndex - firstIndex === 1) {
+ if (distanceFromFirst <= distanceFromLast) {
+ return items[firstIndex];
+ }
+ else {
+ return items[lastIndex];
+ }
+ }
+
+ // Binary search
+ var midIndex = Math.floor((firstIndex + lastIndex) / 2);
+ var itemPosition = this._calculateItemPositionWithAnchor(items[midIndex], itemAnchorPoint);
+ var distanceFromMid = cc.pLength(cc.pSub(targetPosition, itemPosition));
+
+ if (distanceFromFirst <= distanceFromLast) {
+ // Left half
+ return this._findClosestItem(targetPosition, items, itemAnchorPoint, firstIndex, distanceFromFirst, midIndex, distanceFromMid);
+ }
+ else {
+ // Right half
+ return this._findClosestItem(targetPosition, items, itemAnchorPoint, midIndex, distanceFromMid, lastIndex, distanceFromLast);
+ }
+ },
+
+ /**
+ * Query the closest item to a specific position in inner container.
+ *
+ * @param {cc.Point} targetPosition Specifies the target position in inner container's coordinates.
+ * @param {cc.Point} itemAnchorPoint Specifies an anchor point of each item for position to calculate distance.
+ * @returns {?ccui.Widget} A item instance if list view is not empty. Otherwise, returns null.
+ */
+ getClosestItemToPosition: function (targetPosition, itemAnchorPoint) {
+ if (this._items.length === 0) {
+ return null;
+ }
+
+ // Find the closest item through binary search
+ var firstIndex = 0;
+ var firstPosition = this._calculateItemPositionWithAnchor(this._items[firstIndex], itemAnchorPoint);
+ var distanceFromFirst = cc.pLength(cc.pSub(targetPosition, firstPosition));
+
+ var lastIndex = this._items.length - 1;
+ var lastPosition = this._calculateItemPositionWithAnchor(this._items[lastIndex], itemAnchorPoint);
+ var distanceFromLast = cc.pLength(cc.pSub(targetPosition, lastPosition));
+
+ return this._findClosestItem(targetPosition, this._items, itemAnchorPoint, firstIndex, distanceFromFirst, lastIndex, distanceFromLast);
+ },
+
+ /**
+ * Query the closest item to a specific position in current view.
+ * For instance, to find the item in the center of view, call 'getClosestItemToPositionInCurrentView(cc.p(0.5, 0.5), cc.p(0.5, 0.5))'.
+ *
+ * @param {cc.Point} positionRatioInView Specifies the target position with ratio in list view's content size.
+ * @param {cc.Point} itemAnchorPoint Specifies an anchor point of each item for position to calculate distance.
+ * @returns {?ccui.Widget} A item instance if list view is not empty. Otherwise, returns null.
+ */
+
+ getClosestItemToPositionInCurrentView: function (positionRatioInView, itemAnchorPoint) {
+ // Calculate the target position
+ var contentSize = this.getContentSize();
+ var targetPosition = cc.pMult(this._innerContainer.getPosition(), -1);
+ targetPosition.x += contentSize.width * positionRatioInView.x;
+ targetPosition.y += contentSize.height * positionRatioInView.y;
+
+ return this.getClosestItemToPosition(targetPosition, itemAnchorPoint);
+ },
+
+ /**
+ * Query the center item
+ * @returns {?ccui.Widget} A item instance.
+ */
+ getCenterItemInCurrentView: function () {
+ return this.getClosestItemToPositionInCurrentView(cc.p(0.5, 0.5), cc.p(0.5, 0.5));
+ },
+
+ /**
+ * Query the leftmost item in horizontal list
+ * @returns {?ccui.Widget} A item instance.
+ */
+ getLeftmostItemInCurrentView: function () {
+ if (this._direction === ccui.ScrollView.DIR_HORIZONTAL) {
+ return this.getClosestItemToPositionInCurrentView(cc.p(0, 0.5), cc.p(0.5, 0.5));
+ }
+
+ return null;
+ },
+
+ /**
+ * Query the rightmost item in horizontal list
+ * @returns {?ccui.Widget} A item instance.
+ */
+ getRightmostItemInCurrentView: function () {
+ if (this._direction === ccui.ScrollView.DIR_HORIZONTAL) {
+ return this.getClosestItemToPositionInCurrentView(cc.p(1, 0.5), cc.p(0.5, 0.5));
+ }
+
+ return null;
+ },
+
+ /**
+ * Query the topmost item in horizontal list
+ * @returns {?ccui.Widget} A item instance.
+ */
+ getTopmostItemInCurrentView: function () {
+ if (this._direction === ccui.ScrollView.DIR_VERTICAL) {
+ return this.getClosestItemToPositionInCurrentView(cc.p(0.5, 1), cc.p(0.5, 0.5));
+ }
+
+ return null;
+ },
+
+ /**
+ * Query the topmost item in horizontal list
+ * @returns {?ccui.Widget} A item instance.
+ */
+ getBottommostItemInCurrentView: function () {
+ if (this._direction === ccui.ScrollView.DIR_VERTICAL) {
+ return this.getClosestItemToPositionInCurrentView(cc.p(0.5, 0), cc.p(0.5, 0.5));
+ }
+
+ return null;
+ },
+
+ _calculateItemDestination: function (positionRatioInView, item, itemAnchorPoint) {
+ var contentSize = this.getContentSize();
+ var positionInView = cc.p(0, 0);
+ positionInView.x += contentSize.width * positionRatioInView.x;
+ positionInView.y += contentSize.height * positionRatioInView.y;
+
+ var itemPosition = this._calculateItemPositionWithAnchor(item, itemAnchorPoint);
+ return cc.pMult(cc.pSub(itemPosition, positionInView), -1);
+ },
+
+ jumpToBottom: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToBottom.call(this);
+ },
+
+ jumpToTop: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToTop.call(this);
+ },
+
+ jumpToLeft: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToLeft.call(this);
+ },
+
+ jumpToRight: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToRight.call(this);
+ },
+
+ jumpToTopLeft: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToTopLeft.call(this);
+ },
+
+ jumpToTopRight: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToTopRight.call(this);
+ },
+
+ jumpToBottomLeft: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToBottomLeft.call(this);
+ },
+
+ jumpToBottomRight: function () {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToBottomRight.call(this);
+ },
+
+ jumpToPercentVertical: function (percent) {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToPercentVertical.call(this, percent);
+ },
+
+ jumpToPercentHorizontal: function (percent) {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToPercentHorizontal.call(this, percent);
+ },
+
+ jumpToPercentBothDirection: function (percent) {
+ this.doLayout();
+ ccui.ScrollView.prototype.jumpToPercentBothDirection.call(this, percent);
+ },
+
+ /**
+ * Jump to specific item
+ * @param {number} itemIndex Specifies the item's index
+ * @param {cc.Point} positionRatioInView Specifies the position with ratio in list view's content size.
+ * @param {cc.Point} itemAnchorPoint Specifies an anchor point of each item for position to calculate distance.
+ */
+ jumpToItem: function (itemIndex, positionRatioInView, itemAnchorPoint) {
+ var item = this.getItem(itemIndex);
+
+ if (!item)
+ return;
+
+ this.doLayout();
+
+ var destination = this._calculateItemDestination(positionRatioInView, item, itemAnchorPoint);
+
+ if (!this.bounceEnabled) {
+ var delta = cc.pSub(destination, this._innerContainer.getPosition());
+ var outOfBoundary = this._getHowMuchOutOfBoundary(delta);
+ destination.x += outOfBoundary.x;
+ destination.y += outOfBoundary.y;
+ }
+
+ this._jumpToDestination(destination);
+ },
+
+ /**
+ * Scroll to specific item
+ * @param {number} itemIndex Specifies the item's index
+ * @param {cc.Point} positionRatioInView Specifies the position with ratio in list view's content size.
+ * @param {cc.Point} itemAnchorPoint Specifies an anchor point of each item for position to calculate distance.
+ * @param {number} [timeInSec = 1.0] Scroll time
+ */
+ scrollToItem: function (itemIndex, positionRatioInView, itemAnchorPoint, timeInSec) {
+ if (timeInSec === undefined)
+ timeInSec = 1;
+
+ var item = this.getItem(itemIndex);
+
+ if (!item)
+ return;
+
+ var destination = this._calculateItemDestination(positionRatioInView, item, itemAnchorPoint);
+ this._startAutoScrollToDestination(destination, timeInSec, true);
+ },
+
+ /**
+ * Requests refresh list view.
+ * @deprecated Use method requestDoLayout() instead
+ */
+ requestRefreshView: function () {
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Refreshes list view.
+ * @deprecated Use method forceDoLayout() instead
+ */
+ refreshView: function () {
+ this.forceDoLayout()
+ },
+
+ /**
+ * provides a public _doLayout function for Editor. it calls _doLayout.
+ */
+ doLayout: function () {
+ this._doLayout();
+ },
+
+ requestDoLayout: function () {
+ this._refreshViewDirty = true;
+ },
+
+ _doLayout: function () {
+ //ccui.Layout.prototype._doLayout.call(this);
+ if (this._refreshViewDirty) {
+ var locItems = this._items;
+ for (var i = 0; i < locItems.length; i++) {
+ var item = locItems[i];
+ item.setLocalZOrder(i);
+ this._remedyLayoutParameter(item);
+ }
+ this._updateInnerContainerSize();
+ this._innerContainer.forceDoLayout();
+ this._refreshViewDirty = false;
+ }
+ },
+
+ /**
+ * Adds event listener to ccui.ListView.
+ * @param {Function} selector
+ * @param {Object} [target=]
+ * @deprecated since v3.0, please use addEventListener instead.
+ */
+ addEventListenerListView: function (selector, target) {
+ this._listViewEventListener = target;
+ this._listViewEventSelector = selector;
+ },
+
+ /**
+ * Adds callback function called ListView event triggered
+ * @param {Function} selector
+ */
+ addEventListener: function (selector) {
+ this._ccListViewEventCallback = selector;
+ },
+
+ _selectedItemEvent: function (event) {
+ var eventEnum = (event === ccui.Widget.TOUCH_BEGAN) ? ccui.ListView.ON_SELECTED_ITEM_START : ccui.ListView.ON_SELECTED_ITEM_END;
+ if (this._listViewEventSelector) {
+ if (this._listViewEventListener)
+ this._listViewEventSelector.call(this._listViewEventListener, this, eventEnum);
+ else
+ this._listViewEventSelector(this, eventEnum);
+ }
+ if (this._ccListViewEventCallback)
+ this._ccListViewEventCallback(this, eventEnum);
+ },
+
+ /**
+ * Intercept touch event, handle its child's touch event.
+ * @param {Number} eventType
+ * @param {ccui.Widget} sender
+ * @param {cc.Touch} touch
+ */
+ interceptTouchEvent: function (eventType, sender, touch) {
+ ccui.ScrollView.prototype.interceptTouchEvent.call(this, eventType, sender, touch);
+ if (!this._touchEnabled) {
+ return;
+ }
+ if (eventType !== ccui.Widget.TOUCH_MOVED) {
+ var parent = sender;
+ while (parent) {
+ if (parent && parent.getParent() === this._innerContainer) {
+ this._curSelectedIndex = this.getIndex(parent);
+ break;
+ }
+ parent = parent.getParent();
+ }
+ if (sender.isHighlighted())
+ this._selectedItemEvent(eventType);
+ }
+ },
+
+ /**
+ * Returns current selected index
+ * @returns {number}
+ */
+ getCurSelectedIndex: function () {
+ return this._curSelectedIndex;
+ },
+
+ _onSizeChanged: function () {
+ ccui.ScrollView.prototype._onSizeChanged.call(this);
+ this._refreshViewDirty = true;
+ },
+
+ /**
+ * Returns the "class name" of ccui.ListView.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "ListView";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.ListView();
+ },
+
+ _copyClonedWidgetChildren: function (model) {
+ var arrayItems = model.getItems();
+ for (var i = 0; i < arrayItems.length; i++) {
+ var item = arrayItems[i];
+ this.pushBackCustomItem(item.clone());
+ }
+ },
+
+ _copySpecialProperties: function (listView) {
+ if (listView instanceof ccui.ListView) {
+ ccui.ScrollView.prototype._copySpecialProperties.call(this, listView);
+ this.setItemModel(listView._model);
+ this.setItemsMargin(listView._itemsMargin);
+ this.setGravity(listView._gravity);
+
+ this._listViewEventListener = listView._listViewEventListener;
+ this._listViewEventSelector = listView._listViewEventSelector;
+ }
+ },
+
+ _startAttenuatingAutoScroll: function (deltaMove, initialVelocity) {
+ var adjustedDeltaMove = deltaMove;
+
+ if (this._items.length !== 0 && this._magneticType !== ccui.ListView.MAGNETIC_NONE) {
+ adjustedDeltaMove = this._flattenVectorByDirection(adjustedDeltaMove);
+
+ var howMuchOutOfBoundary = this._getHowMuchOutOfBoundary(adjustedDeltaMove);
+ // If the destination is out of boundary, do nothing here. Because it will be handled by bouncing back.
+ if (howMuchOutOfBoundary.x === 0 && howMuchOutOfBoundary.y === 0) {
+ var magType = this._magneticType;
+ if (magType === ccui.ListView.MAGNETIC_BOTH_END) {
+ if (this._direction === ccui.ScrollView.DIR_HORIZONTAL) {
+ magType = (adjustedDeltaMove.x > 0 ? ccui.ListView.MAGNETIC_LEFT : ccui.ListView.MAGNETIC_RIGHT);
+ }
+ else if (this._direction === ccui.ScrollView.DIR_VERTICAL) {
+ magType = (adjustedDeltaMove.y > 0 ? ccui.ListView.MAGNETIC_BOTTOM : ccui.ListView.MAGNETIC_TOP);
+ }
+ }
+
+ // Adjust the delta move amount according to the magnetic type
+ var magneticAnchorPoint = this._getAnchorPointByMagneticType(magType);
+ var magneticPosition = cc.pMult(this._innerContainer.getPosition(), -1);
+ magneticPosition.x += this.width * magneticAnchorPoint.x;
+ magneticPosition.y += this.height * magneticAnchorPoint.y;
+
+ var pTargetItem = this.getClosestItemToPosition(cc.pSub(magneticPosition, adjustedDeltaMove), magneticAnchorPoint);
+ var itemPosition = this._calculateItemPositionWithAnchor(pTargetItem, magneticAnchorPoint);
+ adjustedDeltaMove = cc.pSub(magneticPosition, itemPosition);
+ }
+ }
+ ccui.ScrollView.prototype._startAttenuatingAutoScroll.call(this, adjustedDeltaMove, initialVelocity);
+ },
+
+ _getAnchorPointByMagneticType: function (magneticType) {
+ switch (magneticType) {
+ case ccui.ListView.MAGNETIC_NONE:
+ return cc.p(0, 0);
+ case ccui.ListView.MAGNETIC_BOTH_END:
+ return cc.p(0, 1);
+ case ccui.ListView.MAGNETIC_CENTER:
+ return cc.p(0.5, 0.5);
+ case ccui.ListView.MAGNETIC_LEFT:
+ return cc.p(0, 0.5);
+ case ccui.ListView.MAGNETIC_RIGHT:
+ return cc.p(1, 0.5);
+ case ccui.ListView.MAGNETIC_TOP:
+ return cc.p(0.5, 1);
+ case ccui.ListView.MAGNETIC_BOTTOM:
+ return cc.p(0.5, 0);
+ }
+
+ return cc.p(0, 0);
+ },
+
+ _startMagneticScroll: function () {
+ if (this._items.length === 0 || this._magneticType === ccui.ListView.MAGNETIC_NONE) {
+ return;
+ }
+
+ // Find the closest item
+ var magneticAnchorPoint = this._getAnchorPointByMagneticType(this._magneticType);
+ var magneticPosition = cc.pMult(this._innerContainer.getPosition(), -1);
+ magneticPosition.x += this.width * magneticAnchorPoint.x;
+ magneticPosition.y += this.height * magneticAnchorPoint.y;
+
+ var pTargetItem = this.getClosestItemToPosition(magneticPosition, magneticAnchorPoint);
+ this.scrollToItem(this.getIndex(pTargetItem), magneticAnchorPoint, magneticAnchorPoint);
+ }
+});
+
+/**
+ * allocates and initializes a UIListView.
+ * @deprecated since v3.0, please use new ccui.ListView() instead.
+ */
+ccui.ListView.create = function () {
+ return new ccui.ListView();
+};
+
+// Constants
+//listView event type
+/**
+ * The flag selected item of ccui.ListView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.EVENT_SELECTED_ITEM = 0;
+
+/**
+ * The flag selected item start of ccui.ListView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.ON_SELECTED_ITEM_START = 0;
+/**
+ * The flag selected item end of ccui.ListView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.ON_SELECTED_ITEM_END = 1;
+
+//listView gravity
+/**
+ * The left flag of ccui.ListView's gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.GRAVITY_LEFT = 0;
+/**
+ * The right flag of ccui.ListView's gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.GRAVITY_RIGHT = 1;
+/**
+ * The center horizontal flag of ccui.ListView's gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.GRAVITY_CENTER_HORIZONTAL = 2;
+/**
+ * The top flag of ccui.ListView's gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.GRAVITY_TOP = 3;
+/**
+ * The bottom flag of ccui.ListView's gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.GRAVITY_BOTTOM = 4;
+/**
+ * The center vertical flag of ccui.ListView's gravity.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.GRAVITY_CENTER_VERTICAL = 5;
+
+/**
+ * The flag of ccui.ListView's magnetic none type.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.MAGNETIC_NONE = 0;
+/**
+ * The flag of ccui.ListView's magnetic center type.
+ * ListView tries to align its items in center of current view.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.MAGNETIC_CENTER = 1;
+/**
+ * The flag of ccui.ListView's magnetic both end type.
+ * ListView tries to align its items in left or right end if it is horizontal, top or bottom in vertical.
+ * The aligning side (left or right, top or bottom) is determined by user's scroll direction.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.MAGNETIC_BOTH_END = 2;
+/**
+ * The flag of ccui.ListView's magnetic left type.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.MAGNETIC_LEFT = 3;
+/**
+ * The flag of ccui.ListView's magnetic right type.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.MAGNETIC_RIGHT = 4;
+/**
+ * The flag of ccui.ListView's magnetic top type.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.MAGNETIC_TOP = 5;
+/**
+ * The flag of ccui.ListView's magnetic bottom type.
+ * @constant
+ * @type {number}
+ */
+ccui.ListView.MAGNETIC_BOTTOM = 6;
diff --git a/extensions/ccui/uiwidgets/scroll-widget/UIPageView.js b/extensions/ccui/uiwidgets/scroll-widget/UIPageView.js
new file mode 100644
index 0000000000..e37853778a
--- /dev/null
+++ b/extensions/ccui/uiwidgets/scroll-widget/UIPageView.js
@@ -0,0 +1,593 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The PageView control of Cocos UI.
+ * @class
+ * @extends ccui.ListView
+ * @example
+ * var pageView = new ccui.PageView();
+ * pageView.setTouchEnabled(true);
+ * pageView.addPage(new ccui.Layout());
+ * this.addChild(pageView);
+ */
+ccui.PageView = ccui.ListView.extend(/** @lends ccui.PageView# */{
+ _curPageIdx: 0,
+ _childFocusCancelOffset: 0,
+ _pageViewEventListener: null,
+ _pageViewEventSelector: null,
+ _className: "PageView",
+
+ _indicator: null,
+ _indicatorPositionAsAnchorPoint: null,
+ /**
+ * Allocates and initializes a UIPageView.
+ * Constructor of ccui.PageView. please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
+ * @example
+ * // example
+ * var uiPageView = new ccui.PageView();
+ */
+ ctor: function () {
+ ccui.ListView.prototype.ctor.call(this);
+
+ this._childFocusCancelOffset = 5;
+ this._indicatorPositionAsAnchorPoint = cc.p(0.5, 0.1);
+ this._pageViewEventListener = null;
+ this._pageViewEventSelector = null;
+
+ this.setDirection(ccui.ScrollView.DIR_HORIZONTAL);
+ this.setMagneticType(ccui.ListView.MAGNETIC_CENTER);
+ this.setScrollBarEnabled(false);
+ },
+
+ /**
+ * Add a widget to a page of PageView.
+ * @deprecated since v3.9, please use 'insertPage(Widget* page, int idx)' instead.
+ * @param {ccui.Widget} widget widget to be added to PageView.
+ * @param {number} pageIdx index of page.
+ * @param {Boolean} forceCreate if force create and there is no page exist, PageView would create a default page for adding widget.
+ */
+ addWidgetToPage: function (widget, pageIdx, forceCreate) {
+ this.insertCustomItem(widget, pageIdx);
+ },
+
+ /**
+ * Insert a page into the end of PageView.
+ * @param {ccui.Widget} page Page to be inserted.
+ */
+ addPage: function (page) {
+ this.pushBackCustomItem(page);
+ },
+
+ /**
+ * Insert a page into PageView at a given index.
+ * @param {ccui.Widget} page Page to be inserted.
+ * @param {number} idx A given index.
+ */
+ insertPage: function (page, idx) {
+ this.insertCustomItem(page, idx);
+ },
+
+ /**
+ * Removes a page from PageView.
+ * @param {ccui.Widget} page Page to be removed.
+ */
+ removePage: function (page) {
+ this.removeItem(this.getIndex(page));
+ },
+
+ /**
+ * Removes a page at index of PageView.
+ * @param {number} index A given index.
+ */
+ removePageAtIndex: function (index) {
+ this.removeItem(index);
+ },
+
+ /**
+ * Removes all pages from PageView
+ */
+ removeAllPages: function () {
+ this.removeAllItems();
+ },
+
+ /**
+ * scroll PageView to index.
+ * @param {number} idx A given index in the PageView. Index start from 0 to pageCount -1.
+ */
+ scrollToItem: function (idx) {
+ ccui.ListView.prototype.scrollToItem.call(this, idx, cc.p(0.5, 0.5), cc.p(0.5, 0.5));
+ },
+
+ /**
+ * scroll PageView to index.
+ * @param {number} idx A given index in the PageView. Index start from 0 to pageCount -1.
+ */
+ scrollToPage: function (idx) {
+ this.scrollToItem(idx);
+ },
+
+
+ _doLayout: function () {
+ if (!this._refreshViewDirty)
+ return;
+
+ ccui.ListView.prototype._doLayout.call(this);
+
+ if (this._indicator) {
+ var index = this.getIndex(this.getCenterItemInCurrentView());
+ this._indicator.indicate(index);
+ }
+
+ this._refreshViewDirty = false;
+ },
+
+ /**
+ * Changes scroll direction of ccui.PageView.
+ * @param {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH} direction
+ */
+ setDirection: function (direction) {
+ ccui.ListView.prototype.setDirection.call(this, direction);
+ if (direction === ccui.ScrollView.DIR_HORIZONTAL) {
+ this._indicatorPositionAsAnchorPoint = cc.p(0.5, 0.1);
+ }
+ else if (direction === ccui.ScrollView.DIR_VERTICAL) {
+ this._indicatorPositionAsAnchorPoint = cc.p(0.1, 0.5);
+ }
+
+ if (this._indicator) {
+ this._indicator.setDirection(direction);
+ this._refreshIndicatorPosition();
+ }
+ },
+
+ /**
+ * Set custom scroll threshold to page view. If you don't specify the value, the pageView will scroll when half page view width reached.
+ * @since v3.2
+ * @param threshold
+ * @deprecated Since v3.9, this method has no effect.
+ */
+ setCustomScrollThreshold: function (threshold) {
+
+ },
+
+ /**
+ * Returns user defined scroll page threshold.
+ * @since v3.2
+ * @deprecated Since v3.9, this method always returns 0.
+ */
+ getCustomScrollThreshold: function () {
+ return 0;
+ },
+
+ /**
+ * Set using user defined scroll page threshold or not. If you set it to false, then the default scroll threshold is pageView.width / 2.
+ * @since v3.2
+ * @deprecated Since v3.9, this method has no effect.
+ */
+ setUsingCustomScrollThreshold: function (flag) {
+ },
+
+ /**
+ * Queries whether we are using user defined scroll page threshold or not
+ * @deprecated Since v3.9, this method always returns false.
+ */
+ isUsingCustomScrollThreshold: function () {
+ return false;
+ },
+
+ _moveInnerContainer: function (deltaMove, canStartBounceBack) {
+ ccui.ListView.prototype._moveInnerContainer.call(this, deltaMove, canStartBounceBack);
+ this._curPageIdx = this.getIndex(this.getCenterItemInCurrentView());
+ if (this._indicator) {
+ this._indicator.indicate(this._curPageIdx);
+ }
+ },
+
+ _onItemListChanged: function () {
+ ccui.ListView.prototype._onItemListChanged.call(this);
+ if (this._indicator) {
+ this._indicator.reset(this._items.length);
+ }
+ },
+
+ _onSizeChanged: function () {
+ ccui.ListView.prototype._onSizeChanged.call(this);
+ this._refreshIndicatorPosition();
+ },
+
+ _remedyLayoutParameter: function (item) {
+ item.setContentSize(this.getContentSize());
+ ccui.ListView.prototype._remedyLayoutParameter.call(this, item);
+ },
+
+ _refreshIndicatorPosition: function () {
+ if (this._indicator) {
+ var contentSize = this.getContentSize();
+ var posX = contentSize.width * this._indicatorPositionAsAnchorPoint.x;
+ var posY = contentSize.height * this._indicatorPositionAsAnchorPoint.y;
+ this._indicator.setPosition(cc.p(posX, posY));
+ }
+ },
+
+ _handleReleaseLogic: function (touchPoint) {
+
+ ccui.ScrollView.prototype._handleReleaseLogic.call(this, touchPoint);
+
+ if (this._items.length <= 0)
+ return;
+
+ var touchMoveVelocity = this._flattenVectorByDirection(this._calculateTouchMoveVelocity());
+
+ var INERTIA_THRESHOLD = 500;
+ if (cc.pLength(touchMoveVelocity) < INERTIA_THRESHOLD) {
+ this._startMagneticScroll();
+ }
+ else {
+ // Handle paging by inertia force.
+ var currentPage = this.getItem(this._curPageIdx);
+ var destination = this._calculateItemDestination(cc.p(0.5, 0.5), currentPage, cc.p(0.5, 0.5));
+ var deltaToCurrentPage = cc.pSub(destination, this.getInnerContainerPosition());
+ deltaToCurrentPage = this._flattenVectorByDirection(deltaToCurrentPage);
+
+ // If the direction of displacement to current page and the direction of touch are same, just start magnetic scroll to the current page.
+ // Otherwise, move to the next page of touch direction.
+ if (touchMoveVelocity.x * deltaToCurrentPage.x > 0 || touchMoveVelocity.y * deltaToCurrentPage.y > 0) {
+ this._startMagneticScroll();
+ }
+ else {
+ if (touchMoveVelocity.x < 0 || touchMoveVelocity.y > 0) {
+ ++this._curPageIdx;
+ }
+ else {
+ --this._curPageIdx;
+ }
+ this._curPageIdx = Math.min(this._curPageIdx, this._items.length);
+ this._curPageIdx = Math.max(this._curPageIdx, 0);
+ this.scrollToItem(this._curPageIdx);
+ }
+ }
+
+ },
+
+ _getAutoScrollStopEpsilon: function () {
+ return 0.001;
+ },
+
+ _pageTurningEvent: function () {
+ if (this._pageViewEventSelector) {
+ if (this._pageViewEventListener)
+ this._pageViewEventSelector.call(this._pageViewEventListener, this, ccui.PageView.EVENT_TURNING);
+ else
+ this._pageViewEventSelector(this, ccui.PageView.EVENT_TURNING);
+ }
+ if (this._ccEventCallback)
+ this._ccEventCallback(this, ccui.PageView.EVENT_TURNING);
+ },
+
+ /**
+ * Adds event listener to ccui.PageView.
+ * @param {Function} selector
+ * @param {Object} [target=]
+ * @deprecated since v3.0, please use addEventListener instead.
+ */
+ addEventListenerPageView: function (selector, target) {
+ this._pageViewEventSelector = selector;
+ this._pageViewEventListener = target;
+ },
+
+ addEventListener: function (selector) {
+ this._ccEventCallback = function (ref, eventType) {
+ if (eventType == ccui.ScrollView.EVENT_AUTOSCROLL_ENDED)
+ selector(this, eventType)
+ };
+ },
+
+ /**
+ * Jump to a page with a given index without scrolling.
+ * This is the different between scrollToPage.
+ * @param {number} index A given index in PageView. Index start from 0 to pageCount -1.
+ */
+ setCurrentPageIndex: function (index) {
+ this.jumpToItem(index, cc.p(0.5, 0.5), cc.p(0.5, 0.5));
+ },
+
+ /**
+ * Jump to a page with a given index without scrolling.
+ * This is the different between scrollToPage.
+ * @param {number} index A given index in PageView. Index start from 0 to pageCount -1.
+ * @deprecated since v3.9, this is deprecated. Use `setCurrentPageIndex()` instead.
+ */
+ setCurPageIndex: function (index) {
+ this.setCurrentPageIndex(index);
+ },
+
+ /**
+ * Returns current page index
+ * @returns {number}
+ */
+ getCurrentPageIndex: function () {
+ return this._curPageIdx;
+ },
+
+ /**
+ * Returns current page index
+ * @deprecated since v3.9, this is deprecated. Use `getCurrentPageIndex()` instead.
+ * @returns {number}
+ */
+ getCurPageIndex: function () {
+ var widget = this.getCenterItemInCurrentView();
+ return this.getIndex(widget);
+ },
+
+ /**
+ * Returns all pages of PageView
+ * @returns {Array}
+ */
+ getPages: function () {
+ return this.getItems();
+ },
+
+ /**
+ * Returns a page from PageView by index
+ * @param {Number} index
+ * @returns {ccui.Layout}
+ */
+ getPage: function (index) {
+ return this.getItem(index);
+ },
+
+ /**
+ * Returns the "class name" of ccui.PageView.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "PageView";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.PageView();
+ },
+
+ _copyClonedWidgetChildren: function (model) {
+ var arrayPages = model.getPages();
+ for (var i = 0; i < arrayPages.length; i++) {
+ var page = arrayPages[i];
+ this.addPage(page.clone());
+ }
+ },
+
+ _copySpecialProperties: function (pageView) {
+ ccui.ListView.prototype._copySpecialProperties.call(this, pageView);
+ this._ccEventCallback = pageView._ccEventCallback;
+ this._pageViewEventListener = pageView._pageViewEventListener;
+ this._pageViewEventSelector = pageView._pageViewEventSelector;
+ this._customScrollThreshold = pageView._customScrollThreshold;
+ },
+
+
+ /**
+ * Toggle page indicator enabled.
+ * @param {boolean} enabled True if enable page indicator, false otherwise.
+ */
+ setIndicatorEnabled: function (enabled) {
+ if (enabled == (this._indicator !== null)) {
+ return;
+ }
+
+ if (!enabled) {
+ this.removeProtectedChild(this._indicator);
+ this._indicator = null;
+ }
+ else {
+ this._indicator = new ccui.PageViewIndicator();
+ this._indicator.setDirection(this.getDirection());
+ this.addProtectedChild(this._indicator, 10000);
+ this.setIndicatorSelectedIndexColor(cc.color(100, 100, 255));
+ this._refreshIndicatorPosition();
+ }
+ },
+
+ /**
+ * Query page indicator state.
+ * @returns {boolean} True if page indicator is enabled, false otherwise.
+ */
+ getIndicatorEnabled: function () {
+ return this._indicator !== null;
+ },
+
+ /**
+ * Set the page indicator's position using anchor point.
+ * @param {cc.Point} positionAsAnchorPoint The position as anchor point.
+ */
+ setIndicatorPositionAsAnchorPoint: function (positionAsAnchorPoint) {
+ this._indicatorPositionAsAnchorPoint = positionAsAnchorPoint;
+ this._refreshIndicatorPosition();
+ },
+
+ /**
+ * Get the page indicator's position as anchor point.
+ * @returns {cc.Point}
+ */
+ getIndicatorPositionAsAnchorPoint: function () {
+ return this._indicatorPositionAsAnchorPoint;
+ },
+
+ /**
+ * Set the page indicator's position in page view.
+ * @param {cc.Point} position The position in page view
+ */
+ setIndicatorPosition: function (position) {
+ if (this._indicator) {
+ var contentSize = this.getContentSize();
+ this._indicatorPositionAsAnchorPoint.x = position.x / contentSize.width;
+ this._indicatorPositionAsAnchorPoint.y = position.y / contentSize.height;
+ this._indicator.setPosition(position);
+ }
+ },
+
+ /**
+ * Get the page indicator's position.
+ * @returns {cc.Point}
+ */
+ getIndicatorPosition: function () {
+ cc.assert(this._indicator !== null, "");
+ return this._indicator.getPosition();
+ },
+
+ /**
+ * Set space between page indicator's index nodes.
+ * @param {number} spaceBetweenIndexNodes Space between nodes in pixel.
+ */
+ setIndicatorSpaceBetweenIndexNodes: function (spaceBetweenIndexNodes) {
+ if (this._indicator) {
+ this._indicator.setSpaceBetweenIndexNodes(spaceBetweenIndexNodes);
+ }
+ },
+
+ /**
+ * Get the space between page indicator's index nodes.
+ * @returns {number}
+ */
+ getIndicatorSpaceBetweenIndexNodes: function () {
+ cc.assert(this._indicator !== null, "");
+ return this._indicator.getSpaceBetweenIndexNodes();
+ },
+
+ /**
+ * Set color of page indicator's selected index.
+ * @param {cc.Color} color Color for indicator
+ */
+ setIndicatorSelectedIndexColor: function (color) {
+ if (this._indicator) {
+ this._indicator.setSelectedIndexColor(color);
+ }
+ },
+
+ /**
+ * Get the color of page indicator's selected index.
+ * @returns {cc.Color}
+ */
+ getIndicatorSelectedIndexColor: function () {
+ cc.assert(this._indicator !== null, "");
+ return this._indicator.getSelectedIndexColor();
+ },
+
+ /**
+ * Set color of page indicator's index nodes.
+ * @param {cc.Color} color Color for indicator
+ */
+ setIndicatorIndexNodesColor: function (color) {
+ if (this._indicator) {
+ this._indicator.setIndexNodesColor(color);
+ }
+ },
+
+ /**
+ * Get the color of page indicator's index nodes.
+ * @returns {cc.Color}
+ */
+ getIndicatorIndexNodesColor: function () {
+ cc.assert(this._indicator !== null, "");
+ return this._indicator.getIndexNodesColor();
+ },
+
+ /**
+ * Set scale of page indicator's index nodes.
+ * @param {Number} scale Scale for indicator
+ */
+ setIndicatorIndexNodesScale: function (indexNodesScale) {
+ if (this._indicator) {
+ this._indicator.setIndexNodesScale(indexNodesScale);
+ this._indicator.indicate(this._curPageIdx);
+ }
+ },
+
+ /**
+ * Get the scale of page indicator's index nodes.
+ * @returns {Number}
+ */
+ getIndicatorIndexNodesScale: function () {
+ cc.assert(this._indicator !== null, "");
+ return this._indicator.getIndexNodesScale();
+ },
+
+ /**
+ * Sets texture of indicator index nodes
+ * @param {String} texName
+ * @param {ccui.Widget.LOCAL_TEXTURE | ccui.Widget.PLIST_TEXTURE} [texType = ccui.Widget.LOCAL_TEXTURE]
+ */
+ setIndicatorIndexNodesTexture: function (texName, texType) {
+ if (this._indicator) {
+ this._indicator.setIndexNodesTexture(texName, texType);
+ this._indicator.indicate(this._curPageIdx);
+ }
+ }
+});
+/**
+ * allocates and initializes a UIPageView.
+ * @deprecated since v3.0, please use new ccui.PageView() instead.
+ * @return {ccui.PageView}
+ */
+ccui.PageView.create = function () {
+ return new ccui.PageView();
+};
+
+// Constants
+//PageView event
+/**
+ * The turning flag of ccui.PageView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.PageView.EVENT_TURNING = 0;
+
+//PageView touch direction
+/**
+ * The left flag of ccui.PageView's touch direction.
+ * @constant
+ * @type {number}
+ */
+ccui.PageView.TOUCH_DIR_LEFT = 0;
+/**
+ * The right flag of ccui.PageView's touch direction.
+ * @constant
+ * @type {number}
+ */
+ccui.PageView.TOUCH_DIR_RIGHT = 1;
+
+//PageView auto scroll direction
+/**
+ * The right flag of ccui.PageView's auto scroll direction.
+ * @constant
+ * @type {number}
+ */
+ccui.PageView.DIRECTION_LEFT = 0;
+/**
+ * The right flag of ccui.PageView's auto scroll direction.
+ * @constant
+ * @type {number}
+ */
+ccui.PageView.DIRECTION_RIGHT = 1;
diff --git a/extensions/ccui/uiwidgets/scroll-widget/UIPageViewIndicator.js b/extensions/ccui/uiwidgets/scroll-widget/UIPageViewIndicator.js
new file mode 100644
index 0000000000..8044ba2269
--- /dev/null
+++ b/extensions/ccui/uiwidgets/scroll-widget/UIPageViewIndicator.js
@@ -0,0 +1,305 @@
+/****************************************************************************
+ Copyright (c) 2015 Neo Kim (neo.kim@neofect.com)
+ Copyright (c) 2015 Nikita Besshaposhnikov (nikita.besshaposhnikov@gmail.com)
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The PageViewIndicator control of Cocos UI
+ * Indicator being attached to page view.
+ * @class
+ * @extends ccui.ProtectedNode
+ * @property {Number} spaceBetweenIndexNodes - Space between index nodes in PageViewIndicator
+ */
+ccui.PageViewIndicator = ccui.ProtectedNode.extend(/** @lends ccui.PageViewIndicator# */{
+ _direction: null,
+ _indexNodes: null,
+ _currentIndexNode: null,
+ _spaceBetweenIndexNodes: 0,
+ _indexNodesScale: 1.0,
+ _indexNodesColor: null,
+ _useDefaultTexture: true,
+ _indexNodesTextureFile: "",
+ _indexNodesTexType: ccui.Widget.LOCAL_TEXTURE,
+
+ _className: "PageViewIndicator",
+
+ /**
+ * Allocates and initializes a PageViewIndicator.
+ * Constructor of ccui.PageViewIndicator. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ */
+ ctor: function () {
+ cc.ProtectedNode.prototype.ctor.call(this);
+
+ this._direction = ccui.ScrollView.DIR_HORIZONTAL;
+ this._indexNodes = [];
+ this._spaceBetweenIndexNodes = ccui.PageViewIndicator.SPACE_BETWEEN_INDEX_NODES_DEFAULT;
+ this._indexNodesColor = cc.color.WHITE;
+
+ this._currentIndexNode = ccui.helper._createSpriteFromBase64(ccui.PageViewIndicator.CIRCLE_IMAGE, ccui.PageViewIndicator.CIRCLE_IMAGE_KEY);
+ this._currentIndexNode.setVisible(false);
+ this.addProtectedChild(this._currentIndexNode, 1);
+
+ // this.setCascadeColorEnabled(true);
+ // this.setCascadeOpacityEnabled(true);
+ },
+
+ /**
+ * Sets direction of indicator
+ * @param {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH} direction
+ */
+ setDirection: function (direction) {
+ this._direction = direction;
+ this._rearrange();
+ },
+
+ /**
+ * resets indicator with new page count.
+ * @param {number} numberOfTotalPages
+ */
+ reset: function (numberOfTotalPages) {
+ while (this._indexNodes.length < numberOfTotalPages) {
+ this._increaseNumberOfPages();
+ }
+ while (this._indexNodes.length > numberOfTotalPages) {
+ this._decreaseNumberOfPages();
+ }
+ this._rearrange();
+ this._currentIndexNode.setVisible(this._indexNodes.length > 0);
+ },
+
+ /**
+ * Indicates node by index
+ * @param {number} index
+ */
+ indicate: function (index) {
+ if (index < 0 || index >= this._indexNodes.length) {
+ return;
+ }
+ this._currentIndexNode.setPosition(this._indexNodes[index].getPosition());
+ },
+
+ _rearrange: function () {
+ if (this._indexNodes.length === 0) {
+ return;
+ }
+
+ var horizontal = (this._direction === ccui.ScrollView.DIR_HORIZONTAL);
+
+ // Calculate total size
+ var indexNodeSize = this._indexNodes[0].getContentSize();
+ var sizeValue = (horizontal ? indexNodeSize.width : indexNodeSize.height);
+
+ var numberOfItems = this._indexNodes.length;
+ var totalSizeValue = sizeValue * numberOfItems + this._spaceBetweenIndexNodes * (numberOfItems - 1);
+
+ var posValue = -(totalSizeValue / 2) + (sizeValue / 2);
+ for (var i = 0; i < this._indexNodes.length; ++i) {
+ var position;
+ if (horizontal) {
+ position = cc.p(posValue, indexNodeSize.height / 2.0);
+ }
+ else {
+ position = cc.p(indexNodeSize.width / 2.0, -posValue);
+ }
+ this._indexNodes[i].setPosition(position);
+ posValue += sizeValue + this._spaceBetweenIndexNodes;
+ }
+ },
+
+ /**
+ * Sets space between index nodes.
+ * @param {number} spaceBetweenIndexNodes
+ */
+ setSpaceBetweenIndexNodes: function (spaceBetweenIndexNodes) {
+ if (this._spaceBetweenIndexNodes === spaceBetweenIndexNodes) {
+ return;
+ }
+ this._spaceBetweenIndexNodes = spaceBetweenIndexNodes;
+ this._rearrange();
+ },
+
+ /**
+ * Gets space between index nodes.
+ * @returns {number}
+ */
+ getSpaceBetweenIndexNodes: function () {
+ return this._spaceBetweenIndexNodes;
+ },
+
+ /**
+ * Sets color of selected index node
+ * @param {cc.Color} color
+ */
+ setSelectedIndexColor: function (color) {
+ this._currentIndexNode.setColor(color);
+ },
+
+ /**
+ * Gets color of selected index node
+ * @returns {cc.Color}
+ */
+ getSelectedIndexColor: function () {
+ return this._currentIndexNode.getColor();
+ },
+
+ /**
+ * Sets color of index nodes
+ * @param {cc.Color} indexNodesColor
+ */
+ setIndexNodesColor: function (indexNodesColor) {
+ this._indexNodesColor = indexNodesColor;
+
+ for (var i = 0; i < this._indexNodes.length; ++i) {
+ this._indexNodes[i].setColor(indexNodesColor);
+ }
+ },
+
+ /**
+ * Gets color of index nodes
+ * @returns {cc.Color}
+ */
+ getIndexNodesColor: function () {
+ var locRealColor = this._indexNodesColor;
+ return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
+ },
+
+ /**
+ * Sets scale of index nodes
+ * @param {Number} indexNodesScale
+ */
+ setIndexNodesScale: function (indexNodesScale) {
+ if (this._indexNodesScale === indexNodesScale) {
+ return;
+ }
+ this._indexNodesScale = indexNodesScale;
+
+ this._currentIndexNode.setScale(indexNodesScale);
+
+ for (var i = 0; i < this._indexNodes.length; ++i) {
+ this._indexNodes[i].setScale(this, _indexNodesScale);
+ }
+
+ this._rearrange();
+ },
+
+ /**
+ * Gets scale of index nodes
+ * @returns {Number}
+ */
+ getIndexNodesScale: function () {
+ return this._indexNodesScale;
+ },
+
+ /**
+ * Sets texture of index nodes
+ * @param {String} texName
+ * @param {ccui.Widget.LOCAL_TEXTURE | ccui.Widget.PLIST_TEXTURE} [texType = ccui.Widget.LOCAL_TEXTURE]
+ */
+ setIndexNodesTexture: function (texName, texType) {
+ if (texType === undefined)
+ texType = ccui.Widget.LOCAL_TEXTURE;
+
+ this._useDefaultTexture = false;
+ this._indexNodesTextureFile = texName;
+ this._indexNodesTexType = texType;
+
+ switch (texType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ this._currentIndexNode.setTexture(texName);
+ for (var i = 0; i < this._indexNodes.length; ++i) {
+ this._indexNodes[i].setTexture(texName);
+ }
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ this._currentIndexNode.setSpriteFrame(texName);
+ for (var i = 0; i < this._indexNodes.length; ++i) {
+ this._indexNodes[i].setSpriteFrame(texName);
+ }
+ break;
+ default:
+ break;
+ }
+
+ this._rearrange();
+ },
+
+ _increaseNumberOfPages: function () {
+ var indexNode;
+
+ if (this._useDefaultTexture) {
+ indexNode = ccui.helper._createSpriteFromBase64(ccui.PageViewIndicator.CIRCLE_IMAGE, ccui.PageViewIndicator.CIRCLE_IMAGE_KEY);
+ }
+ else {
+ indexNode = new cc.Sprite();
+ switch (this._indexNodesTexType) {
+ case ccui.Widget.LOCAL_TEXTURE:
+ indexNode.initWithFile(this._indexNodesTextureFile);
+ break;
+ case ccui.Widget.PLIST_TEXTURE:
+ indexNode.initWithSpriteFrameName(this._indexNodesTextureFile);
+ break;
+ default:
+ break;
+ }
+ }
+
+ indexNode.setColor(this._indexNodesColor);
+ indexNode.setScale(this._indexNodesScale);
+
+ this.addProtectedChild(indexNode);
+ this._indexNodes.push(indexNode);
+ },
+
+ _decreaseNumberOfPages: function () {
+ if (this._indexNodes.length === 0) {
+ return;
+ }
+ this.removeProtectedChild(this._indexNodes[0]);
+ this._indexNodes.splice(0, 1);
+ },
+
+ /**
+ * Removes all index nodes.
+ */
+ clear: function () {
+ for (var i = 0; i < this._indexNodes.length; ++i) {
+ this.removeProtectedChild(this._indexNodes[i]);
+ }
+ this._indexNodes.length = 0;
+ this._currentIndexNode.setVisible(false);
+ }
+
+});
+
+var _p = ccui.PageViewIndicator.prototype;
+
+// Extended properties
+/** @expose */
+_p.spaceBetweenIndexNodes;
+cc.defineGetterSetter(_p, "spaceBetweenIndexNodes", _p.getSpaceBetweenIndexNodes, _p.setSpaceBetweenIndexNodes);
+/**
+ * @ignore
+ */
+ccui.PageViewIndicator.SPACE_BETWEEN_INDEX_NODES_DEFAULT = 23;
+ccui.PageViewIndicator.CIRCLE_IMAGE_KEY = "/__circle_image";
+ccui.PageViewIndicator.CIRCLE_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAA8ElEQVRIx62VyRGCQBBF+6gWRCEmYDIQkhiBCgHhSclC8YqWzOV5oVzKAYZp3r1/9fpbxAIBMTsKrjx5cqVgR0wgLhCRUWOjJiPqD56xoaGPhpRZV/iSEy6crHmw5oIrF9b/lVeMofrJgjlnxlIy/wik+JB+mme8BExbBhm+5CJC2LE2LtSEQoyGWDioBA5CoRIohJtK4CYDxzNEM4GAugR1E9VjVC+SZpXvhCJCrjomESLvc17pDGX7bWmlh6UtpjPVCWy9zaJ0TD7qfm3pwERMz2trRVZk3K3BD/L34AY+dEDCniMVBkPFkT2J/b2/AIV+dRpFLOYoAAAAAElFTkSuQmCC";
diff --git a/extensions/ccui/uiwidgets/scroll-widget/UIScrollView.js b/extensions/ccui/uiwidgets/scroll-widget/UIScrollView.js
new file mode 100644
index 0000000000..79741c9525
--- /dev/null
+++ b/extensions/ccui/uiwidgets/scroll-widget/UIScrollView.js
@@ -0,0 +1,1927 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The ScrollView control of Cocos UI
+ * @class
+ * @extends ccui.Layout
+ *
+ * @property {Number} innerWidth - Inner container width of the scroll view
+ * @property {Number} innerHeight - Inner container height of the scroll view
+ * @property {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH} direction - Scroll direction of the scroll view
+ * @property {Boolean} bounceEnabled - Indicate whether bounce is enabled
+ * @property {Boolean} inertiaScrollEnabled - Indicate whether inertiaScroll is enabled
+ * @property {Number} touchTotalTimeThreshold - Touch total time threshold
+ */
+ccui.ScrollView = ccui.Layout.extend(/** @lends ccui.ScrollView# */{
+ _innerContainer: null,
+ _direction: null,
+
+ _topBoundary: 0,
+ _bottomBoundary: 0,
+ _leftBoundary: 0,
+ _rightBoundary: 0,
+
+ _touchMoveDisplacements: null,
+ _touchMoveTimeDeltas: null,
+ _touchMovePreviousTimestamp: 0,
+ _touchTotalTimeThreshold: 0.5,
+
+ _autoScrolling: false,
+ _autoScrollTargetDelta: null,
+ _autoScrollAttenuate: true,
+ _autoScrollStartPosition: null,
+ _autoScrollTotalTime: 0,
+ _autoScrollAccumulatedTime: 0,
+ _autoScrollCurrentlyOutOfBoundary: false,
+ _autoScrollBraking: false,
+ _autoScrollBrakingStartPosition: null,
+
+ _bePressed: false,
+
+ _childFocusCancelOffset: 0,
+
+ bounceEnabled: false,
+
+ _outOfBoundaryAmount: null,
+ _outOfBoundaryAmountDirty: true,
+
+ inertiaScrollEnabled: false,
+
+ _scrollBarEnabled: true,
+ _verticalScrollBar: null,
+ _horizontalScrollBar: null,
+
+ _scrollViewEventListener: null,
+ _scrollViewEventSelector: null,
+ _className: "ScrollView",
+
+ /**
+ * Allocates and initializes a UIScrollView.
+ * Constructor of ccui.ScrollView. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @example
+ * // example
+ * var uiScrollView = new ccui.ScrollView();
+ */
+ ctor: function () {
+ ccui.Layout.prototype.ctor.call(this);
+ this.setClippingEnabled(true);
+ this._innerContainer.setTouchEnabled(false);
+
+ this._direction = ccui.ScrollView.DIR_NONE;
+
+ this._childFocusCancelOffset = 5;
+ this.inertiaScrollEnabled = true;
+
+ this._outOfBoundaryAmount = cc.p(0, 0);
+ this._autoScrollTargetDelta = cc.p(0, 0);
+ this._autoScrollStartPosition = cc.p(0, 0);
+ this._autoScrollBrakingStartPosition = cc.p(0, 0);
+ this._touchMoveDisplacements = [];
+ this._touchMoveTimeDeltas = [];
+ this._touchMovePreviousTimestamp = 0;
+
+ this._scrollBarEnabled = true;
+ this._initScrollBar();
+
+ this.setTouchEnabled(true);
+ },
+
+ /**
+ * Calls the parent class' onEnter and schedules update function.
+ * @override
+ */
+ onEnter: function () {
+ ccui.Layout.prototype.onEnter.call(this);
+ this.scheduleUpdate();
+ },
+
+ onExit: function () {
+ cc.renderer._removeCache(this.__instanceId);
+ ccui.Layout.prototype.onExit.call(this);
+ },
+
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ this._adaptRenderers();
+ this._doLayout();
+
+ var renderer = cc.renderer;
+ cmd.visit(parentCmd);
+
+ renderer.pushRenderCommand(cmd);
+ if (cmd instanceof ccui.ScrollView.WebGLRenderCmd) {
+ var currentID = this.__instanceId;
+ renderer._turnToCacheMode(currentID);
+ }
+
+ var stencilClipping = this._clippingEnabled && this._clippingType === ccui.Layout.CLIPPING_STENCIL;
+ var scissorClipping = this._clippingEnabled && this._clippingType === ccui.Layout.CLIPPING_SCISSOR;
+
+ if (stencilClipping) {
+ cmd.stencilClippingVisit(parentCmd);
+ }
+ else if (scissorClipping) {
+ cmd.scissorClippingVisit(parentCmd);
+ }
+
+ var i, children = this._children, len = children.length, child;
+ var j, pChildren = this._protectedChildren, pLen = pChildren.length, pChild;
+
+ if (this._reorderChildDirty) this.sortAllChildren();
+ if (this._reorderProtectedChildDirty) this.sortAllProtectedChildren();
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child && child._visible) {
+ child.visit(this);
+ }
+ }
+ for (j = 0; j < pLen; j++) {
+ pChild = pChildren[j];
+ if (pChild && pChild._visible) {
+ cmd._changeProtectedChild(pChild);
+ pChild.visit(this);
+ }
+ }
+
+ if (stencilClipping) {
+ cmd.postStencilVisit();
+ }
+ else if (scissorClipping) {
+ cmd.postScissorVisit();
+ }
+
+ if (cmd instanceof ccui.ScrollView.WebGLRenderCmd) {
+ renderer._turnToNormalMode();
+ }
+
+ // Need to update children after do layout
+ this.updateChildren();
+
+ cmd._dirtyFlag = 0;
+ },
+
+ /**
+ * When a widget is in a layout, you could call this method to get the next focused widget within a specified _direction.
+ * If the widget is not in a layout, it will return itself
+ *
+ * @param {Number} _direction the _direction to look for the next focused widget in a layout
+ * @param {ccui.Widget} current the current focused widget
+ * @returns {ccui.Widget}
+ */
+ findNextFocusedWidget: function (direction, current) {
+ if (this.getLayoutType() === ccui.Layout.LINEAR_VERTICAL
+ || this.getLayoutType() === ccui.Layout.LINEAR_HORIZONTAL) {
+ return this._innerContainer.findNextFocusedWidget(direction, current);
+ } else
+ return ccui.Widget.prototype.findNextFocusedWidget.call(this, direction, current);
+ },
+
+ _initRenderer: function () {
+ ccui.Layout.prototype._initRenderer.call(this);
+
+ this._innerContainer = new ccui.Layout();
+ this._innerContainer.setColor(cc.color(255, 255, 255));
+ this._innerContainer.setOpacity(255);
+ this._innerContainer.setCascadeColorEnabled(true);
+ this._innerContainer.setCascadeOpacityEnabled(true);
+
+ this.addProtectedChild(this._innerContainer, 1, 1);
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ return new ccui.ScrollView.WebGLRenderCmd(this);
+ else
+ return new ccui.ScrollView.CanvasRenderCmd(this);
+ },
+
+ _onSizeChanged: function () {
+ ccui.Layout.prototype._onSizeChanged.call(this);
+ var locSize = this._contentSize;
+ this._topBoundary = locSize.height;
+ this._rightBoundary = locSize.width;
+ var innerSize = this._innerContainer.getContentSize();
+ this._innerContainer.setContentSize(cc.size(Math.max(innerSize.width, locSize.width), Math.max(innerSize.height, locSize.height)));
+ this._innerContainer.setPosition(0, locSize.height - this._innerContainer.getContentSize().height);
+
+ if(this._verticalScrollBar)
+ this._verticalScrollBar.onScrolled(this._getHowMuchOutOfBoundary());
+
+ if(this._horizontalScrollBar)
+ this._horizontalScrollBar.onScrolled(this._getHowMuchOutOfBoundary());
+ },
+
+ /**
+ * Changes inner container size of ScrollView.
+ * Inner container size must be larger than or equal the size of ScrollView.
+ * @param {cc.Size} size inner container size.
+ */
+ setInnerContainerSize: function (size) {
+ var innerContainer = this._innerContainer,
+ locSize = this._contentSize,
+ innerSizeWidth = locSize.width, innerSizeHeight = locSize.height;
+
+ if (size.width < locSize.width)
+ cc.log("Inner width <= ScrollView width, it will be force sized!");
+ else
+ innerSizeWidth = size.width;
+
+ if (size.height < locSize.height)
+ cc.log("Inner height <= ScrollView height, it will be force sized!");
+ else
+ innerSizeHeight = size.height;
+
+ innerContainer.setContentSize(cc.size(innerSizeWidth, innerSizeHeight));
+
+ var pos = this._innerContainer.getPosition();
+ var contAP = this._innerContainer.getAnchorPoint();
+
+ if (this._innerContainer.getLeftBoundary() != 0.0)
+ {
+ pos.x = contAP.x * innerSizeWidth;
+ }
+ if (this._innerContainer.getTopBoundary() != this._contentSize.height)
+ {
+ pos.y = this._contentSize.height - (1.0 - contAP.y) * innerSizeHeight;
+ }
+ this.setInnerContainerPosition(pos);
+
+ this._updateScrollBar(cc.p(0 ,0));
+ },
+
+ _setInnerWidth: function (width) {
+ var locW = this._contentSize.width,
+ innerWidth = locW,
+ container = this._innerContainer,
+ oldInnerWidth = container.width;
+ if (width < locW)
+ cc.log("Inner width <= scrollview width, it will be force sized!");
+ else
+ innerWidth = width;
+ container.width = innerWidth;
+
+ switch (this._direction) {
+ case ccui.ScrollView.DIR_HORIZONTAL:
+ case ccui.ScrollView.DIR_BOTH:
+ if (container.getRightBoundary() <= locW) {
+ var newInnerWidth = container.width;
+ var offset = oldInnerWidth - newInnerWidth;
+ this._scrollChildren(offset, 0);
+ }
+ break;
+ }
+ var innerAX = container.anchorX;
+ if (container.getLeftBoundary() > 0.0)
+ container.x = innerAX * innerWidth;
+ if (container.getRightBoundary() < locW)
+ container.x = locW - ((1.0 - innerAX) * innerWidth);
+ },
+
+ _setInnerHeight: function (height) {
+ var locH = this._contentSize.height,
+ innerHeight = locH,
+ container = this._innerContainer,
+ oldInnerHeight = container.height;
+ if (height < locH)
+ cc.log("Inner height <= scrollview height, it will be force sized!");
+ else
+ innerHeight = height;
+ container.height = innerHeight;
+
+ switch (this._direction) {
+ case ccui.ScrollView.DIR_VERTICAL:
+ case ccui.ScrollView.DIR_BOTH:
+ var newInnerHeight = innerHeight;
+ var offset = oldInnerHeight - newInnerHeight;
+ this._scrollChildren(0, offset);
+ break;
+ }
+ var innerAY = container.anchorY;
+ if (container.getLeftBoundary() > 0.0)
+ container.y = innerAY * innerHeight;
+ if (container.getRightBoundary() < locH)
+ container.y = locH - ((1.0 - innerAY) * innerHeight);
+ },
+ /**
+ * Set inner container position
+ *
+ * @param {cc.Point} position Inner container position.
+ */
+ setInnerContainerPosition: function (position) {
+ if (position.x === this._innerContainer.getPositionX() && position.y === this._innerContainer.getPositionY()) {
+ return;
+ }
+ this._innerContainer.setPosition(position);
+ this._outOfBoundaryAmountDirty = true;
+
+ // Process bouncing events
+ if (this.bounceEnabled) {
+ for (var _direction = ccui.ScrollView.MOVEDIR_TOP; _direction < ccui.ScrollView.MOVEDIR_RIGHT; ++_direction) {
+ if (this._isOutOfBoundary(_direction)) {
+ this._processScrollEvent(_direction, true);
+ }
+ }
+ }
+
+ this._dispatchEvent(ccui.ScrollView.EVENT_CONTAINER_MOVED);
+ },
+
+ /**
+ * Get inner container position
+ *
+ * @return The inner container position.
+ */
+ getInnerContainerPosition: function () {
+ return this._innerContainer.getPosition();
+ },
+
+ /**
+ * Returns inner container size of ScrollView.
+ * Inner container size must be larger than or equal ScrollView's size.
+ *
+ * @return {cc.Size} inner container size.
+ */
+ getInnerContainerSize: function () {
+ return this._innerContainer.getContentSize();
+ },
+ _getInnerWidth: function () {
+ return this._innerContainer.width;
+ },
+ _getInnerHeight: function () {
+ return this._innerContainer.height;
+ },
+
+ _isInContainer: function (widget) {
+ if (!this._clippingEnabled)
+ return true;
+ var wPos = widget._position,
+ wSize = widget._contentSize,
+ wAnchor = widget._anchorPoint,
+ size = this._customSize,
+ pos = this._innerContainer._position,
+ bottom = 0, left = 0;
+ if (
+ // Top
+ (bottom = wPos.y - wAnchor.y * wSize.height) >= size.height - pos.y ||
+ // Bottom
+ bottom + wSize.height <= -pos.y ||
+ // right
+ (left = wPos.x - wAnchor.x * wSize.width) >= size.width - pos.x ||
+ // left
+ left + wSize.width <= -pos.x
+ )
+ return false;
+ else return true;
+ },
+
+ updateChildren: function () {
+ var child, i, l;
+ var childrenArray = this._innerContainer._children;
+ for (i = 0, l = childrenArray.length; i < l; i++) {
+ child = childrenArray[i];
+ if (child._inViewRect === true && this._isInContainer(child) === false)
+ child._inViewRect = false;
+ else if (child._inViewRect === false && this._isInContainer(child) === true)
+ child._inViewRect = true;
+ }
+ },
+ /**
+ * Add child to ccui.ScrollView.
+ * @param {cc.Node} widget
+ * @param {Number} [zOrder]
+ * @param {Number|string} [tag] tag or name
+ * @returns {boolean}
+ */
+ addChild: function (widget, zOrder, tag) {
+ if (!widget)
+ return false;
+ if (this._isInContainer(widget) === false)
+ widget._inViewRect = false;
+ zOrder = zOrder || widget.getLocalZOrder();
+ tag = tag || widget.getTag();
+ return this._innerContainer.addChild(widget, zOrder, tag);
+ },
+
+ /**
+ * Removes all children.
+ */
+ removeAllChildren: function () {
+ this.removeAllChildrenWithCleanup(true);
+ },
+
+ /**
+ * Removes all children.
+ * @param {Boolean} cleanup
+ */
+ removeAllChildrenWithCleanup: function (cleanup) {
+ this._innerContainer.removeAllChildrenWithCleanup(cleanup);
+ },
+
+ /**
+ * Removes widget child
+ * @override
+ * @param {ccui.Widget} child
+ * @param {Boolean} cleanup
+ * @returns {boolean}
+ */
+ removeChild: function (child, cleanup) {
+ return this._innerContainer.removeChild(child, cleanup);
+ },
+
+ /**
+ * Returns inner container's children
+ * @returns {Array}
+ */
+ getChildren: function () {
+ return this._innerContainer.getChildren();
+ },
+
+ /**
+ * Gets the count of inner container's children
+ * @returns {Number}
+ */
+ getChildrenCount: function () {
+ return this._innerContainer.getChildrenCount();
+ },
+
+ /**
+ * Gets a child from the container given its tag
+ * @param {Number} tag
+ * @returns {ccui.Widget}
+ */
+ getChildByTag: function (tag) {
+ return this._innerContainer.getChildByTag(tag);
+ },
+
+ /**
+ * Gets a child from the container given its name
+ * @param {String} name
+ * @returns {ccui.Widget}
+ */
+ getChildByName: function (name) {
+ return this._innerContainer.getChildByName(name);
+ },
+
+ _flattenVectorByDirection: function (vector) {
+ var result = cc.p(0, 0);
+ result.x = (this._direction === ccui.ScrollView.DIR_VERTICAL ? 0 : vector.x);
+ result.y = (this._direction === ccui.ScrollView.DIR_HORIZONTAL ? 0 : vector.y);
+ return result;
+ },
+
+ _getHowMuchOutOfBoundary: function (addition) {
+ if (addition === undefined)
+ addition = cc.p(0, 0);
+
+ if (addition.x === 0 && addition.y === 0 && !this._outOfBoundaryAmountDirty) {
+ return this._outOfBoundaryAmount;
+ }
+
+ var outOfBoundaryAmount = cc.p(0, 0);
+
+ if (this._innerContainer.getLeftBoundary() + addition.x > this._leftBoundary) {
+ outOfBoundaryAmount.x = this._leftBoundary - (this._innerContainer.getLeftBoundary() + addition.x);
+ }
+ else if (this._innerContainer.getRightBoundary() + addition.x < this._rightBoundary) {
+ outOfBoundaryAmount.x = this._rightBoundary - (this._innerContainer.getRightBoundary() + addition.x);
+ }
+
+ if (this._innerContainer.getTopBoundary() + addition.y < this._topBoundary) {
+ outOfBoundaryAmount.y = this._topBoundary - (this._innerContainer.getTopBoundary() + addition.y);
+ }
+ else if (this._innerContainer.getBottomBoundary() + addition.y > this._bottomBoundary) {
+ outOfBoundaryAmount.y = this._bottomBoundary - (this._innerContainer.getBottomBoundary() + addition.y);
+ }
+
+ if (addition.x === 0 && addition.y === 0) {
+ this._outOfBoundaryAmount = outOfBoundaryAmount;
+ this._outOfBoundaryAmountDirty = false;
+ }
+ return outOfBoundaryAmount;
+ },
+
+ _isOutOfBoundary: function (dir) {
+ var outOfBoundary = this._getHowMuchOutOfBoundary();
+ if (dir !== undefined) {
+ switch (dir) {
+ case ccui.ScrollView.MOVEDIR_TOP:
+ return outOfBoundary.y > 0;
+ case ccui.ScrollView.MOVEDIR_BOTTOM:
+ return outOfBoundary.y < 0;
+ case ccui.ScrollView.MOVEDIR_LEFT:
+ return outOfBoundary.x < 0;
+ case ccui.ScrollView.MOVEDIR_RIGHT:
+ return outOfBoundary.x > 0;
+ }
+ }
+ else {
+ return !this._fltEqualZero(outOfBoundary);
+ }
+
+ return false;
+ },
+
+
+ _moveInnerContainer: function (deltaMove, canStartBounceBack) {
+ var adjustedMove = this._flattenVectorByDirection(deltaMove);
+
+ this.setInnerContainerPosition(cc.pAdd(this.getInnerContainerPosition(), adjustedMove));
+
+ var outOfBoundary = this._getHowMuchOutOfBoundary();
+ this._updateScrollBar(outOfBoundary);
+
+ if (this.bounceEnabled && canStartBounceBack) {
+ this._startBounceBackIfNeeded();
+ }
+ },
+
+ _updateScrollBar: function(outOfBoundary)
+ {
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.onScrolled(outOfBoundary);
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.onScrolled(outOfBoundary);
+ }
+ },
+
+ _calculateTouchMoveVelocity: function () {
+ var totalTime = 0;
+ for (var i = 0; i < this._touchMoveTimeDeltas.length; ++i) {
+ totalTime += this._touchMoveTimeDeltas[i];
+ }
+ if (totalTime == 0 || totalTime >= this._touchTotalTimeThreshold) {
+ return cc.p(0, 0);
+ }
+
+ var totalMovement = cc.p(0, 0);
+
+ for (var i = 0; i < this._touchMoveDisplacements.length; ++i) {
+ totalMovement.x += this._touchMoveDisplacements[i].x;
+ totalMovement.y += this._touchMoveDisplacements[i].y;
+ }
+
+ return cc.pMult(totalMovement, 1 / totalTime);
+ },
+
+ /**
+ * Set the touch total time threshold
+ * @param {Number} touchTotalTimeThreshold
+ */
+ setTouchTotalTimeThreshold: function (touchTotalTimeThreshold) {
+ this._touchTotalTimeThreshold = touchTotalTimeThreshold;
+ },
+
+
+ /**
+ * Get the touch total time threshold
+ * @returns {Number}
+ */
+ getTouchTotalTimeThreshold: function () {
+ return this._touchTotalTimeThreshold;
+ },
+
+ _startInertiaScroll: function (touchMoveVelocity) {
+ var MOVEMENT_FACTOR = 0.7;
+ var inertiaTotalMovement = cc.pMult(touchMoveVelocity, MOVEMENT_FACTOR);
+ this._startAttenuatingAutoScroll(inertiaTotalMovement, touchMoveVelocity);
+ },
+
+ _startBounceBackIfNeeded: function () {
+ if (!this.bounceEnabled) {
+ return false;
+ }
+ var bounceBackAmount = this._getHowMuchOutOfBoundary();
+ if (this._fltEqualZero(bounceBackAmount)) {
+ return false;
+ }
+
+ var BOUNCE_BACK_DURATION = 1.0;
+ this._startAutoScroll(bounceBackAmount, BOUNCE_BACK_DURATION, true);
+ return true;
+ },
+
+ _startAutoScrollToDestination: function (destination, timeInSec, attenuated) {
+ this._startAutoScroll(cc.pSub(destination, this._innerContainer.getPosition()), timeInSec, attenuated);
+ },
+
+ _calculateAutoScrollTimeByInitialSpeed: function (initialSpeed) {
+ // Calculate the time from the initial speed according to quintic polynomial.
+ return Math.sqrt(Math.sqrt(initialSpeed / 5));
+ },
+
+ _startAttenuatingAutoScroll: function (deltaMove, initialVelocity) {
+ var time = this._calculateAutoScrollTimeByInitialSpeed(cc.pLength(initialVelocity));
+ this._startAutoScroll(deltaMove, time, true);
+ },
+
+ _startAutoScroll: function (deltaMove, timeInSec, attenuated) {
+ var adjustedDeltaMove = this._flattenVectorByDirection(deltaMove);
+
+ this._autoScrolling = true;
+ this._autoScrollTargetDelta = adjustedDeltaMove;
+ this._autoScrollAttenuate = attenuated;
+ this._autoScrollStartPosition = this._innerContainer.getPosition();
+ this._autoScrollTotalTime = timeInSec;
+ this._autoScrollAccumulatedTime = 0;
+ this._autoScrollBraking = false;
+ this._autoScrollBrakingStartPosition = cc.p(0, 0);
+
+ // If the destination is also out of boundary of same side, start brake from beggining.
+ var currentOutOfBoundary = this._getHowMuchOutOfBoundary();
+ if (!this._fltEqualZero(currentOutOfBoundary)) {
+ this._autoScrollCurrentlyOutOfBoundary = true;
+ var afterOutOfBoundary = this._getHowMuchOutOfBoundary(adjustedDeltaMove);
+ if (currentOutOfBoundary.x * afterOutOfBoundary.x > 0 || currentOutOfBoundary.y * afterOutOfBoundary.y > 0) {
+ this._autoScrollBraking = true;
+ }
+ }
+ },
+
+ /**
+ * Immediately stops inner container scroll initiated by any of the "scrollTo*" member functions
+ */
+ stopAutoScroll: function () {
+ this._autoScrolling = false;
+ this._autoScrollAttenuate = true;
+ this._autoScrollTotalTime = 0;
+ this._autoScrollAccumulatedTime = 0;
+ },
+
+ _isNecessaryAutoScrollBrake: function () {
+ if (this._autoScrollBraking) {
+ return true;
+ }
+
+ if (this._isOutOfBoundary()) {
+ // It just went out of boundary.
+ if (!this._autoScrollCurrentlyOutOfBoundary) {
+ this._autoScrollCurrentlyOutOfBoundary = true;
+ this._autoScrollBraking = true;
+ this._autoScrollBrakingStartPosition = this.getInnerContainerPosition();
+ return true;
+ }
+ }
+ else {
+ this._autoScrollCurrentlyOutOfBoundary = false;
+ }
+ return false;
+ },
+
+ _getAutoScrollStopEpsilon: function () {
+ return 0.0001;
+ },
+
+ _fltEqualZero: function (point) {
+ return (Math.abs(point.x) <= 0.0001 && Math.abs(point.y) <= 0.0001);
+ },
+
+ _processAutoScrolling: function (deltaTime) {
+ var OUT_OF_BOUNDARY_BREAKING_FACTOR = 0.05;
+ // Make auto scroll shorter if it needs to deaccelerate.
+ var brakingFactor = (this._isNecessaryAutoScrollBrake() ? OUT_OF_BOUNDARY_BREAKING_FACTOR : 1);
+
+ // Elapsed time
+ this._autoScrollAccumulatedTime += deltaTime * (1 / brakingFactor);
+
+ // Calculate the progress percentage
+ var percentage = Math.min(1, this._autoScrollAccumulatedTime / this._autoScrollTotalTime);
+ if (this._autoScrollAttenuate) {
+ percentage -= 1;
+ percentage = percentage * percentage * percentage * percentage * percentage + 1;
+ }
+
+ // Calculate the new position
+ var newPosition = cc.pAdd(this._autoScrollStartPosition, cc.pMult(this._autoScrollTargetDelta, percentage));
+ var reachedEnd = Math.abs(percentage - 1) <= this._getAutoScrollStopEpsilon();
+
+ if (this.bounceEnabled) {
+ // The new position is adjusted if out of boundary
+ newPosition = cc.pAdd(this._autoScrollBrakingStartPosition, cc.pMult(cc.pSub(newPosition, this._autoScrollBrakingStartPosition), brakingFactor));
+ }
+ else {
+ // Don't let go out of boundary
+ var moveDelta = cc.pSub(newPosition, this.getInnerContainerPosition());
+ var outOfBoundary = this._getHowMuchOutOfBoundary(moveDelta);
+ if (!this._fltEqualZero(outOfBoundary)) {
+ newPosition.x += outOfBoundary.x;
+ newPosition.y += outOfBoundary.y;
+
+ reachedEnd = true;
+ }
+ }
+
+ // Finish auto scroll if it ended
+ if (reachedEnd) {
+ this._autoScrolling = false;
+ this._dispatchEvent(ccui.ScrollView.EVENT_AUTOSCROLL_ENDED);
+ }
+
+ this._moveInnerContainer(cc.pSub(newPosition, this.getInnerContainerPosition()), reachedEnd);
+ },
+
+ _jumpToDestination: function (desOrX, y) {
+ if (desOrX.x === undefined) {
+ desOrX = cc.p(desOrX, y);
+ }
+
+ this._autoScrolling = false;
+ this._moveInnerContainer(cc.pSub(desOrX, this.getInnerContainerPosition()), true);
+ },
+
+ _scrollChildren: function (deltaMove) {
+ var realMove = deltaMove;
+ if (this.bounceEnabled) {
+ // If the position of the inner container is out of the boundary, the offsets should be divided by two.
+ var outOfBoundary = this._getHowMuchOutOfBoundary();
+ realMove.x *= (outOfBoundary.x == 0 ? 1 : 0.5);
+ realMove.y *= (outOfBoundary.y == 0 ? 1 : 0.5);
+ }
+
+ if (!this.bounceEnabled) {
+ var outOfBoundary = this._getHowMuchOutOfBoundary(realMove);
+ realMove.x += outOfBoundary.x;
+ realMove.y += outOfBoundary.y;
+ }
+
+ var scrolledToLeft = false;
+ var scrolledToRight = false;
+ var scrolledToTop = false;
+ var scrolledToBottom = false;
+
+ if (realMove.y > 0.0) // up
+ {
+ var icBottomPos = this._innerContainer.getBottomBoundary();
+ if (icBottomPos + realMove.y >= this._bottomBoundary) {
+ scrolledToBottom = true;
+ }
+ }
+ else if (realMove.y < 0.0) // down
+ {
+ var icTopPos = this._innerContainer.getTopBoundary();
+ if (icTopPos + realMove.y <= this._topBoundary) {
+ scrolledToTop = true;
+ }
+ }
+
+ if (realMove.x < 0.0) // left
+ {
+ var icRightPos = this._innerContainer.getRightBoundary();
+ if (icRightPos + realMove.x <= this._rightBoundary) {
+ scrolledToRight = true;
+ }
+ }
+ else if (realMove.x > 0.0) // right
+ {
+ var icLeftPos = this._innerContainer.getLeftBoundary();
+ if (icLeftPos + realMove.x >= this._leftBoundary) {
+ scrolledToLeft = true;
+ }
+ }
+ this._moveInnerContainer(realMove, false);
+
+ if (realMove.x != 0 || realMove.y != 0) {
+ this._processScrollingEvent();
+ }
+ if (scrolledToBottom) {
+ this._processScrollEvent(ccui.ScrollView.MOVEDIR_BOTTOM, false);
+ }
+ if (scrolledToTop) {
+ this._processScrollEvent(ccui.ScrollView.MOVEDIR_TOP, false);
+ }
+ if (scrolledToLeft) {
+ this._processScrollEvent(ccui.ScrollView.MOVEDIR_LEFT, false);
+ }
+ if (scrolledToRight) {
+ this._processScrollEvent(ccui.ScrollView.MOVEDIR_RIGHT, false);
+ }
+ },
+
+ /**
+ * Scroll inner container to bottom boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToBottom: function (time, attenuated) {
+ this._startAutoScrollToDestination(cc.p(this._innerContainer.getPositionX(), 0), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to top boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToTop: function (time, attenuated) {
+ this._startAutoScrollToDestination(
+ cc.p(this._innerContainer.getPositionX(), this._contentSize.height - this._innerContainer.getContentSize().height), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to left boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToLeft: function (time, attenuated) {
+ this._startAutoScrollToDestination(cc.p(0, this._innerContainer.getPositionY()), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to right boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToRight: function (time, attenuated) {
+ this._startAutoScrollToDestination(
+ cc.p(this._contentSize.width - this._innerContainer.getContentSize().width, this._innerContainer.getPositionY()), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to top and left boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToTopLeft: function (time, attenuated) {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll direction is not both!");
+ return;
+ }
+ this._startAutoScrollToDestination(cc.p(0, this._contentSize.height - this._innerContainer.getContentSize().height), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to top and right boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToTopRight: function (time, attenuated) {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll direction is not both!");
+ return;
+ }
+ var inSize = this._innerContainer.getContentSize();
+ this._startAutoScrollToDestination(cc.p(this._contentSize.width - inSize.width,
+ this._contentSize.height - inSize.height), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to bottom and left boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToBottomLeft: function (time, attenuated) {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll direction is not both!");
+ return;
+ }
+ this._startAutoScrollToDestination(cc.p(0, 0), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to bottom and right boundary of ScrollView.
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToBottomRight: function (time, attenuated) {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll direction is not both!");
+ return;
+ }
+ this._startAutoScrollToDestination(cc.p(this._contentSize.width - this._innerContainer.getContentSize().width, 0), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to vertical percent position of ScrollView.
+ * @param {Number} percent
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToPercentVertical: function (percent, time, attenuated) {
+ var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
+ var h = -minY;
+ this._startAutoScrollToDestination(cc.p(this._innerContainer.getPositionX(), minY + percent * h / 100), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to horizontal percent position of ScrollView.
+ * @param {Number} percent
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToPercentHorizontal: function (percent, time, attenuated) {
+ var w = this._innerContainer.getContentSize().width - this._contentSize.width;
+ this._startAutoScrollToDestination(cc.p(-(percent * w / 100), this._innerContainer.getPositionY()), time, attenuated);
+ },
+
+ /**
+ * Scroll inner container to both _direction percent position of ScrollView.
+ * @param {cc.Point} percent
+ * @param {Number} time
+ * @param {Boolean} attenuated
+ */
+ scrollToPercentBothDirection: function (percent, time, attenuated) {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH)
+ return;
+ var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
+ var h = -minY;
+ var w = this._innerContainer.getContentSize().width - this._contentSize.width;
+ this._startAutoScrollToDestination(cc.p(-(percent.x * w / 100), minY + percent.y * h / 100), time, attenuated);
+ },
+
+ /**
+ * Move inner container to bottom boundary of ScrollView.
+ */
+ jumpToBottom: function () {
+ this._jumpToDestination(this._innerContainer.getPositionX(), 0);
+ },
+
+ /**
+ * Move inner container to top boundary of ScrollView.
+ */
+ jumpToTop: function () {
+ this._jumpToDestination(this._innerContainer.getPositionX(), this._contentSize.height - this._innerContainer.getContentSize().height);
+ },
+
+ /**
+ * Move inner container to left boundary of ScrollView.
+ */
+ jumpToLeft: function () {
+ this._jumpToDestination(0, this._innerContainer.getPositionY());
+ },
+
+ /**
+ * Move inner container to right boundary of ScrollView.
+ */
+ jumpToRight: function () {
+ this._jumpToDestination(this._contentSize.width - this._innerContainer.getContentSize().width, this._innerContainer.getPositionY());
+ },
+
+ /**
+ * Move inner container to top and left boundary of ScrollView.
+ */
+ jumpToTopLeft: function () {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll _direction is not both!");
+ return;
+ }
+ this._jumpToDestination(0, this._contentSize.height - this._innerContainer.getContentSize().height);
+ },
+
+ /**
+ * Move inner container to top and right boundary of ScrollView.
+ */
+ jumpToTopRight: function () {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll _direction is not both!");
+ return;
+ }
+ var inSize = this._innerContainer.getContentSize();
+ this._jumpToDestination(this._contentSize.width - inSize.width, this._contentSize.height - inSize.height);
+ },
+
+ /**
+ * Move inner container to bottom and left boundary of ScrollView.
+ */
+ jumpToBottomLeft: function () {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll _direction is not both!");
+ return;
+ }
+ this._jumpToDestination(0, 0);
+ },
+
+ /**
+ * Move inner container to bottom and right boundary of ScrollView.
+ */
+ jumpToBottomRight: function () {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH) {
+ cc.log("Scroll _direction is not both!");
+ return;
+ }
+ this._jumpToDestination(this._contentSize.width - this._innerContainer.getContentSize().width, 0);
+ },
+
+ /**
+ * Move inner container to vertical percent position of ScrollView.
+ * @param {Number} percent The destination vertical percent, accept value between 0 - 100
+ */
+ jumpToPercentVertical: function (percent) {
+ var minY = this._contentSize.height - this._innerContainer.getContentSize().height;
+ var h = -minY;
+ this._jumpToDestination(this._innerContainer.getPositionX(), minY + percent * h / 100);
+ },
+
+ /**
+ * Move inner container to horizontal percent position of ScrollView.
+ * @param {Number} percent The destination vertical percent, accept value between 0 - 100
+ */
+ jumpToPercentHorizontal: function (percent) {
+ var w = this._innerContainer.getContentSize().width - this._contentSize.width;
+ this._jumpToDestination(-(percent * w / 100), this._innerContainer.getPositionY());
+ },
+
+ /**
+ * Move inner container to both _direction percent position of ScrollView.
+ * @param {cc.Point} percent The destination vertical percent, accept value between 0 - 100
+ */
+ jumpToPercentBothDirection: function (percent) {
+ if (this._direction !== ccui.ScrollView.DIR_BOTH)
+ return;
+ var inSize = this._innerContainer.getContentSize();
+ var minY = this._contentSize.height - inSize.height;
+ var h = -minY;
+ var w = inSize.width - this._contentSize.width;
+ this._jumpToDestination(-(percent.x * w / 100), minY + percent.y * h / 100);
+ },
+
+ _gatherTouchMove: function (delta) {
+ var NUMBER_OF_GATHERED_TOUCHES_FOR_MOVE_SPEED = 5;
+ while (this._touchMoveDisplacements.length >= NUMBER_OF_GATHERED_TOUCHES_FOR_MOVE_SPEED) {
+ this._touchMoveDisplacements.splice(0, 1);
+ this._touchMoveTimeDeltas.splice(0, 1)
+ }
+ this._touchMoveDisplacements.push(delta);
+
+ var timestamp = (new Date()).getTime();
+ this._touchMoveTimeDeltas.push((timestamp - this._touchMovePreviousTimestamp) / 1000);
+ this._touchMovePreviousTimestamp = timestamp;
+ },
+
+ _handlePressLogic: function (touch) {
+ this._bePressed = true;
+ this._autoScrolling = false;
+
+ // Clear gathered touch move information
+
+ this._touchMovePreviousTimestamp = (new Date()).getTime();
+ this._touchMoveDisplacements.length = 0;
+ this._touchMoveTimeDeltas.length = 0;
+
+
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.onTouchBegan();
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.onTouchBegan();
+ }
+ },
+
+ _handleMoveLogic: function (touch) {
+ var touchPositionInNodeSpace = this.convertToNodeSpace(touch.getLocation()),
+ previousTouchPositionInNodeSpace = this.convertToNodeSpace(touch.getPreviousLocation());
+ var delta = cc.pSub(touchPositionInNodeSpace, previousTouchPositionInNodeSpace);
+
+ this._scrollChildren(delta);
+ this._gatherTouchMove(delta);
+ },
+
+ _handleReleaseLogic: function (touch) {
+
+ var touchPositionInNodeSpace = this.convertToNodeSpace(touch.getLocation()),
+ previousTouchPositionInNodeSpace = this.convertToNodeSpace(touch.getPreviousLocation());
+ var delta = cc.pSub(touchPositionInNodeSpace, previousTouchPositionInNodeSpace);
+
+ this._gatherTouchMove(delta);
+
+ this._bePressed = false;
+
+ var bounceBackStarted = this._startBounceBackIfNeeded();
+ if (!bounceBackStarted && this.inertiaScrollEnabled) {
+ var touchMoveVelocity = this._calculateTouchMoveVelocity();
+ if (touchMoveVelocity.x !== 0 || touchMoveVelocity.y !== 0) {
+ this._startInertiaScroll(touchMoveVelocity);
+ }
+ }
+
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.onTouchEnded();
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.onTouchEnded();
+ }
+ },
+
+ /**
+ * The touch began event callback handler of ccui.ScrollView.
+ * @param {cc.Touch} touch
+ * @param {cc.Event} event
+ * @returns {boolean}
+ */
+ onTouchBegan: function (touch, event) {
+ var pass = ccui.Layout.prototype.onTouchBegan.call(this, touch, event);
+ if (!this._isInterceptTouch) {
+ if (this._hit)
+ this._handlePressLogic(touch);
+ }
+ return pass;
+ },
+
+ /**
+ * The touch moved event callback handler of ccui.ScrollView.
+ * @param {cc.Touch} touch
+ * @param {cc.Event} event
+ */
+ onTouchMoved: function (touch, event) {
+ ccui.Layout.prototype.onTouchMoved.call(this, touch, event);
+ if (!this._isInterceptTouch)
+ this._handleMoveLogic(touch);
+ },
+
+ /**
+ * The touch ended event callback handler of ccui.ScrollView.
+ * @param {cc.Touch} touch
+ * @param {cc.Event} event
+ */
+ onTouchEnded: function (touch, event) {
+ ccui.Layout.prototype.onTouchEnded.call(this, touch, event);
+ if (!this._isInterceptTouch)
+ this._handleReleaseLogic(touch);
+ this._isInterceptTouch = false;
+ },
+
+ /**
+ * The touch canceled event callback of ccui.ScrollView.
+ * @param {cc.Touch} touch
+ * @param {cc.Event} event
+ */
+ onTouchCancelled: function (touch, event) {
+ ccui.Layout.prototype.onTouchCancelled.call(this, touch, event);
+ if (!this._isInterceptTouch)
+ this._handleReleaseLogic(touch);
+ this._isInterceptTouch = false;
+ },
+
+ /**
+ * The update callback handler.
+ * @param {Number} dt
+ */
+ update: function (dt) {
+ if (this._autoScrolling)
+ this._processAutoScrolling(dt);
+ },
+
+ /**
+ * Intercept touch event, handle its child's touch event.
+ * @override
+ * @param {number} event event type
+ * @param {ccui.Widget} sender
+ * @param {cc.Touch} touch
+ */
+ interceptTouchEvent: function (event, sender, touch) {
+ if (!this._touchEnabled) {
+ ccui.Layout.prototype.interceptTouchEvent.call(this, event, sender, touch);
+ return;
+ }
+
+ if (this._direction === ccui.ScrollView.DIR_NONE)
+ return;
+
+ var touchPoint = touch.getLocation();
+ switch (event) {
+ case ccui.Widget.TOUCH_BEGAN:
+ this._isInterceptTouch = true;
+ this._touchBeganPosition.x = touchPoint.x;
+ this._touchBeganPosition.y = touchPoint.y;
+ this._handlePressLogic(touch);
+ break;
+ case ccui.Widget.TOUCH_MOVED:
+ var offset = cc.pLength(cc.pSub(sender.getTouchBeganPosition(), touchPoint));
+ this._touchMovePosition.x = touchPoint.x;
+ this._touchMovePosition.y = touchPoint.y;
+ if (offset > this._childFocusCancelOffset) {
+ sender.setHighlighted(false);
+ this._handleMoveLogic(touch);
+ }
+ break;
+ case ccui.Widget.TOUCH_CANCELED:
+ case ccui.Widget.TOUCH_ENDED:
+ this._touchEndPosition.x = touchPoint.x;
+ this._touchEndPosition.y = touchPoint.y;
+ this._handleReleaseLogic(touch);
+ if (sender.isSwallowTouches())
+ this._isInterceptTouch = false;
+ break;
+ }
+ },
+
+ _processScrollEvent: function (_directionEvent, bounce) {
+ var event = 0;
+
+ switch (_directionEvent) {
+ case ccui.ScrollView.MOVEDIR_TOP:
+ event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_TOP : ccui.ScrollView.EVENT_SCROLL_TO_TOP);
+ break;
+ case ccui.ScrollView.MOVEDIR_BOTTOM:
+ event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_BOTTOM : ccui.ScrollView.EVENT_SCROLL_TO_BOTTOM);
+ break;
+ case ccui.ScrollView.MOVEDIR_LEFT:
+ event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_LEFT : ccui.ScrollView.EVENT_SCROLL_TO_LEFT);
+ break;
+ case ccui.ScrollView.MOVEDIR_RIGHT:
+ event = (bounce ? ccui.ScrollView.EVENT_BOUNCE_RIGHT : ccui.ScrollView.EVENT_SCROLL_TO_RIGHT);
+ break;
+ }
+
+ this._dispatchEvent(event);
+ },
+
+ _processScrollingEvent: function () {
+ this._dispatchEvent(ccui.ScrollView.EVENT_SCROLLING);
+ },
+
+ _dispatchEvent: function (event) {
+ if (this._scrollViewEventSelector) {
+ if (this._scrollViewEventListener)
+ this._scrollViewEventSelector.call(this._scrollViewEventListener, this, event);
+ else
+ this._scrollViewEventSelector(this, event);
+ }
+ if (this._ccEventCallback)
+ this._ccEventCallback(this, event);
+ },
+
+ /**
+ * Adds callback function called ScrollView event triggered
+ * @param {Function} selector
+ * @param {Object} [target=]
+ * @deprecated since v3.0, please use addEventListener instead.
+ */
+ addEventListenerScrollView: function (selector, target) {
+ this._scrollViewEventSelector = selector;
+ this._scrollViewEventListener = target;
+ },
+
+ /**
+ * Adds callback function called ScrollView event triggered
+ * @param {Function} selector
+ */
+ addEventListener: function (selector) {
+ this._ccEventCallback = selector;
+ },
+
+ /**
+ * Changes scroll _direction of ScrollView.
+ * @param {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH} dir
+ * Direction::VERTICAL means vertical scroll, Direction::HORIZONTAL means horizontal scroll
+ */
+ setDirection: function (dir) {
+ this._direction = dir;
+
+ if(this._scrollBarEnabled)
+ {
+ this._removeScrollBar();
+ this._initScrollBar();
+ }
+ },
+
+ /**
+ * Returns scroll direction of ScrollView.
+ * @returns {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_BOTH}
+ */
+ getDirection: function () {
+ return this._direction;
+ },
+
+ /**
+ * Sets bounce enabled
+ * @param {Boolean} enabled
+ */
+ setBounceEnabled: function (enabled) {
+ this.bounceEnabled = enabled;
+ },
+
+ /**
+ * Returns whether bounce is enabled
+ * @returns {boolean}
+ */
+ isBounceEnabled: function () {
+ return this.bounceEnabled;
+ },
+
+ /**
+ * Sets inertiaScroll enabled
+ * @param {boolean} enabled
+ */
+ setInertiaScrollEnabled: function (enabled) {
+ this.inertiaScrollEnabled = enabled;
+ },
+
+ /**
+ * Returns whether inertiaScroll is enabled
+ * @returns {boolean}
+ */
+ isInertiaScrollEnabled: function () {
+ return this.inertiaScrollEnabled;
+ },
+
+ /**
+ * Toggle scroll bar enabled.
+ * @param {boolean} enabled True if enable scroll bar, false otherwise.
+ */
+ setScrollBarEnabled: function(enabled)
+ {
+ if(this._scrollBarEnabled === enabled)
+ {
+ return;
+ }
+
+ if(this._scrollBarEnabled)
+ {
+ this._removeScrollBar();
+ }
+ this._scrollBarEnabled = enabled;
+ if(this._scrollBarEnabled)
+ {
+ this._initScrollBar();
+ }
+ },
+ /**
+ * Query scroll bar state.
+ * @returns {boolean} True if scroll bar is enabled, false otherwise.
+ */
+ isScrollBarEnabled: function()
+ {
+ return this._scrollBarEnabled;
+ },
+
+ /**
+ * Set the scroll bar positions from the left-bottom corner (horizontal) and right-top corner (vertical).
+ * @param {cc.Point} positionFromCorner The position from the left-bottom corner (horizontal) and right-top corner (vertical).
+ */
+ setScrollBarPositionFromCorner: function(positionFromCorner)
+ {
+ if(this._direction !== ccui.ScrollView.DIR_HORIZONTAL)
+ {
+ this.setScrollBarPositionFromCornerForVertical(positionFromCorner);
+ }
+ if(this._direction !== ccui.ScrollView.DIR_VERTICAL)
+ {
+ this.setScrollBarPositionFromCornerForHorizontal(positionFromCorner);
+ }
+ },
+
+ /**
+ * Set the vertical scroll bar position from right-top corner.
+ * @param {cc.Point} positionFromCorner The position from right-top corner
+ */
+ setScrollBarPositionFromCornerForVertical: function(positionFromCorner)
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ cc.assert(this._direction !== ccui.ScrollView.DIR_HORIZONTAL, "Scroll view doesn't have a vertical scroll bar!");
+ this._verticalScrollBar.setPositionFromCorner(positionFromCorner);
+ },
+
+ /**
+ * Get the vertical scroll bar's position from right-top corner.
+ * @returns {cc.Point}
+ */
+ getScrollBarPositionFromCornerForVertical: function()
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ cc.assert(this._direction !== ccui.ScrollView.DIR_HORIZONTAL, "Scroll view doesn't have a vertical scroll bar!");
+ return this._verticalScrollBar.getPositionFromCorner();
+ },
+
+ /**
+ * Set the horizontal scroll bar position from left-bottom corner.
+ * @param {cc.Point} positionFromCorner The position from left-bottom corner
+ */
+ setScrollBarPositionFromCornerForHorizontal: function(positionFromCorner)
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ cc.assert(this._direction !== ccui.ScrollView.DIR_VERTICAL, "Scroll view doesn't have a horizontal scroll bar!");
+ this._horizontalScrollBar.setPositionFromCorner(positionFromCorner);
+ },
+
+ /**
+ * Get the horizontal scroll bar's position from right-top corner.
+ * @returns {cc.Point}
+ */
+ getScrollBarPositionFromCornerForHorizontal: function()
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ cc.assert(this._direction !== ccui.ScrollView.DIR_VERTICAL, "Scroll view doesn't have a horizontal scroll bar!");
+ return this._horizontalScrollBar.getPositionFromCorner();
+ },
+
+ /**
+ * Set the scroll bar's width
+ * @param {number} width The scroll bar's width
+ */
+ setScrollBarWidth: function(width)
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.setWidth(width);
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.setWidth(width);
+ }
+ },
+
+ /**
+ * Get the scroll bar's width
+ * @returns {number} the scroll bar's width
+ */
+ getScrollBarWidth: function()
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ return this._verticalScrollBar.getWidth();
+ }
+ if(this._horizontalScrollBar)
+ {
+ return this._horizontalScrollBar.getWidth();
+ }
+ return 0;
+ },
+
+ /**
+ * Set the scroll bar's color
+ * @param {cc.Color} color the scroll bar's color
+ */
+ setScrollBarColor: function(color)
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.setColor(color);
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.setColor(color);
+ }
+ },
+
+ /**
+ * Get the scroll bar's color
+ * @returns {cc.Color} the scroll bar's color
+ */
+ getScrollBarColor: function()
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.getColor();
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.getColor();
+ }
+ return cc.color.WHITE;
+ },
+
+ /**
+ * Set the scroll bar's opacity
+ * @param {number} opacity the scroll bar's opacity
+ */
+ setScrollBarOpacity: function(opacity)
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.opacity = opacity;
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.opacity = opacity;
+ }
+ },
+
+ /**
+ * Get the scroll bar's opacity
+ * @returns {number}
+ */
+ getScrollBarOpacity: function()
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ return this._verticalScrollBar.opacity;
+ }
+ if(this._horizontalScrollBar)
+ {
+ return this._horizontalScrollBar.opacity;
+ }
+ return -1;
+ },
+
+ /**
+ * Set scroll bar auto hide state
+ * @param {boolean} autoHideEnabled scroll bar auto hide state
+ */
+ setScrollBarAutoHideEnabled: function(autoHideEnabled)
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.autoHideEnabled = autoHideEnabled;
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.autoHideEnabled = autoHideEnabled;
+ }
+ },
+
+ /**
+ * Query scroll bar auto hide state
+ * @returns {boolean}
+ */
+ isScrollBarAutoHideEnabled: function()
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ return this._verticalScrollBar.autoHideEnabled;
+ }
+ if(this._horizontalScrollBar)
+ {
+ return this._horizontalScrollBar.autoHideEnabled;
+ }
+ return false;
+ },
+
+ /**
+ * Set scroll bar auto hide time
+ * @param {number} autoHideTime scroll bar auto hide state
+ */
+ setScrollBarAutoHideTime: function(autoHideTime)
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ this._verticalScrollBar.autoHideTime = autoHideTime;
+ }
+ if(this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar.autoHideTime = autoHideTime;
+ }
+ },
+
+ /**
+ * Get the scroll bar's auto hide time
+ * @returns {number}
+ */
+ getScrollBarAutoHideTime: function()
+ {
+ cc.assert(this._scrollBarEnabled, "Scroll bar should be enabled!");
+ if(this._verticalScrollBar)
+ {
+ return this._verticalScrollBar.autoHideTime;
+ }
+ if(this._horizontalScrollBar)
+ {
+ return this._horizontalScrollBar.autoHideTime;
+ }
+ return 0;
+ },
+
+ /**
+ * Gets inner container of ScrollView. Inner container is the container of ScrollView's children.
+ * @returns {ccui.Layout}
+ */
+ getInnerContainer: function () {
+ return this._innerContainer;
+ },
+
+ /**
+ * Sets LayoutType of ccui.ScrollView.
+ * @param {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE} type
+ */
+ setLayoutType: function (type) {
+ this._innerContainer.setLayoutType(type);
+ },
+
+ /**
+ * Returns the layout type of ccui.ScrollView.
+ * @returns {ccui.Layout.ABSOLUTE|ccui.Layout.LINEAR_VERTICAL|ccui.Layout.LINEAR_HORIZONTAL|ccui.Layout.RELATIVE}
+ */
+ getLayoutType: function () {
+ return this._innerContainer.getLayoutType();
+ },
+
+ _doLayout: function () {
+ if (!this._doLayoutDirty)
+ return;
+ this._doLayoutDirty = false;
+ },
+
+ /**
+ * Returns the "class name" of ccui.ScrollView.
+ * @returns {string}
+ */
+ getDescription: function () {
+ return "ScrollView";
+ },
+
+ _createCloneInstance: function () {
+ return new ccui.ScrollView();
+ },
+
+ _copyClonedWidgetChildren: function (model) {
+ ccui.Layout.prototype._copyClonedWidgetChildren.call(this, model);
+ },
+
+ _copySpecialProperties: function (scrollView) {
+ if (scrollView instanceof ccui.ScrollView) {
+ ccui.Layout.prototype._copySpecialProperties.call(this, scrollView);
+ this.setInnerContainerSize(scrollView.getInnerContainerSize());
+ this.setInnerContainerPosition(scrollView.getInnerContainerPosition());
+ this.setDirection(scrollView._direction);
+
+ this._topBoundary = scrollView._topBoundary;
+ this._bottomBoundary = scrollView._bottomBoundary;
+ this._leftBoundary = scrollView._leftBoundary;
+ this._rightBoundary = scrollView._rightBoundary;
+ this._bePressed = scrollView._bePressed;
+ this._childFocusCancelOffset = scrollView._childFocusCancelOffset;
+ this._touchMoveDisplacements = scrollView._touchMoveDisplacements;
+ this._touchMoveTimeDeltas = scrollView._touchMoveTimeDeltas;
+ this._touchMovePreviousTimestamp = scrollView._touchMovePreviousTimestamp;
+ this._autoScrolling = scrollView._autoScrolling;
+ this._autoScrollAttenuate = scrollView._autoScrollAttenuate;
+ this._autoScrollStartPosition = scrollView._autoScrollStartPosition;
+ this._autoScrollTargetDelta = scrollView._autoScrollTargetDelta;
+ this._autoScrollTotalTime = scrollView._autoScrollTotalTime;
+ this._autoScrollAccumulatedTime = scrollView._autoScrollAccumulatedTime;
+ this._autoScrollCurrentlyOutOfBoundary = scrollView._autoScrollCurrentlyOutOfBoundary;
+ this._autoScrollBraking = scrollView._autoScrollBraking;
+ this._autoScrollBrakingStartPosition = scrollView._autoScrollBrakingStartPosition;
+
+ this.setBounceEnabled(scrollView.bounceEnabled);
+ this.setInertiaScrollEnabled(scrollView.inertiaScrollEnabled);
+
+ this._scrollViewEventListener = scrollView._scrollViewEventListener;
+ this._scrollViewEventSelector = scrollView._scrollViewEventSelector;
+ this._ccEventCallback = scrollView._ccEventCallback;
+
+ this.setScrollBarEnabled(scrollView.isScrollBarEnabled());
+ if(this.isScrollBarEnabled())
+ {
+ if(this._direction !== ccui.ScrollView.DIR_HORIZONTAL)
+ {
+ this.setScrollBarPositionFromCornerForVertical(scrollView.getScrollBarPositionFromCornerForVertical());
+ }
+ if(this._direction !== ccui.ScrollView.DIR_VERTICAL)
+ {
+ this.setScrollBarPositionFromCornerForHorizontal(scrollView.getScrollBarPositionFromCornerForHorizontal());
+ }
+ this.setScrollBarWidth(scrollView.getScrollBarWidth());
+ this.setScrollBarColor(scrollView.getScrollBarColor());
+ this.setScrollBarAutoHideEnabled(scrollView.isScrollBarAutoHideEnabled());
+ this.setScrollBarAutoHideTime(scrollView.getScrollBarAutoHideTime());
+ }
+ }
+ },
+
+ _initScrollBar: function()
+ {
+ if(this._direction !== ccui.ScrollView.DIR_HORIZONTAL && !this._verticalScrollBar)
+ {
+ this._verticalScrollBar = new ccui.ScrollViewBar(this, ccui.ScrollView.DIR_VERTICAL);
+ this.addProtectedChild(this._verticalScrollBar, 2);
+ }
+ if(this._direction !== ccui.ScrollView.DIR_VERTICAL && !this._horizontalScrollBar)
+ {
+ this._horizontalScrollBar = new ccui.ScrollViewBar(this, ccui.ScrollView.DIR_HORIZONTAL);
+ this.addProtectedChild(this._horizontalScrollBar, 2);
+ }
+ },
+
+ _removeScrollBar: function()
+ {
+ if(this._verticalScrollBar)
+ {
+ this.removeProtectedChild(this._verticalScrollBar);
+ this._verticalScrollBar = null;
+ }
+ if(this._horizontalScrollBar)
+ {
+ this.removeProtectedChild(this._horizontalScrollBar);
+ this._horizontalScrollBar = null;
+ }
+ },
+
+ /**
+ * Returns a node by tag
+ * @param {Number} tag
+ * @returns {cc.Node}
+ * @deprecated since v3.0, please use getChildByTag instead.
+ */
+ getNodeByTag: function (tag) {
+ return this._innerContainer.getNodeByTag(tag);
+ },
+
+ /**
+ * Returns all nodes of inner container
+ * @returns {Array}
+ * @deprecated since v3.0, please use getChildren instead.
+ */
+ getNodes: function () {
+ return this._innerContainer.getNodes();
+ },
+
+ /**
+ * Removes a node from ccui.ScrollView.
+ * @param {cc.Node} node
+ * @deprecated since v3.0, please use removeChild instead.
+ */
+ removeNode: function (node) {
+ this._innerContainer.removeNode(node);
+ },
+
+ /**
+ * Removes a node by tag
+ * @param {Number} tag
+ * @deprecated since v3.0, please use removeChildByTag instead.
+ */
+ removeNodeByTag: function (tag) {
+ this._innerContainer.removeNodeByTag(tag);
+ },
+
+ /**
+ * Remove all node from ccui.ScrollView.
+ * @deprecated since v3.0, please use removeAllChildren instead.
+ */
+ removeAllNodes: function () {
+ this._innerContainer.removeAllNodes();
+ },
+
+ /**
+ * Add node for scrollView
+ * @param {cc.Node} node
+ * @param {Number} zOrder
+ * @param {Number} tag
+ * @deprecated since v3.0, please use addChild instead.
+ */
+ addNode: function (node, zOrder, tag) {
+ this._innerContainer.addNode(node, zOrder, tag);
+ }
+});
+
+var _p = ccui.ScrollView.prototype;
+
+// Extended properties
+/** @expose */
+_p.innerWidth;
+cc.defineGetterSetter(_p, "innerWidth", _p._getInnerWidth, _p._setInnerWidth);
+/** @expose */
+_p.innerHeight;
+cc.defineGetterSetter(_p, "innerHeight", _p._getInnerHeight, _p._setInnerHeight);
+/** @expose */
+_p.direction;
+cc.defineGetterSetter(_p, "direction", _p.getDirection, _p.setDirection);
+/** @expose */
+_p.touchTotalTimeThreshold;
+cc.defineGetterSetter(_p, "touchTotalTimeThreshold", _p.getTouchTotalTimeThreshold, _p.setTouchTotalTimeThreshold);
+_p = null;
+/**
+ * allocates and initializes a UIScrollView.
+ * @deprecated since v3.0, please use new ccui.ScrollView() instead.
+ * @return {ccui.ScrollView}
+ */
+ccui.ScrollView.create = function () {
+ return new ccui.ScrollView();
+};
+
+// Constants
+//ScrollView direction
+/**
+ * The none flag of ccui.ScrollView's direction.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.DIR_NONE = 0;
+/**
+ * The vertical flag of ccui.ScrollView's direction.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.DIR_VERTICAL = 1;
+/**
+ * The horizontal flag of ccui.ScrollView's direction.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.DIR_HORIZONTAL = 2;
+/**
+ * The both flag of ccui.ScrollView's direction.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.DIR_BOTH = 3;
+
+//ScrollView event
+/**
+ * The flag scroll to top of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_SCROLL_TO_TOP = 0;
+/**
+ * The flag scroll to bottom of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_SCROLL_TO_BOTTOM = 1;
+/**
+ * The flag scroll to left of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_SCROLL_TO_LEFT = 2;
+/**
+ * The flag scroll to right of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_SCROLL_TO_RIGHT = 3;
+/**
+ * The scrolling flag of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_SCROLLING = 4;
+/**
+ * The flag bounce top of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_BOUNCE_TOP = 5;
+/**
+ * The flag bounce bottom of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_BOUNCE_BOTTOM = 6;
+/**
+ * The flag bounce left of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_BOUNCE_LEFT = 7;
+/**
+ * The flag bounce right of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_BOUNCE_RIGHT = 8;
+/**
+ * The flag container moved of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_CONTAINER_MOVED = 9;
+/**
+ * The flag autoscroll ended of ccui.ScrollView's event.
+ * @constant
+ * @type {number}
+ */
+ccui.ScrollView.EVENT_AUTOSCROLL_ENDED = 10;
+
+/**
+ * @ignore
+ */
+
+ccui.ScrollView.MOVEDIR_TOP = 0;
+ccui.ScrollView.MOVEDIR_BOTTOM = 1;
+ccui.ScrollView.MOVEDIR_LEFT = 2;
+ccui.ScrollView.MOVEDIR_RIGHT = 3;
diff --git a/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewBar.js b/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewBar.js
new file mode 100644
index 0000000000..4e9c1840a7
--- /dev/null
+++ b/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewBar.js
@@ -0,0 +1,343 @@
+/****************************************************************************
+ Copyright (c) 2015 Neo Kim (neo.kim@neofect.com)
+ Copyright (c) 2015 Nikita Besshaposhnikov (nikita.besshaposhnikov@gmail.com)
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The ScrollViewBar control of Cocos UI
+ * Scroll bar being attached to ScrollView layout container.
+ * @class
+ * @extends ccui.ProtectedNode
+ *
+ * @property {Number} opacity - Opacity of the scroll view bar
+ * @property {Boolean} autoHideEnabled - Auto hide is enabled in the scroll view bar
+ * @property {Number} autoHideTime - Auto hide time of the scroll view bar
+ */
+ccui.ScrollViewBar = ccui.ProtectedNode.extend(/** @lends ccui.ScrollViewBar# */{
+ _parentScroll: null,
+ _direction: null,
+
+ _upperHalfCircle: null,
+ _lowerHalfCircle: null,
+ _body: null,
+
+ _opacity: 255,
+
+ _marginFromBoundary: 0,
+ _marginForLength: 0,
+
+ _touching: false,
+
+ _autoHideEnabled: true,
+ autoHideTime: 0,
+ _autoHideRemainingTime: 0,
+ _className: "ScrollViewBar",
+
+ /**
+ * Allocates and initializes a UIScrollViewBar.
+ * Constructor of ccui.ScrollViewBar. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ * @param {ccui.ScrollView} parent A parent of scroll bar.
+ * @param {ccui.ScrollView.DIR_NONE | ccui.ScrollView.DIR_HORIZONTAL | ccui.ScrollView.DIR_VERTICAL | ccui.ScrollView.DIR_BOTH} direction
+ */
+ ctor: function (parent, direction) {
+ cc.ProtectedNode.prototype.ctor.call(this);
+ this._direction = direction;
+ this._parentScroll = parent;
+
+ this._marginFromBoundary = ccui.ScrollViewBar.DEFAULT_MARGIN;
+ this._marginForLength = ccui.ScrollViewBar.DEFAULT_MARGIN;
+ this.opacity = 255 * ccui.ScrollViewBar.DEFAULT_SCROLLBAR_OPACITY;
+ this.autoHideTime = ccui.ScrollViewBar.DEFAULT_AUTO_HIDE_TIME;
+ this._autoHideEnabled = true;
+
+ ccui.ScrollViewBar.prototype.init.call(this);
+
+ this.setCascadeColorEnabled(true);
+ this.setCascadeOpacityEnabled(true);
+ },
+
+ /**
+ * Initializes a ccui.ScrollViewBar. Please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
+ * @returns {boolean}
+ */
+ init: function () {
+ this._upperHalfCircle = ccui.helper._createSpriteFromBase64(ccui.ScrollViewBar.HALF_CIRCLE_IMAGE, ccui.ScrollViewBar.HALF_CIRCLE_IMAGE_KEY);
+ this._upperHalfCircle.setAnchorPoint(cc.p(0.5, 0));
+
+ this._lowerHalfCircle = ccui.helper._createSpriteFromBase64(ccui.ScrollViewBar.HALF_CIRCLE_IMAGE, ccui.ScrollViewBar.HALF_CIRCLE_IMAGE_KEY);
+ this._lowerHalfCircle.setAnchorPoint(cc.p(0.5, 0));
+ this._lowerHalfCircle.setScaleY(-1);
+
+ this.addProtectedChild(this._upperHalfCircle);
+ this.addProtectedChild(this._lowerHalfCircle);
+
+ this._body = ccui.helper._createSpriteFromBase64(ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT, ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT_KEY);
+ this._body.setAnchorPoint(cc.p(0.5, 0));
+ this.addProtectedChild(this._body);
+
+ this.setColor(ccui.ScrollViewBar.DEFAULT_COLOR);
+ this.onScrolled(cc.p(0, 0));
+ cc.ProtectedNode.prototype.setOpacity.call(this, 0);
+ this._autoHideRemainingTime = 0;
+
+ if (this._direction === ccui.ScrollView.DIR_HORIZONTAL) {
+ this.setRotation(90);
+ }
+ },
+
+ /**
+ * Set the scroll bar position from the left-bottom corner (horizontal) or right-top corner (vertical).
+ * @param {cc.Point} positionFromCorner The position from the left-bottom corner (horizontal) or right-top corner (vertical).
+ */
+ setPositionFromCorner: function (positionFromCorner) {
+ if (this._direction === ccui.ScrollView.DIR_VERTICAL) {
+ this._marginForLength = positionFromCorner.y;
+ this._marginFromBoundary = positionFromCorner.x;
+ }
+ else {
+ this._marginForLength = positionFromCorner.x;
+ this._marginFromBoundary = positionFromCorner.y;
+ }
+ },
+
+ onEnter: function () {
+ cc.ProtectedNode.prototype.onEnter.call(this);
+ this.scheduleUpdate();
+ },
+
+ /**
+ * Get the scroll bar position from the left-bottom corner (horizontal) or right-top corner (vertical).
+ * @returns {cc.Point}
+ */
+ getPositionFromCorner: function () {
+ if (this._direction === ccui.ScrollView.DIR_VERTICAL) {
+ return cc.p(this._marginFromBoundary, this._marginForLength);
+ }
+ else {
+ return cc.p(this._marginForLength, this._marginFromBoundary);
+ }
+ },
+ /**
+ * Set the scroll bar's width
+ * @param {number} width The scroll bar's width
+ */
+ setWidth: function (width) {
+ var scale = width / this._body.width;
+ this._body.setScaleX(scale);
+ this._upperHalfCircle.setScale(scale);
+ this._lowerHalfCircle.setScale(-scale);
+ },
+
+ /**
+ * Get the scroll bar's width
+ * @returns {number} the scroll bar's width
+ */
+ getWidth: function () {
+ return this._body.getBoundingBox().width;
+ },
+
+ /**
+ * Set scroll bar auto hide state
+ * @param {boolean} autoHideEnabled scroll bar auto hide state
+ */
+ setAutoHideEnabled: function (autoHideEnabled) {
+ this._autoHideEnabled = autoHideEnabled;
+
+ if (!this._autoHideEnabled && !this._touching && this._autoHideRemainingTime <= 0)
+ cc.ProtectedNode.prototype.setOpacity.call(this, this.opacity);
+ else
+ cc.ProtectedNode.prototype.setOpacity.call(this, 0);
+ },
+ /**
+ * Query scroll bar auto hide state
+ * @returns {boolean} True if scroll bar auto hide is enabled, false otherwise.
+ */
+ isAutoHideEnabled: function () {
+ return this._autoHideEnabled;
+ },
+
+ /**
+ * Set scroll bar opacity
+ * @param {number} opacity scroll bar opacity
+ */
+ setOpacity: function (opacity) {
+ this._opacity = opacity;
+ },
+
+ /**
+ * Get scroll bar opacity
+ * @returns {number}
+ */
+ getOpacity: function () {
+ return this._opacity;
+ },
+
+ _updateLength: function (length) {
+ var ratio = length / this._body.getTextureRect().height;
+ this._body.setScaleY(ratio);
+ this._upperHalfCircle.setPositionY(this._body.getPositionY() + length);
+ },
+
+ _processAutoHide: function (dt) {
+ if (!this._autoHideEnabled || this._autoHideRemainingTime <= 0) {
+ return;
+ }
+ else if (this._touching) {
+ // If it is touching, don't auto hide.
+ return;
+ }
+
+ this._autoHideRemainingTime -= dt;
+ if (this._autoHideRemainingTime <= this.autoHideTime) {
+ this._autoHideRemainingTime = Math.max(0, this._autoHideRemainingTime);
+ cc.ProtectedNode.prototype.setOpacity.call(this, this._opacity * (this._autoHideRemainingTime / this.autoHideTime));
+ }
+ },
+
+
+ update: function (dt) {
+ this._processAutoHide(dt);
+ },
+
+ /**
+ * This is called by parent ScrollView when a touch is began. Don't call this directly.
+ */
+ onTouchBegan: function () {
+ if (!this._autoHideEnabled) {
+ return;
+ }
+ this._touching = true;
+ },
+
+ /**
+ * This is called by parent ScrollView when a touch is ended. Don't call this directly.
+ */
+ onTouchEnded: function () {
+ if (!this._autoHideEnabled) {
+ return;
+ }
+ this._touching = false;
+
+ if (this._autoHideRemainingTime <= 0) {
+ // If the remaining time is 0, it means that it didn't moved after touch started so scroll bar is not showing.
+ return;
+ }
+ this._autoHideRemainingTime = this.autoHideTime;
+ },
+
+ /**
+ * @brief This is called by parent ScrollView when the parent is scrolled. Don't call this directly.
+ *
+ * @param {cc.Point} outOfBoundary amount how much the inner container of ScrollView is out of boundary
+ */
+ onScrolled: function (outOfBoundary) {
+ if (this._autoHideEnabled) {
+ this._autoHideRemainingTime = this.autoHideTime;
+ cc.ProtectedNode.prototype.setOpacity.call(this, this.opacity);
+ }
+
+ var innerContainer = this._parentScroll.getInnerContainer();
+
+ var innerContainerMeasure = 0;
+ var scrollViewMeasure = 0;
+ var outOfBoundaryValue = 0;
+ var innerContainerPosition = 0;
+
+ if (this._direction === ccui.ScrollView.DIR_VERTICAL) {
+ innerContainerMeasure = innerContainer.height;
+ scrollViewMeasure = this._parentScroll.height;
+ outOfBoundaryValue = outOfBoundary.y;
+ innerContainerPosition = -innerContainer.getPositionY();
+ }
+ else if (this._direction === ccui.ScrollView.DIR_HORIZONTAL) {
+ innerContainerMeasure = innerContainer.width;
+ scrollViewMeasure = this._parentScroll.width;
+ outOfBoundaryValue = outOfBoundary.x;
+ innerContainerPosition = -innerContainer.getPositionX();
+ }
+
+ var length = this._calculateLength(innerContainerMeasure, scrollViewMeasure, outOfBoundaryValue);
+ var position = this._calculatePosition(innerContainerMeasure, scrollViewMeasure, innerContainerPosition, outOfBoundaryValue, length);
+ this._updateLength(length);
+ this.setPosition(position);
+ },
+
+ _calculateLength: function (innerContainerMeasure, scrollViewMeasure, outOfBoundaryValue) {
+ var denominatorValue = innerContainerMeasure;
+ if (outOfBoundaryValue !== 0) {
+ // If it is out of boundary, the length of scroll bar gets shorter quickly.
+ var GETTING_SHORTER_FACTOR = 20;
+ denominatorValue += (outOfBoundaryValue > 0 ? outOfBoundaryValue : -outOfBoundaryValue) * GETTING_SHORTER_FACTOR;
+ }
+
+ var lengthRatio = scrollViewMeasure / denominatorValue;
+ return Math.abs(scrollViewMeasure - 2 * this._marginForLength) * lengthRatio;
+ },
+
+ _calculatePosition: function (innerContainerMeasure, scrollViewMeasure, innerContainerPosition, outOfBoundaryValue, length) {
+ var denominatorValue = innerContainerMeasure - scrollViewMeasure;
+ if (outOfBoundaryValue !== 0) {
+ denominatorValue += Math.abs(outOfBoundaryValue);
+ }
+
+ var positionRatio = 0;
+
+ if (denominatorValue !== 0) {
+ positionRatio = innerContainerPosition / denominatorValue;
+ positionRatio = Math.max(positionRatio, 0);
+ positionRatio = Math.min(positionRatio, 1);
+ }
+
+ var position = (scrollViewMeasure - length - 2 * this._marginForLength) * positionRatio + this._marginForLength;
+
+ if (this._direction === ccui.ScrollView.DIR_VERTICAL) {
+ return cc.p(this._parentScroll.width - this._marginFromBoundary, position);
+ }
+ else {
+ return cc.p(position, this._marginFromBoundary);
+ }
+ }
+
+});
+
+var _p = ccui.ScrollViewBar.prototype;
+
+// Extended properties
+/** @expose */
+_p.opacity;
+cc.defineGetterSetter(_p, "opacity", _p.getOpacity, _p.setOpacity);
+/** @expose */
+_p.autoHideEnabled;
+cc.defineGetterSetter(_p, "autoHideEnabled", _p.isAutoHideEnabled, _p.setAutoHideEnabled);
+
+/**
+ * @ignore
+ */
+ccui.ScrollViewBar.DEFAULT_COLOR = cc.color(52, 65, 87);
+ccui.ScrollViewBar.DEFAULT_MARGIN = 20;
+ccui.ScrollViewBar.DEFAULT_AUTO_HIDE_TIME = 0.2;
+ccui.ScrollViewBar.DEFAULT_SCROLLBAR_OPACITY = 0.4;
+ccui.ScrollViewBar.HALF_CIRCLE_IMAGE_KEY = "/__half_circle_image";
+ccui.ScrollViewBar.HALF_CIRCLE_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAGCAMAAADAMI+zAAAAJ1BMVEX///////////////////////////////////////////////////9Ruv0SAAAADHRSTlMABgcbbW7Hz9Dz+PmlcJP5AAAAMElEQVR4AUXHwQ2AQAhFwYcLH1H6r1djzDK3ASxUpTBeK/uTCyz7dx54b44m4p5cD1MwAooEJyk3AAAAAElFTkSuQmCC";
+ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT_KEY = "/__body_image_height";
+ccui.ScrollViewBar.BODY_IMAGE_1_PIXEL_HEIGHT = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAABCAMAAADdNb8LAAAAA1BMVEX///+nxBvIAAAACklEQVR4AWNABgAADQABYc2cpAAAAABJRU5ErkJggg==";
diff --git a/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewCanvasRenderCmd.js b/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewCanvasRenderCmd.js
new file mode 100644
index 0000000000..4607932e9d
--- /dev/null
+++ b/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewCanvasRenderCmd.js
@@ -0,0 +1,32 @@
+(function () {
+ if (!ccui.ProtectedNode.CanvasRenderCmd)
+ return;
+ ccui.ScrollView.CanvasRenderCmd = function (renderable) {
+ this._layoutCmdCtor(renderable);
+ //this._needDraw = true;
+ this._dirty = false;
+ };
+
+ var proto = ccui.ScrollView.CanvasRenderCmd.prototype = Object.create(ccui.Layout.CanvasRenderCmd.prototype);
+ proto.constructor = ccui.ScrollView.CanvasRenderCmd;
+
+ proto.rendering = function (ctx) {
+ var currentID = this._node.__instanceId;
+ var i, locCmds = cc.renderer._cacheToCanvasCmds[currentID], len,
+ scaleX = cc.view.getScaleX(),
+ scaleY = cc.view.getScaleY();
+ var context = ctx || cc._renderContext;
+ context.computeRealOffsetY();
+
+ this._node.updateChildren();
+
+ for (i = 0, len = locCmds.length; i < len; i++) {
+ var checkNode = locCmds[i]._node;
+ if (checkNode instanceof ccui.ScrollView)
+ continue;
+ if (checkNode && checkNode._parent && checkNode._parent._inViewRect === false)
+ continue;
+ locCmds[i].rendering(context, scaleX, scaleY);
+ }
+ };
+})();
diff --git a/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewWebGLRenderCmd.js b/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewWebGLRenderCmd.js
new file mode 100644
index 0000000000..97ba7ff66b
--- /dev/null
+++ b/extensions/ccui/uiwidgets/scroll-widget/UIScrollViewWebGLRenderCmd.js
@@ -0,0 +1,45 @@
+(function () {
+ if (!ccui.ProtectedNode.WebGLRenderCmd)
+ return;
+ ccui.ScrollView.WebGLRenderCmd = function (renderable) {
+ this._layoutCmdCtor(renderable);
+ this._needDraw = true;
+ this._dirty = false;
+ };
+
+ var proto = ccui.ScrollView.WebGLRenderCmd.prototype = Object.create(ccui.Layout.WebGLRenderCmd.prototype);
+ proto.constructor = ccui.ScrollView.WebGLRenderCmd;
+
+ proto.rendering = function (ctx) {
+ var currentID = this._node.__instanceId,
+ locCmds = cc.renderer._cacheToBufferCmds[currentID],
+ i, len, checkNode, cmd,
+ context = ctx || cc._renderContext;
+ if (!locCmds) {
+ return;
+ }
+
+ this._node.updateChildren();
+
+ // Reset buffer for rendering
+ context.bindBuffer(gl.ARRAY_BUFFER, null);
+
+ for (i = 0, len = locCmds.length; i < len; i++) {
+ cmd = locCmds[i];
+ checkNode = cmd._node;
+ if (checkNode && checkNode._parent && checkNode._parent._inViewRect === false)
+ continue;
+
+ if (cmd.uploadData) {
+ cc.renderer._uploadBufferData(cmd);
+ }
+ else {
+ if (cmd._batchingSize > 0) {
+ cc.renderer._batchRendering();
+ }
+ cmd.rendering(context);
+ }
+ cc.renderer._batchRendering();
+ }
+ };
+})();
diff --git a/extensions/cocostudio/CocoStudio.js b/extensions/cocostudio/CocoStudio.js
new file mode 100644
index 0000000000..fdb2ddcea8
--- /dev/null
+++ b/extensions/cocostudio/CocoStudio.js
@@ -0,0 +1,68 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+/**
+ * The main namespace of Cocostudio, all classes, functions, properties and constants of Spine are defined in this namespace
+ * @namespace
+ * @name ccs
+ */
+var ccs = ccs || {};
+
+/**
+ * The same as cc.Class
+ * @class
+ */
+ccs.Class = ccs.Class || cc.Class;
+ccs.Class.extend = ccs.Class.extend || cc.Class.extend;
+
+/**
+ * The same as cc.Node
+ * @class
+ * @extends ccs.Class
+ */
+ccs.Node = ccs.Node || cc.Node;
+ccs.Node.extend = ccs.Node.extend || cc.Node.extend;
+
+/**
+ * The same as cc.Sprite
+ * @class
+ * @extends ccs.Class
+ */
+ccs.Sprite = ccs.Sprite || cc.Sprite;
+ccs.Sprite.extend = ccs.Sprite.extend || cc.Sprite.extend;
+
+/**
+ * The same as cc.Component
+ * @class
+ * @extends ccs.Class
+ */
+ccs.Component = ccs.Component || cc.Component;
+ccs.Component.extend = ccs.Component.extend || cc.Component.extend;
+
+/**
+ * CocoStudio version
+ * @constant
+ * @type {string}
+ */
+ccs.cocostudioVersion = "v1.3.0.0";
\ No newline at end of file
diff --git a/extensions/cocostudio/action/CCActionFrame.js b/extensions/cocostudio/action/CCActionFrame.js
new file mode 100644
index 0000000000..2571031de9
--- /dev/null
+++ b/extensions/cocostudio/action/CCActionFrame.js
@@ -0,0 +1,530 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//Action frame type
+/**
+ * The flag move action type of Cocostudio frame.
+ * @constant
+ * @type {number}
+ */
+ccs.FRAME_TYPE_MOVE = 0;
+/**
+ * The flag scale action type of Cocostudio frame.
+ * @constant
+ * @type {number}
+ */
+ccs.FRAME_TYPE_SCALE = 1;
+/**
+ * The flag rotate action type of Cocostudio frame.
+ * @constant
+ * @type {number}
+ */
+ccs.FRAME_TYPE_ROTATE = 2;
+/**
+ * The flag tint action type of Cocostudio frame.
+ * @constant
+ * @type {number}
+ */
+ccs.FRAME_TYPE_TINT = 3;
+/**
+ * The flag fade action type of Cocostudio frame.
+ * @constant
+ * @type {number}
+ */
+ccs.FRAME_TYPE_FADE = 4;
+/**
+ * The max flag of Cocostudio frame.
+ * @constant
+ * @type {number}
+ */
+ccs.FRAME_TYPE_MAX = 5;
+
+/**
+ * The ease type of Cocostudio frame.
+ * @constant
+ * @type {Object}
+ */
+ccs.FrameEaseType = {
+ CUSTOM : -1,
+
+ LINEAR : 0,
+
+ SINE_EASEIN : 1,
+ SINE_EASEOUT : 2,
+ SINE_EASEINOUT : 3,
+
+ QUAD_EASEIN : 4,
+ QUAD_EASEOUT : 5,
+ QUAD_EASEINOUT : 6,
+
+ CUBIC_EASEIN : 7,
+ CUBIC_EASEOUT : 8,
+ CUBIC_EASEINOUT : 9,
+
+ QUART_EASEIN : 10,
+ QUART_EASEOUT : 11,
+ QUART_EASEINOUT : 12,
+
+ QUINT_EASEIN : 13,
+ QUINT_EASEOUT : 14,
+ QUINT_EASEINOUT : 15,
+
+ EXPO_EASEIN : 16,
+ EXPO_EASEOUT : 17,
+ EXPO_EASEINOUT : 18,
+
+ CIRC_EASEIN : 19,
+ CIRC_EASEOUT : 20,
+ CIRC_EASEINOUT : 21,
+
+ ELASTIC_EASEIN : 22,
+ ELASTIC_EASEOUT : 23,
+ ELASTIC_EASEINOUT : 24,
+
+ BACK_EASEIN : 25,
+ BACK_EASEOUT : 26,
+ BACK_EASEINOUT : 27,
+
+ BOUNCE_EASEIN : 28,
+ BOUNCE_EASEOUT : 29,
+ BOUNCE_EASEINOUT : 30,
+
+ TWEEN_EASING_MAX: 1000
+};
+
+
+/**
+ * The action frame of Cocostudio. It's the base class of ccs.ActionMoveFrame, ccs.ActionScaleFrame etc.
+ * @class
+ * @extends ccs.Class
+ *
+ * @property {Number} frameType - frame type of ccs.ActionFrame
+ * @property {Number} easingType - easing type of ccs.ActionFrame
+ * @property {Number} frameIndex - frame index of ccs.ActionFrame
+ * @property {Number} time - time of ccs.ActionFrame
+ */
+ccs.ActionFrame = ccs.Class.extend(/** @lends ccs.ActionFrame# */{
+ frameType: 0,
+ easingType: 0,
+ frameIndex: 0,
+ _Parameter: null,
+ time: 0,
+
+ /**
+ * The constructor of cc.ActionFrame.
+ */
+ ctor: function () {
+ this.frameType = 0;
+ this.easingType = ccs.FrameEaseType.LINEAR;
+ this.frameIndex = 0;
+ this.time = 0;
+ },
+
+ /**
+ * Returns the action of ActionFrame. its subClass need override it.
+ * @param {number} duration the duration time of ActionFrame
+ * @param {ccs.ActionFrame} srcFrame source frame.
+ * @returns {null}
+ */
+ getAction: function (duration, srcFrame) {
+ cc.log("Need a definition of for ActionFrame");
+ return null;
+ },
+
+ _getEasingAction : function (action) {
+ if (action === null) {
+ console.error("Action cannot be null!");
+ return null;
+ }
+
+ var resultAction;
+ switch (this.easingType) {
+ case ccs.FrameEaseType.CUSTOM:
+ break;
+ case ccs.FrameEaseType.LINEAR:
+ resultAction = action;
+ break;
+ case ccs.FrameEaseType.SINE_EASEIN:
+ resultAction = action.easing(cc.easeSineIn());
+ break;
+ case ccs.FrameEaseType.SINE_EASEOUT:
+ resultAction = action.easing(cc.easeSineOut());
+ break;
+ case ccs.FrameEaseType.SINE_EASEINOUT:
+ resultAction = action.easing(cc.easeSineInOut());
+ break;
+ case ccs.FrameEaseType.QUAD_EASEIN:
+ resultAction = action.easing(cc.easeQuadraticActionIn());
+ break;
+ case ccs.FrameEaseType.QUAD_EASEOUT:
+ resultAction = action.easing(cc.easeQuadraticActionOut());
+ break;
+ case ccs.FrameEaseType.QUAD_EASEINOUT:
+ resultAction = action.easing(cc.easeQuadraticActionInOut());
+ break;
+ case ccs.FrameEaseType.CUBIC_EASEIN:
+ resultAction = action.easing(cc.easeCubicActionIn());
+ break;
+ case ccs.FrameEaseType.CUBIC_EASEOUT:
+ resultAction = action.easing(cc.easeCubicActionOut());
+ break;
+ case ccs.FrameEaseType.CUBIC_EASEINOUT:
+ resultAction = action.easing(cc.easeCubicActionInOut());
+ break;
+ case ccs.FrameEaseType.QUART_EASEIN:
+ resultAction = action.easing(cc.easeQuarticActionIn());
+ break;
+ case ccs.FrameEaseType.QUART_EASEOUT:
+ resultAction = action.easing(cc.easeQuarticActionOut());
+ break;
+ case ccs.FrameEaseType.QUART_EASEINOUT:
+ resultAction = action.easing(cc.easeQuarticActionInOut());
+ break;
+ case ccs.FrameEaseType.QUINT_EASEIN:
+ resultAction = action.easing(cc.easeQuinticActionIn());
+ break;
+ case ccs.FrameEaseType.QUINT_EASEOUT:
+ resultAction = action.easing(cc.easeQuinticActionOut());
+ break;
+ case ccs.FrameEaseType.QUINT_EASEINOUT:
+ resultAction = action.easing(cc.easeQuinticActionInOut());
+ break;
+ case ccs.FrameEaseType.EXPO_EASEIN:
+ resultAction = action.easing(cc.easeExponentialIn());
+ break;
+ case ccs.FrameEaseType.EXPO_EASEOUT:
+ resultAction = action.easing(cc.easeExponentialOut());
+ break;
+ case ccs.FrameEaseType.EXPO_EASEINOUT:
+ resultAction = action.easing(cc.easeExponentialInOut());
+ break;
+ case ccs.FrameEaseType.CIRC_EASEIN:
+ resultAction = action.easing(cc.easeCircleActionIn());
+ break;
+ case ccs.FrameEaseType.CIRC_EASEOUT:
+ resultAction = action.easing(cc.easeCircleActionOut());
+ break;
+ case ccs.FrameEaseType.CIRC_EASEINOUT:
+ resultAction = action.easing(cc.easeCircleActionInOut());
+ break;
+ case ccs.FrameEaseType.ELASTIC_EASEIN:
+ resultAction = action.easing(cc.easeElasticIn());
+ break;
+ case ccs.FrameEaseType.ELASTIC_EASEOUT:
+ resultAction = action.easing(cc.easeElasticOut());
+ break;
+ case ccs.FrameEaseType.ELASTIC_EASEINOUT:
+ resultAction = action.easing(cc.easeElasticInOut());
+ break;
+ case ccs.FrameEaseType.BACK_EASEIN:
+ resultAction = action.easing(cc.easeBackIn());
+ break;
+ case ccs.FrameEaseType.BACK_EASEOUT:
+ resultAction = action.easing(cc.easeBackOut());
+ break;
+ case ccs.FrameEaseType.BACK_EASEINOUT:
+ resultAction = action.easing(cc.easeBackInOut());
+ break;
+ case ccs.FrameEaseType.BOUNCE_EASEIN:
+ resultAction = action.easing(cc.easeBounceIn());
+ break;
+ case ccs.FrameEaseType.BOUNCE_EASEOUT:
+ resultAction = action.easing(cc.easeBounceOut());
+ break;
+ case ccs.FrameEaseType.BOUNCE_EASEINOUT:
+ resultAction = action.easing(cc.easeBounceInOut());
+ break;
+ }
+
+ return resultAction;
+ },
+
+ /**
+ * Sets the easing parameter to action frame.
+ * @param {Array} parameter
+ */
+ setEasingParameter: function(parameter){
+ this._Parameter = [];
+ for(var i=0;i locFrameIndex ? locFrameIndex : locFrameindex;
+ }
+ if (!bFindFrame)
+ locFrameindex = 0;
+ return locFrameindex;
+ },
+
+ /**
+ * Returns the index of last ccs.ActionFrame.
+ * @returns {number}
+ */
+ getLastFrameIndex: function () {
+ var locFrameindex = -1;
+ var locIsFindFrame = false, locFrameArray = this._frameArray;
+ for (var i = 0, len = this._frameArrayNum; i < len; i++) {
+ var locArray = locFrameArray[i];
+ if (locArray.length <= 0)
+ continue;
+ locIsFindFrame = true;
+ var locFrame = locArray[locArray.length - 1];
+ var locFrameIndex = locFrame.frameIndex;
+ locFrameindex = locFrameindex < locFrameIndex ? locFrameIndex : locFrameindex;
+ }
+ if (!locIsFindFrame)
+ locFrameindex = 0;
+ return locFrameindex;
+ },
+
+ /**
+ * Updates action states to some time.
+ * @param {Number} time
+ * @returns {boolean}
+ */
+ updateActionToTimeLine: function (time) {
+ var locIsFindFrame = false;
+ var locUnitTime = this.getUnitTime();
+ for (var i = 0; i < this._frameArrayNum; i++) {
+ var locArray = this._frameArray[i];
+ if (!locArray)
+ continue;
+
+ for (var j = 0; j < locArray.length; j++) {
+ var locFrame = locArray[j];
+ if (locFrame.frameIndex * locUnitTime === time) {
+ this._easingToFrame(1.0, 1.0, locFrame);
+ locIsFindFrame = true;
+ break;
+ } else if (locFrame.frameIndex * locUnitTime > time) {
+ if (j === 0) {
+ this._easingToFrame(1.0, 1.0, locFrame);
+ locIsFindFrame = false;
+ } else {
+ var locSrcFrame = locArray[j - 1];
+ var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * locUnitTime;
+ var locDelaytime = time - locSrcFrame.frameIndex * locUnitTime;
+ this._easingToFrame(locDuration, 1.0, locSrcFrame);
+ this._easingToFrame(locDuration, locDelaytime / locDuration, locFrame);
+ locIsFindFrame = true;
+ }
+ break;
+ }
+ }
+ }
+ return locIsFindFrame;
+ },
+
+ _easingToFrame: function (duration, delayTime, destFrame) {
+ var action = destFrame.getAction(duration);
+ var node = this.getActionNode();
+ if (action == null || node == null)
+ return;
+ action.startWithTarget(node);
+ action.update(delayTime);
+ },
+
+ /**
+ * Returns if the action is done once time.
+ * @returns {Boolean} that if the action is done once time
+ */
+ isActionDoneOnce: function () {
+ if (!this._action)
+ return true;
+ return this._action.isDone();
+ }
+});
diff --git a/extensions/CocoStudio/Action/CCActionObject.js b/extensions/cocostudio/action/CCActionObject.js
similarity index 55%
rename from extensions/CocoStudio/Action/CCActionObject.js
rename to extensions/cocostudio/action/CCActionObject.js
index 1932562e45..88597f382e 100644
--- a/extensions/CocoStudio/Action/CCActionObject.js
+++ b/extensions/cocostudio/action/CCActionObject.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -23,11 +24,11 @@
****************************************************************************/
/**
- * Base class for cc.ActionObject
+ * The Cocostudio's action object.
* @class
- * @extends cc.Class
+ * @extends ccs.Class
*/
-cc.ActionObject = cc.Class.extend({
+ccs.ActionObject = ccs.Class.extend(/** @lends ccs.ActionObject# */{
_actionNodeList: null,
_name: "",
_loop: false,
@@ -35,6 +36,13 @@ cc.ActionObject = cc.Class.extend({
_playing: false,
_unitTime: 0,
_currentTime: 0,
+ _scheduler:null,
+ _callback: null,
+ _fTotalTime: 0,
+
+ /**
+ * Construction of ccs.ActionObject.
+ */
ctor: function () {
this._actionNodeList = [];
this._name = "";
@@ -43,10 +51,12 @@ cc.ActionObject = cc.Class.extend({
this._playing = false;
this._unitTime = 0.1;
this._currentTime = 0;
+ this._fTotalTime = 0;
+ this._scheduler = cc.director.getScheduler();
},
/**
- * Sets name for object
+ * Sets name to ccs.ActionObject
* @param {string} name
*/
setName: function (name) {
@@ -54,7 +64,7 @@ cc.ActionObject = cc.Class.extend({
},
/**
- * Gets name for object
+ * Returns name fo ccs.ActionObject
* @returns {string}
*/
getName: function () {
@@ -70,7 +80,7 @@ cc.ActionObject = cc.Class.extend({
},
/**
- * Gets if the action will loop play.
+ * Returns if the action will loop play.
* @returns {boolean}
*/
getLoop: function () {
@@ -91,15 +101,15 @@ cc.ActionObject = cc.Class.extend({
},
/**
- * Gets the time interval of frame.
- * @returns {number}
+ * Returns the time interval of frame.
+ * @returns {number} the time interval of frame
*/
getUnitTime: function () {
return this._unitTime;
},
/**
- * Gets the current time of frame.
+ * Returns the current time of frame.
* @returns {number}
*/
getCurrentTime: function () {
@@ -108,15 +118,23 @@ cc.ActionObject = cc.Class.extend({
/**
* Sets the current time of frame.
- * @param time
+ * @param {Number} time the current time of frame
*/
setCurrentTime: function (time) {
this._currentTime = time;
},
/**
- * Return if the action is playing.
- * @returns {boolean}
+ * Returns the total time of frame.
+ * @returns {number} the total time of frame
+ */
+ getTotalTime: function(){
+ return this._fTotalTime;
+ },
+
+ /**
+ * Returns if the action is playing.
+ * @returns {boolean} true if the action is playing, false the otherwise
*/
isPlaying: function () {
return this._playing;
@@ -132,71 +150,83 @@ cc.ActionObject = cc.Class.extend({
this.setLoop(dic["loop"]);
this.setUnitTime(dic["unittime"]);
var actionNodeList = dic["actionnodelist"];
+ var maxLength = 0;
for (var i = 0; i < actionNodeList.length; i++) {
- var locActionNode = new cc.ActionNode();
- var locActionNodeDic = actionNodeList[i];
- locActionNode.initWithDictionary(locActionNodeDic, root);
- locActionNode.setUnitTime(this.getUnitTime());
- this._actionNodeList.push(locActionNode);
- locActionNodeDic = null;
+ var actionNode = new ccs.ActionNode();
+
+ var actionNodeDic = actionNodeList[i];
+ actionNode.initWithDictionary(actionNodeDic, root);
+ actionNode.setUnitTime(this.getUnitTime());
+ this._actionNodeList.push(actionNode);
+ var length = actionNode.getLastFrameIndex() - actionNode.getFirstFrameIndex();
+ if(length > maxLength){
+ maxLength = length;
+ }
}
+ this._fTotalTime = maxLength * this._unitTime;
},
/**
* Adds a ActionNode to play the action.
- * @param {cc.ActionNode} node
+ * @param {ccs.ActionNode} node
*/
addActionNode: function (node) {
- if (!node) {
+ if (!node)
return;
- }
this._actionNodeList.push(node);
node.setUnitTime(this._unitTime);
},
/**
* Removes a ActionNode which play the action.
- * @param {cc.ActionNode} node
+ * @param {ccs.ActionNode} node
*/
removeActionNode: function (node) {
- if (node == null) {
+ if (node == null)
return;
- }
- cc.ArrayRemoveObject(this._actionNodeList, node);
+ cc.arrayRemoveObject(this._actionNodeList, node);
},
/**
- * Play the action.
+ * Plays the action.
+ * @param {cc.CallFunc} [fun] Action Call Back
*/
- play: function () {
+ play: function (fun) {
this.stop();
- var frameNum = this._actionNodeList.length;
+ this.updateToFrameByTime(0);
+ var locActionNodeList = this._actionNodeList;
+ var frameNum = locActionNodeList.length;
for (var i = 0; i < frameNum; i++) {
- var locActionNode = this._actionNodeList[i];
- locActionNode.playAction(this.getLoop());
+ locActionNodeList[i].playAction(fun);
}
+ if (this._loop)
+ this._scheduler.schedule(this.simulationActionUpdate, this, 0, cc.REPEAT_FOREVER, 0, false, this.__instanceId + "");
+ if(fun !== undefined)
+ this._callback = fun;
},
/**
- * pause the action.
+ * Pauses the action.
*/
pause: function () {
this._pause = true;
+ this._playing = false;
},
/**
- * stop the action.
+ * Stop the action.
*/
stop: function () {
- for (var i = 0; i < this._actionNodeList.length; i++) {
- var locActionNode = this._actionNodeList[i];
- locActionNode.stopAction();
- }
+ var locActionNodeList = this._actionNodeList;
+ for (var i = 0; i < locActionNodeList.length; i++)
+ locActionNodeList[i].stopAction();
+ this._scheduler.unschedule(this.simulationActionUpdate, this);
this._pause = false;
+ this._playing = false;
},
/**
- * Method of update frame .
+ * Updates frame by time.
*/
updateToFrameByTime: function (time) {
this._currentTime = time;
@@ -204,5 +234,30 @@ cc.ActionObject = cc.Class.extend({
var locActionNode = this._actionNodeList[i];
locActionNode.updateActionToTimeLine(time);
}
+ },
+
+ /**
+ * scheduler update function
+ * @param {Number} dt delta time
+ */
+ simulationActionUpdate: function (dt) {
+ var isEnd = true, locNodeList = this._actionNodeList;
+ for(var i = 0, len = locNodeList.length; i < len; i++) {
+ if (!locNodeList[i].isActionDoneOnce()){
+ isEnd = false;
+ break;
+ }
+ }
+
+ if (isEnd){
+ if (this._callback !== null)
+ this._callback.execute();
+ if (this._loop)
+ this.play();
+ else{
+ this._playing = false;
+ this._scheduler.unschedule(this.simulationActionUpdate, this);
+ }
+ }
}
});
\ No newline at end of file
diff --git a/extensions/cocostudio/armature/CCArmature.js b/extensions/cocostudio/armature/CCArmature.js
new file mode 100644
index 0000000000..3836c34afd
--- /dev/null
+++ b/extensions/cocostudio/armature/CCArmature.js
@@ -0,0 +1,591 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The main class of Armature, it plays armature animation, manages and updates bones' state.
+ * @class
+ * @extends ccs.Node
+ *
+ * @property {ccs.Bone} parentBone - The parent bone of the armature node
+ * @property {ccs.ArmatureAnimation} animation - The animation
+ * @property {ccs.ArmatureData} armatureData - The armature data
+ * @property {String} name - The name of the armature
+ * @property {cc.SpriteBatchNode} batchNode - The batch node of the armature
+ * @property {Number} version - The version
+ * @property {Object} body - The body of the armature
+ * @property {ccs.ColliderFilter} colliderFilter - <@writeonly> The collider filter of the armature
+ */
+ccs.Armature = ccs.Node.extend(/** @lends ccs.Armature# */{
+ animation: null,
+ armatureData: null,
+ batchNode: null,
+ _parentBone: null,
+ _boneDic: null,
+ _topBoneList: null,
+ _armatureIndexDic: null,
+ _offsetPoint: null,
+ version: 0,
+ _armatureTransformDirty: true,
+ _body: null,
+ _blendFunc: null,
+ _className: "Armature",
+
+ /**
+ * Create a armature node.
+ * Constructor of ccs.Armature
+ * @param {String} name
+ * @param {ccs.Bone} parentBone
+ * @example
+ * var armature = new ccs.Armature();
+ */
+ ctor: function (name, parentBone) {
+ cc.Node.prototype.ctor.call(this);
+ this._name = "";
+ this._topBoneList = [];
+ this._armatureIndexDic = {};
+ this._offsetPoint = cc.p(0, 0);
+ this._armatureTransformDirty = true;
+ this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST};
+ name && ccs.Armature.prototype.init.call(this, name, parentBone);
+ // Hack way to avoid RendererWebGL from skipping Armature
+ this._texture = {};
+ },
+
+ /**
+ * Initializes a CCArmature with the specified name and CCBone
+ * @param {String} [name]
+ * @param {ccs.Bone} [parentBone]
+ * @return {Boolean}
+ */
+ init: function (name, parentBone) {
+ if (parentBone)
+ this._parentBone = parentBone;
+ this.removeAllChildren();
+ this.animation = new ccs.ArmatureAnimation();
+ this.animation.init(this);
+
+ this._boneDic = {};
+ this._topBoneList.length = 0;
+
+ //this._name = name || "";
+ var armatureDataManager = ccs.armatureDataManager;
+
+ var animationData;
+ if (name !== "") {
+ //animationData
+ animationData = armatureDataManager.getAnimationData(name);
+ cc.assert(animationData, "AnimationData not exist!");
+
+ this.animation.setAnimationData(animationData);
+
+ //armatureData
+ var armatureData = armatureDataManager.getArmatureData(name);
+ cc.assert(armatureData, "ArmatureData not exist!");
+
+ this.armatureData = armatureData;
+
+ //boneDataDic
+ var boneDataDic = armatureData.getBoneDataDic();
+ for (var key in boneDataDic) {
+ var bone = this.createBone(String(key));
+
+ //! init bone's Tween to 1st movement's 1st frame
+ do {
+ var movData = animationData.getMovement(animationData.movementNames[0]);
+ if (!movData) break;
+
+ var _movBoneData = movData.getMovementBoneData(bone.getName());
+ if (!_movBoneData || _movBoneData.frameList.length <= 0) break;
+
+ var frameData = _movBoneData.getFrameData(0);
+ if (!frameData) break;
+
+ bone.getTweenData().copy(frameData);
+ bone.changeDisplayWithIndex(frameData.displayIndex, false);
+ } while (0);
+ }
+
+ this.update(0);
+ this.updateOffsetPoint();
+ } else {
+ name = "new_armature";
+ this.armatureData = new ccs.ArmatureData();
+ this.armatureData.name = name;
+
+ animationData = new ccs.AnimationData();
+ animationData.name = name;
+
+ armatureDataManager.addArmatureData(name, this.armatureData);
+ armatureDataManager.addAnimationData(name, animationData);
+
+ this.animation.setAnimationData(animationData);
+ }
+
+ this._renderCmd.initShaderCache();
+
+ this.setCascadeOpacityEnabled(true);
+ this.setCascadeColorEnabled(true);
+ return true;
+ },
+
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ cmd.visit(parentCmd);
+ cmd._dirtyFlag = 0;
+ },
+
+ addChild: function (child, localZOrder, tag) {
+ if (child instanceof ccui.Widget) {
+ cc.log("Armature doesn't support to add Widget as its child, it will be fix soon.");
+ return;
+ }
+ cc.Node.prototype.addChild.call(this, child, localZOrder, tag);
+ },
+
+ /**
+ * create a bone with name
+ * @param {String} boneName
+ * @return {ccs.Bone}
+ */
+ createBone: function (boneName) {
+ var existedBone = this.getBone(boneName);
+ if (existedBone)
+ return existedBone;
+
+ var boneData = this.armatureData.getBoneData(boneName);
+ var parentName = boneData.parentName;
+
+ var bone = null;
+ if (parentName) {
+ this.createBone(parentName);
+ bone = new ccs.Bone(boneName);
+ this.addBone(bone, parentName);
+ } else {
+ bone = new ccs.Bone(boneName);
+ this.addBone(bone, "");
+ }
+
+ bone.setBoneData(boneData);
+ bone.getDisplayManager().changeDisplayWithIndex(-1, false);
+ return bone;
+ },
+
+ /**
+ * Add a Bone to this Armature
+ * @param {ccs.Bone} bone The Bone you want to add to Armature
+ * @param {String} parentName The parent Bone's name you want to add to. If it's null, then set Armature to its parent
+ */
+ addBone: function (bone, parentName) {
+ cc.assert(bone, "Argument must be non-nil");
+ var locBoneDic = this._boneDic;
+ if (bone.getName())
+ cc.assert(!locBoneDic[bone.getName()], "bone already added. It can't be added again");
+
+ if (parentName) {
+ var boneParent = locBoneDic[parentName];
+ if (boneParent)
+ boneParent.addChildBone(bone);
+ else
+ this._topBoneList.push(bone);
+ } else
+ this._topBoneList.push(bone);
+ bone.setArmature(this);
+
+ locBoneDic[bone.getName()] = bone;
+ this.addChild(bone);
+ },
+
+ /**
+ * Remove a bone with the specified name. If recursion it will also remove child Bone recursively.
+ * @param {ccs.Bone} bone The bone you want to remove
+ * @param {Boolean} recursion Determine whether remove the bone's child recursion.
+ */
+ removeBone: function (bone, recursion) {
+ cc.assert(bone, "bone must be added to the bone dictionary!");
+
+ bone.setArmature(null);
+ bone.removeFromParent(recursion);
+ cc.arrayRemoveObject(this._topBoneList, bone);
+
+ delete this._boneDic[bone.getName()];
+ this.removeChild(bone, true);
+ },
+
+ /**
+ * Gets a bone with the specified name
+ * @param {String} name The bone's name you want to get
+ * @return {ccs.Bone}
+ */
+ getBone: function (name) {
+ return this._boneDic[name];
+ },
+
+ /**
+ * Change a bone's parent with the specified parent name.
+ * @param {ccs.Bone} bone The bone you want to change parent
+ * @param {String} parentName The new parent's name
+ */
+ changeBoneParent: function (bone, parentName) {
+ cc.assert(bone, "bone must be added to the bone dictionary!");
+
+ var parentBone = bone.getParentBone();
+ if (parentBone) {
+ cc.arrayRemoveObject(parentBone.getChildren(), bone);
+ bone.setParentBone(null);
+ }
+
+ if (parentName) {
+ var boneParent = this._boneDic[parentName];
+ if (boneParent) {
+ boneParent.addChildBone(bone);
+ cc.arrayRemoveObject(this._topBoneList, bone);
+ } else
+ this._topBoneList.push(bone);
+ }
+ },
+
+ /**
+ * Get CCArmature's bone dictionary
+ * @return {Object} Armature's bone dictionary
+ */
+ getBoneDic: function () {
+ return this._boneDic;
+ },
+
+ /**
+ * Set contentSize and Calculate anchor point.
+ */
+ updateOffsetPoint: function () {
+ // Set contentsize and Calculate anchor point.
+ var rect = this.getBoundingBox();
+ this.setContentSize(rect);
+ var locOffsetPoint = this._offsetPoint;
+ locOffsetPoint.x = -rect.x;
+ locOffsetPoint.y = -rect.y;
+ if (rect.width !== 0 && rect.height !== 0)
+ this.setAnchorPoint(locOffsetPoint.x / rect.width, locOffsetPoint.y / rect.height);
+ },
+
+ getOffsetPoints: function () {
+ return {x: this._offsetPoint.x, y: this._offsetPoint.y};
+ },
+
+ /**
+ * Sets animation to this Armature
+ * @param {ccs.ArmatureAnimation} animation
+ */
+ setAnimation: function (animation) {
+ this.animation = animation;
+ },
+
+ /**
+ * Gets the animation of this Armature.
+ * @return {ccs.ArmatureAnimation}
+ */
+ getAnimation: function () {
+ return this.animation;
+ },
+
+ /**
+ * armatureTransformDirty getter
+ * @returns {Boolean}
+ */
+ getArmatureTransformDirty: function () {
+ return this._armatureTransformDirty;
+ },
+
+ /**
+ * The update callback of ccs.Armature, it updates animation's state and updates bone's state.
+ * @override
+ * @param {Number} dt
+ */
+ update: function (dt) {
+ this.animation.update(dt);
+ var locTopBoneList = this._topBoneList;
+ for (var i = 0; i < locTopBoneList.length; i++)
+ locTopBoneList[i].update(dt);
+ this._armatureTransformDirty = false;
+ },
+
+ /**
+ * The callback when ccs.Armature enter stage.
+ * @override
+ */
+ onEnter: function () {
+ cc.Node.prototype.onEnter.call(this);
+ this.scheduleUpdate();
+ },
+
+ /**
+ * The callback when ccs.Armature exit stage.
+ * @override
+ */
+ onExit: function () {
+ cc.Node.prototype.onExit.call(this);
+ this.unscheduleUpdate();
+ },
+
+ /**
+ * This boundingBox will calculate all bones' boundingBox every time
+ * @returns {cc.Rect}
+ */
+ getBoundingBox: function () {
+ var minX, minY, maxX, maxY = 0;
+ var first = true;
+
+ var boundingBox = cc.rect(0, 0, 0, 0), locChildren = this._children;
+
+ var len = locChildren.length;
+ for (var i = 0; i < len; i++) {
+ var bone = locChildren[i];
+ if (bone) {
+ var r = bone.getDisplayManager().getBoundingBox();
+ if (r.x === 0 && r.y === 0 && r.width === 0 && r.height === 0)
+ continue;
+
+ if (first) {
+ minX = r.x;
+ minY = r.y;
+ maxX = r.x + r.width;
+ maxY = r.y + r.height;
+ first = false;
+ } else {
+ minX = r.x < boundingBox.x ? r.x : boundingBox.x;
+ minY = r.y < boundingBox.y ? r.y : boundingBox.y;
+ maxX = r.x + r.width > boundingBox.x + boundingBox.width ?
+ r.x + r.width : boundingBox.x + boundingBox.width;
+ maxY = r.y + r.height > boundingBox.y + boundingBox.height ?
+ r.y + r.height : boundingBox.y + boundingBox.height;
+ }
+
+ boundingBox.x = minX;
+ boundingBox.y = minY;
+ boundingBox.width = maxX - minX;
+ boundingBox.height = maxY - minY;
+ }
+ }
+ return cc.rectApplyAffineTransform(boundingBox, this.getNodeToParentTransform());
+ },
+
+ /**
+ * when bone contain the point ,then return it.
+ * @param {Number} x
+ * @param {Number} y
+ * @returns {ccs.Bone}
+ */
+ getBoneAtPoint: function (x, y) {
+ var locChildren = this._children;
+ for (var i = locChildren.length - 1; i >= 0; i--) {
+ var child = locChildren[i];
+ if (child instanceof ccs.Bone && child.getDisplayManager().containPoint(x, y))
+ return child;
+ }
+ return null;
+ },
+
+ /**
+ * Sets parent bone of this Armature
+ * @param {ccs.Bone} parentBone
+ */
+ setParentBone: function (parentBone) {
+ this._parentBone = parentBone;
+ var locBoneDic = this._boneDic;
+ for (var key in locBoneDic) {
+ locBoneDic[key].setArmature(this);
+ }
+ },
+
+ /**
+ * Return parent bone of ccs.Armature.
+ * @returns {ccs.Bone}
+ */
+ getParentBone: function () {
+ return this._parentBone;
+ },
+
+ /**
+ * draw contour
+ */
+ drawContour: function () {
+ cc._drawingUtil.setDrawColor(255, 255, 255, 255);
+ cc._drawingUtil.setLineWidth(1);
+ var locBoneDic = this._boneDic;
+ for (var key in locBoneDic) {
+ var bone = locBoneDic[key];
+ var detector = bone.getColliderDetector();
+ if (!detector)
+ continue;
+ var bodyList = detector.getColliderBodyList();
+ for (var i = 0; i < bodyList.length; i++) {
+ var body = bodyList[i];
+ var vertexList = body.getCalculatedVertexList();
+ cc._drawingUtil.drawPoly(vertexList, vertexList.length, true);
+ }
+ }
+ },
+
+ setBody: function (body) {
+ if (this._body === body)
+ return;
+
+ this._body = body;
+ this._body.data = this;
+ var child, displayObject, locChildren = this._children;
+ for (var i = 0; i < locChildren.length; i++) {
+ child = locChildren[i];
+ if (child instanceof ccs.Bone) {
+ var displayList = child.getDisplayManager().getDecorativeDisplayList();
+ for (var j = 0; j < displayList.length; j++) {
+ displayObject = displayList[j];
+ var detector = displayObject.getColliderDetector();
+ if (detector)
+ detector.setBody(this._body);
+ }
+ }
+ }
+ },
+
+ getShapeList: function () {
+ if (this._body)
+ return this._body.shapeList;
+ return null;
+ },
+
+ getBody: function () {
+ return this._body;
+ },
+
+ /**
+ * Sets the blendFunc to ccs.Armature
+ * @param {cc.BlendFunc|Number} blendFunc
+ * @param {Number} [dst]
+ */
+ setBlendFunc: function (blendFunc, dst) {
+ if (dst === undefined) {
+ this._blendFunc.src = blendFunc.src;
+ this._blendFunc.dst = blendFunc.dst;
+ } else {
+ this._blendFunc.src = blendFunc;
+ this._blendFunc.dst = dst;
+ }
+ },
+
+ /**
+ * Returns the blendFunc of ccs.Armature
+ * @returns {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
+ },
+
+ /**
+ * set collider filter
+ * @param {ccs.ColliderFilter} filter
+ */
+ setColliderFilter: function (filter) {
+ var locBoneDic = this._boneDic;
+ for (var key in locBoneDic)
+ locBoneDic[key].setColliderFilter(filter);
+ },
+
+ /**
+ * Returns the armatureData of ccs.Armature
+ * @return {ccs.ArmatureData}
+ */
+ getArmatureData: function () {
+ return this.armatureData;
+ },
+
+ /**
+ * Sets armatureData to this Armature
+ * @param {ccs.ArmatureData} armatureData
+ */
+ setArmatureData: function (armatureData) {
+ this.armatureData = armatureData;
+ },
+
+ getBatchNode: function () {
+ return this.batchNode;
+ },
+
+ setBatchNode: function (batchNode) {
+ this.batchNode = batchNode;
+ },
+
+ /**
+ * version getter
+ * @returns {Number}
+ */
+ getVersion: function () {
+ return this.version;
+ },
+
+ /**
+ * version setter
+ * @param {Number} version
+ */
+ setVersion: function (version) {
+ this.version = version;
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new ccs.Armature.CanvasRenderCmd(this);
+ else
+ return new ccs.Armature.WebGLRenderCmd(this);
+ }
+});
+
+var _p = ccs.Armature.prototype;
+
+/** @expose */
+_p.parentBone;
+cc.defineGetterSetter(_p, "parentBone", _p.getParentBone, _p.setParentBone);
+/** @expose */
+_p.body;
+cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody);
+/** @expose */
+_p.colliderFilter;
+cc.defineGetterSetter(_p, "colliderFilter", null, _p.setColliderFilter);
+
+_p = null;
+
+/**
+ * Allocates an armature, and use the ArmatureData named name in ArmatureDataManager to initializes the armature.
+ * @param {String} [name] Bone name
+ * @param {ccs.Bone} [parentBone] the parent bone
+ * @return {ccs.Armature}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.Armature.create = function (name, parentBone) {
+ return new ccs.Armature(name, parentBone);
+};
diff --git a/extensions/cocostudio/armature/CCArmatureCanvasRenderCmd.js b/extensions/cocostudio/armature/CCArmatureCanvasRenderCmd.js
new file mode 100644
index 0000000000..bdb35f970f
--- /dev/null
+++ b/extensions/cocostudio/armature/CCArmatureCanvasRenderCmd.js
@@ -0,0 +1,213 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ ccs.Armature.RenderCmd = {
+ _updateAnchorPointInPoint: function () {
+ var node = this._node;
+ var contentSize = node._contentSize, anchorPoint = node._anchorPoint, offsetPoint = node._offsetPoint;
+ this._anchorPointInPoints.x = contentSize.width * anchorPoint.x - offsetPoint.x;
+ this._anchorPointInPoints.y = contentSize.height * anchorPoint.y - offsetPoint.y;
+
+ this._realAnchorPointInPoints.x = contentSize.width * anchorPoint.x;
+ this._realAnchorPointInPoints.y = contentSize.height * anchorPoint.y;
+ this.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ },
+
+ getAnchorPointInPoints: function () {
+ return cc.p(this._realAnchorPointInPoints);
+ }
+ };
+})();
+
+(function () {
+ ccs.Armature.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+
+ this._realAnchorPointInPoints = new cc.Point(0, 0);
+ this._canUseDirtyRegion = true;
+ this._startRenderCmd = new cc.CustomRenderCmd(this, this._startCmdCallback);
+ this._RestoreRenderCmd = new cc.CustomRenderCmd(this, this._RestoreCmdCallback);
+ this._startRenderCmd._canUseDirtyRegion = true;
+ this._RestoreRenderCmd._canUseDirtyRegion = true;
+
+ this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ };
+
+ var proto = ccs.Armature.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ cc.inject(ccs.Armature.RenderCmd, proto);
+ proto.constructor = ccs.Armature.CanvasRenderCmd;
+
+ proto._startCmdCallback = function (ctx, scaleX, scaleY) {
+ var node = this._node, parent = node._parent;
+ this.transform(parent ? parent._renderCmd : null);
+
+ var wrapper = ctx || cc._renderContext;
+ wrapper.save();
+ //set to armature mode
+ wrapper._switchToArmatureMode(true, this._worldTransform, scaleX, scaleY);
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+
+ var locChildren = this._node._children;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var selBone = locChildren[i];
+ var boneCmd = selBone._renderCmd;
+ if (selBone && selBone.getDisplayRenderNode) {
+ var boneType = selBone.getDisplayRenderNodeType();
+ var selNode = selBone.getDisplayRenderNode();
+ if (selNode && selNode._renderCmd) {
+ var cmd = selNode._renderCmd;
+ cmd.transform(null); //must be null, use transform in armature mode
+ if (boneType !== ccs.DISPLAY_TYPE_ARMATURE && boneType !== ccs.DISPLAY_TYPE_SPRITE) {
+ cc.affineTransformConcatIn(cmd._worldTransform, selBone._worldTransform);
+ }
+
+ //update displayNode's color and opacity, because skin didn't call visit()
+ var flags = cc.Node._dirtyFlags, locFlag = cmd._dirtyFlag, boneFlag = boneCmd._dirtyFlag;
+ var colorDirty = boneFlag & flags.colorDirty,
+ opacityDirty = boneFlag & flags.opacityDirty;
+ if (colorDirty)
+ boneCmd._updateDisplayColor(this._displayedColor);
+ if (opacityDirty)
+ boneCmd._updateDisplayOpacity(this._displayedOpacity);
+ if (colorDirty || opacityDirty)
+ boneCmd._updateColor();
+
+ var parentColor = selBone._renderCmd._displayedColor, parentOpacity = selBone._renderCmd._displayedOpacity;
+ colorDirty = locFlag & flags.colorDirty;
+ opacityDirty = locFlag & flags.opacityDirty;
+ if (colorDirty)
+ cmd._updateDisplayColor(parentColor);
+ if (opacityDirty)
+ cmd._updateDisplayOpacity(parentOpacity);
+ if (colorDirty || opacityDirty) {
+ cmd._updateColor();
+ }
+ }
+ }
+ }
+ };
+
+ proto._RestoreCmdCallback = function (wrapper) {
+ this._cacheDirty = false;
+ wrapper._switchToArmatureMode(false);
+ wrapper.restore();
+ };
+
+ proto.initShaderCache = function () {
+ };
+ proto.setShaderProgram = function () {
+ };
+ proto.updateChildPosition = function (dis, bone) {
+ dis.visit();
+ // cc.renderer.pushRenderCommand(dis._renderCmd);
+ };
+
+ proto.rendering = function (ctx, scaleX, scaleY) {
+ var node = this._node;
+ var locChildren = node._children;
+ var alphaPremultiplied = cc.BlendFunc.ALPHA_PREMULTIPLIED, alphaNonPremultipled = cc.BlendFunc.ALPHA_NON_PREMULTIPLIED;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var selBone = locChildren[i];
+ if (selBone && selBone.getDisplayRenderNode) {
+ var selNode = selBone.getDisplayRenderNode();
+ if (null === selNode)
+ continue;
+
+ selBone._renderCmd._syncStatus(this);
+ switch (selBone.getDisplayRenderNodeType()) {
+ case ccs.DISPLAY_TYPE_SPRITE:
+ selNode.visit(selBone);
+ break;
+ case ccs.DISPLAY_TYPE_ARMATURE:
+ selNode._renderCmd.rendering(ctx, scaleX, scaleY);
+ break;
+ default:
+ selNode.visit(selBone);
+ break;
+ }
+ } else if (selBone instanceof cc.Node) {
+ this._visitNormalChild(selBone);
+ // selBone.visit(this);
+ }
+ }
+ };
+
+ proto._visitNormalChild = function (childNode) {
+ if (!childNode)
+ return;
+
+ var cmd = childNode._renderCmd;
+ // quick return if not visible
+ if (!childNode._visible)
+ return;
+ cmd._curLevel = this._curLevel + 1;
+
+ //visit for canvas
+ var i, children = childNode._children, child;
+ cmd._syncStatus(this);
+ //because armature use transform, not setTransform
+ cmd.transform(null);
+
+ var len = children.length;
+ if (len > 0) {
+ childNode.sortAllChildren();
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0)
+ child.visit(childNode);
+ else
+ break;
+ }
+ cc.renderer.pushRenderCommand(cmd);
+ for (; i < len; i++)
+ children[i].visit(childNode);
+ } else {
+ cc.renderer.pushRenderCommand(cmd);
+ }
+ this._dirtyFlag = 0;
+ };
+
+ proto.visit = function (parentCmd) {
+ var node = this._node;
+ // quick return if not visible. children won't be drawn.
+ if (!node._visible)
+ return;
+
+ this._syncStatus(parentCmd);
+ node.sortAllChildren();
+
+ cc.renderer.pushRenderCommand(this._startRenderCmd);
+ this.rendering();
+ cc.renderer.pushRenderCommand(this._RestoreRenderCmd);
+
+ this._cacheDirty = false;
+ };
+})();
diff --git a/extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js b/extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js
new file mode 100644
index 0000000000..6f24c7b677
--- /dev/null
+++ b/extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js
@@ -0,0 +1,185 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+
+ ccs.Armature.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+
+ this._parentCmd = null;
+ this._realAnchorPointInPoints = new cc.Point(0, 0);
+
+ this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ };
+
+ var proto = ccs.Armature.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ cc.inject(ccs.Armature.RenderCmd, proto);
+ proto.constructor = ccs.Armature.WebGLRenderCmd;
+
+ proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) {
+ var node = this._node, cmd;
+ var parentCmd = this._parentCmd || this;
+
+ var locChildren = node._children;
+ var alphaPremultiplied = cc.BlendFunc.ALPHA_PREMULTIPLIED, alphaNonPremultipled = cc.BlendFunc.ALPHA_NON_PREMULTIPLIED;
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ var selBone = locChildren[i];
+ var boneCmd = selBone._renderCmd;
+ if (selBone && selBone.getDisplayRenderNode) {
+ var selNode = selBone.getDisplayRenderNode();
+ if (null === selNode)
+ continue;
+ cmd = selNode._renderCmd;
+ switch (selBone.getDisplayRenderNodeType()) {
+ case ccs.DISPLAY_TYPE_SPRITE:
+ if (selNode instanceof ccs.Skin) {
+ selNode.setShaderProgram(this._shaderProgram);
+ this._updateColorAndOpacity(cmd, selBone); //because skin didn't call visit()
+ cmd.transform(parentCmd);
+
+ var func = selBone.getBlendFunc();
+ if (func.src !== alphaPremultiplied.src || func.dst !== alphaPremultiplied.dst)
+ selNode.setBlendFunc(selBone.getBlendFunc());
+ else {
+ var tex = selNode.getTexture();
+ if (node._blendFunc.src === alphaPremultiplied.src &&
+ node._blendFunc.dst === alphaPremultiplied.dst &&
+ tex && !tex.hasPremultipliedAlpha()) {
+ selNode.setBlendFunc(alphaNonPremultipled);
+ }
+ else {
+ selNode.setBlendFunc(node._blendFunc);
+ }
+ }
+ // Support batch for Armature skin
+ cc.renderer._uploadBufferData(cmd);
+ }
+ break;
+ case ccs.DISPLAY_TYPE_ARMATURE:
+ selNode.setShaderProgram(this._shaderProgram);
+ this._updateColorAndOpacity(cmd, selBone);
+ cmd._parentCmd = this;
+ // Continue rendering in default
+ default:
+ boneCmd._syncStatus(parentCmd);
+ cmd._syncStatus(boneCmd);
+ if (cmd.uploadData) {
+ cc.renderer._uploadBufferData(cmd);
+ }
+ else if (cmd.rendering) {
+ // Finish previous batch
+ cc.renderer._batchRendering();
+ cmd.rendering(cc._renderContext);
+ }
+ break;
+ }
+ } else if (selBone instanceof cc.Node) {
+ selBone.setShaderProgram(this._shaderProgram);
+ boneCmd._syncStatus(parentCmd);
+ if (boneCmd.uploadData) {
+ cc.renderer._uploadBufferData(boneCmd);
+ }
+ else if (boneCmd.rendering) {
+ // Finish previous batch
+ cc.renderer._batchRendering();
+ boneCmd.rendering(cc._renderContext);
+ }
+ }
+ }
+ this._parentCmd = null;
+ return 0;
+ };
+
+ proto.initShaderCache = function () {
+ this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR);
+ };
+
+ proto.setShaderProgram = function (shaderProgram) {
+ this._glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(shaderProgram);
+ };
+
+ proto._updateColorAndOpacity = function (skinRenderCmd, bone) {
+ //update displayNode's color and opacity
+ var parentColor = bone._renderCmd._displayedColor, parentOpacity = bone._renderCmd._displayedOpacity;
+
+ var flags = cc.Node._dirtyFlags, locFlag = skinRenderCmd._dirtyFlag;
+ var colorDirty = locFlag & flags.colorDirty,
+ opacityDirty = locFlag & flags.opacityDirty;
+ if (colorDirty)
+ skinRenderCmd._updateDisplayColor(parentColor);
+ if (opacityDirty)
+ skinRenderCmd._updateDisplayOpacity(parentOpacity);
+ if (colorDirty || opacityDirty)
+ skinRenderCmd._updateColor();
+ };
+
+ proto.visit = function (parentCmd) {
+ var node = this._node;
+ // quick return if not visible. children won't be drawn.
+ if (!node._visible)
+ return;
+
+ parentCmd = parentCmd || this.getParentRenderCmd();
+ if (parentCmd)
+ this._curLevel = parentCmd._curLevel + 1;
+
+ this._syncStatus(parentCmd);
+
+ node.sortAllChildren();
+ var renderer = cc.renderer,
+ children = node._children, child,
+ i, len = children.length;
+
+ if (isNaN(node._customZ)) {
+ node._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0) {
+ if (isNaN(child._customZ)) {
+ child._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ renderer.pushRenderCommand(this);
+ for (; i < len; i++) {
+ child = children[i];
+ if (isNaN(child._customZ)) {
+ child._vertexZ = renderer.assignedZ;
+ renderer.assignedZ += renderer.assignedZStep;
+ }
+ }
+
+ this._dirtyFlag = 0;
+ };
+})();
diff --git a/extensions/cocostudio/armature/CCBone.js b/extensions/cocostudio/armature/CCBone.js
new file mode 100644
index 0000000000..953e786b87
--- /dev/null
+++ b/extensions/cocostudio/armature/CCBone.js
@@ -0,0 +1,747 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The Bone of Armature, it has bone data, display manager and transform data for armature.
+ * @class
+ * @extends ccs.Node
+ *
+ * @param {String} [name] The name of the bone
+ * @example
+ *
+ * var bone = new ccs.Bone("head");
+ *
+ * @property {ccs.BoneData} boneData - The bone data
+ * @property {ccs.Armature} armature - The armature
+ * @property {ccs.Bone} parentBone - The parent bone
+ * @property {ccs.Armature} childArmature - The child armature
+ * @property {Array} childrenBone - <@readonly> All children bones
+ * @property {ccs.Tween} tween - <@readonly> Tween
+ * @property {ccs.FrameData} tweenData - <@readonly> The tween data
+ * @property {ccs.ColliderFilter} colliderFilter - The collider filter
+ * @property {ccs.DisplayManager} displayManager - The displayManager
+ * @property {Boolean} ignoreMovementBoneData - Indicate whether force the bone to show When CCArmature play a animation and there isn't a CCMovementBoneData of this bone in this CCMovementData.
+ * @property {String} name - The name of the bone
+ * @property {Boolean} blendDirty - Indicate whether the blend is dirty
+ *
+ */
+ccs.Bone = ccs.Node.extend(/** @lends ccs.Bone# */{
+ _boneData: null,
+ _armature: null,
+ _childArmature: null,
+ _displayManager: null,
+ ignoreMovementBoneData: false,
+ _tween: null,
+ _tweenData: null,
+ _parentBone: null,
+ _boneTransformDirty: false,
+ _worldTransform: null,
+ _blendFunc: null,
+ blendDirty: false,
+ _worldInfo: null,
+ _armatureParentBone: null,
+ _dataVersion: 0,
+ _className: "Bone",
+
+ ctor: function (name) {
+ cc.Node.prototype.ctor.call(this);
+ this._tweenData = null;
+ this._parentBone = null;
+ this._armature = null;
+ this._childArmature = null;
+ this._boneData = null;
+ this._tween = null;
+ this._displayManager = null;
+ this.ignoreMovementBoneData = false;
+
+ this._worldTransform = cc.affineTransformMake(1, 0, 0, 1, 0, 0);
+ this._boneTransformDirty = true;
+ this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
+ this.blendDirty = false;
+ this._worldInfo = null;
+
+ this._armatureParentBone = null;
+ this._dataVersion = 0;
+
+ ccs.Bone.prototype.init.call(this, name);
+ },
+
+ /**
+ * Initializes a ccs.Bone with the specified name
+ * @param {String} name bone name
+ * @return {Boolean}
+ */
+ init: function (name) {
+// cc.Node.prototype.init.call(this);
+ if (name)
+ this._name = name;
+ this._tweenData = new ccs.FrameData();
+
+ this._tween = new ccs.Tween(this);
+
+ this._displayManager = new ccs.DisplayManager(this);
+
+ this._worldInfo = new ccs.BaseData();
+ this._boneData = new ccs.BaseData();
+
+ return true;
+ },
+
+ /**
+ * Sets the boneData to ccs.Bone.
+ * @param {ccs.BoneData} boneData
+ */
+ setBoneData: function (boneData) {
+ cc.assert(boneData, "_boneData must not be null");
+
+ if (this._boneData !== boneData)
+ this._boneData = boneData;
+
+ this.setName(this._boneData.name);
+ this._localZOrder = this._boneData.zOrder;
+ this._displayManager.initDisplayList(boneData);
+ },
+
+ /**
+ * Returns boneData of ccs.Bone.
+ * @return {ccs.BoneData}
+ */
+ getBoneData: function () {
+ return this._boneData;
+ },
+
+ /**
+ * Sets the armature reference to ccs.Bone.
+ * @param {ccs.Armature} armature
+ */
+ setArmature: function (armature) {
+ this._armature = armature;
+ if (armature) {
+ this._tween.setAnimation(this._armature.getAnimation());
+ this._dataVersion = this._armature.getArmatureData().dataVersion;
+ this._armatureParentBone = this._armature.getParentBone();
+ } else
+ this._armatureParentBone = null;
+ },
+
+ /**
+ * Returns the armature reference of ccs.Bone.
+ * @return {ccs.Armature}
+ */
+ getArmature: function () {
+ return this._armature;
+ },
+
+ /**
+ * Updates worldTransform by tween data and updates display state
+ * @param {Number} delta
+ */
+ update: function (delta) {
+ if (this._parentBone)
+ this._boneTransformDirty = this._boneTransformDirty || this._parentBone.isTransformDirty();
+
+ if (this._armatureParentBone && !this._boneTransformDirty)
+ this._boneTransformDirty = this._armatureParentBone.isTransformDirty();
+
+ if (this._boneTransformDirty) {
+ var locTweenData = this._tweenData;
+ if (this._dataVersion >= ccs.CONST_VERSION_COMBINED) {
+ ccs.TransformHelp.nodeConcat(locTweenData, this._boneData);
+ locTweenData.scaleX -= 1;
+ locTweenData.scaleY -= 1;
+ }
+
+ var locWorldInfo = this._worldInfo;
+ locWorldInfo.copy(locTweenData);
+ locWorldInfo.x = locTweenData.x + this._position.x;
+ locWorldInfo.y = locTweenData.y + this._position.y;
+ locWorldInfo.scaleX = locTweenData.scaleX * this._scaleX;
+ locWorldInfo.scaleY = locTweenData.scaleY * this._scaleY;
+ locWorldInfo.skewX = locTweenData.skewX + this._skewX + cc.degreesToRadians(this._rotationX);
+ locWorldInfo.skewY = locTweenData.skewY + this._skewY - cc.degreesToRadians(this._rotationY);
+
+ if (this._parentBone)
+ this._applyParentTransform(this._parentBone);
+ else {
+ if (this._armatureParentBone)
+ this._applyParentTransform(this._armatureParentBone);
+ }
+
+ ccs.TransformHelp.nodeToMatrix(locWorldInfo, this._worldTransform);
+ if (this._armatureParentBone)
+ cc.affineTransformConcatIn(this._worldTransform, this._armature.getNodeToParentTransform()); //TODO TransformConcat
+ }
+
+ ccs.displayFactory.updateDisplay(this, delta, this._boneTransformDirty || this._armature.getArmatureTransformDirty());
+ for (var i = 0; i < this._children.length; i++) {
+ var childBone = this._children[i];
+ childBone.update(delta);
+ }
+ this._boneTransformDirty = false;
+ },
+
+ _applyParentTransform: function (parent) {
+ var locWorldInfo = this._worldInfo;
+ var locParentWorldTransform = parent._worldTransform;
+ var locParentWorldInfo = parent._worldInfo;
+ var x = locWorldInfo.x;
+ var y = locWorldInfo.y;
+ locWorldInfo.x = x * locParentWorldTransform.a + y * locParentWorldTransform.c + locParentWorldInfo.x;
+ locWorldInfo.y = x * locParentWorldTransform.b + y * locParentWorldTransform.d + locParentWorldInfo.y;
+ locWorldInfo.scaleX = locWorldInfo.scaleX * locParentWorldInfo.scaleX;
+ locWorldInfo.scaleY = locWorldInfo.scaleY * locParentWorldInfo.scaleY;
+ locWorldInfo.skewX = locWorldInfo.skewX + locParentWorldInfo.skewX;
+ locWorldInfo.skewY = locWorldInfo.skewY + locParentWorldInfo.skewY;
+ },
+
+ /**
+ * Sets BlendFunc to ccs.Bone.
+ * @param {cc.BlendFunc|Number} blendFunc blendFunc or src of blendFunc
+ * @param {Number} [dst] dst of blendFunc
+ */
+ setBlendFunc: function (blendFunc, dst) {
+ var locBlendFunc = this._blendFunc, srcValue, dstValue;
+ if (dst === undefined) {
+ srcValue = blendFunc.src;
+ dstValue = blendFunc.dst;
+ } else {
+ srcValue = blendFunc;
+ dstValue = dst;
+ }
+ if (locBlendFunc.src !== srcValue || locBlendFunc.dst !== dstValue) {
+ locBlendFunc.src = srcValue;
+ locBlendFunc.dst = dstValue;
+ this.blendDirty = true;
+ }
+ },
+
+ /**
+ * Updates display color
+ */
+ updateColor: function () {
+ var display = this._displayManager.getDisplayRenderNode();
+ if (display !== null) {
+ var cmd = this._renderCmd;
+ display.setColor(
+ cc.color(
+ cmd._displayedColor.r * this._tweenData.r / 255,
+ cmd._displayedColor.g * this._tweenData.g / 255,
+ cmd._displayedColor.b * this._tweenData.b / 255));
+ display.setOpacity(cmd._displayedOpacity * this._tweenData.a / 255);
+ }
+ },
+
+ /**
+ * Updates display zOrder
+ */
+ updateZOrder: function () {
+ if (this._armature.getArmatureData().dataVersion >= ccs.CONST_VERSION_COMBINED) {
+ this.setLocalZOrder(this._tweenData.zOrder + this._boneData.zOrder);
+ } else {
+ this.setLocalZOrder(this._tweenData.zOrder);
+ }
+ },
+
+ /**
+ * Adds a child to this bone, and it will let this child call setParent(ccs.Bone) function to set self to it's parent
+ * @param {ccs.Bone} child
+ */
+ addChildBone: function (child) {
+ cc.assert(child, "Argument must be non-nil");
+ cc.assert(!child.parentBone, "child already added. It can't be added again");
+
+ if (this._children.indexOf(child) < 0) {
+ this._children.push(child);
+ child.setParentBone(this);
+ }
+ },
+
+ /**
+ * Removes a child bone
+ * @param {ccs.Bone} bone
+ * @param {Boolean} recursion
+ */
+ removeChildBone: function (bone, recursion) {
+ if (this._children.length > 0 && this._children.getIndex(bone) !== -1) {
+ if (recursion) {
+ var ccbones = bone._children;
+ for (var i = 0; i < ccbones.length; i++) {
+ var ccBone = ccbones[i];
+ bone.removeChildBone(ccBone, recursion);
+ }
+ }
+
+ bone.setParentBone(null);
+ bone.getDisplayManager().setCurrentDecorativeDisplay(null);
+ cc.arrayRemoveObject(this._children, bone);
+ }
+ },
+
+ /**
+ * Removes itself from its parent ccs.Bone.
+ * @param {Boolean} recursion
+ */
+ removeFromParent: function (recursion) {
+ if (this._parentBone)
+ this._parentBone.removeChildBone(this, recursion);
+ },
+
+ /**
+ * Sets parent bone to ccs.Bone.
+ * If _parent is NUll, then also remove this bone from armature.
+ * It will not set the ccs.Armature, if you want to add the bone to a ccs.Armature, you should use ccs.Armature.addBone(bone, parentName).
+ * @param {ccs.Bone} parent the parent bone.
+ */
+ setParentBone: function (parent) {
+ this._parentBone = parent;
+ },
+
+ /**
+ * Returns the parent bone of ccs.Bone.
+ * @returns {ccs.Bone}
+ */
+ getParentBone: function () {
+ return this._parentBone;
+ },
+
+ /**
+ * Sets ccs.Bone's child armature
+ * @param {ccs.Armature} armature
+ */
+ setChildArmature: function (armature) {
+ if (this._childArmature !== armature) {
+ if (armature == null && this._childArmature)
+ this._childArmature.setParentBone(null);
+ this._childArmature = armature;
+ }
+ },
+
+ /**
+ * Returns ccs.Bone's child armature.
+ * @return {ccs.Armature}
+ */
+ getChildArmature: function () {
+ return this._childArmature;
+ },
+
+ /**
+ * Return the tween of ccs.Bone
+ * @return {ccs.Tween}
+ */
+ getTween: function () {
+ return this._tween;
+ },
+
+ /**
+ * Sets the local zOrder to ccs.Bone.
+ * @param {Number} zOrder
+ */
+ setLocalZOrder: function (zOrder) {
+ if (this._localZOrder !== zOrder)
+ cc.Node.prototype.setLocalZOrder.call(this, zOrder);
+ },
+
+ /**
+ * Return the worldTransform of ccs.Bone.
+ * @returns {cc.AffineTransform}
+ */
+ getNodeToArmatureTransform: function () {
+ return this._worldTransform;
+ },
+
+ /**
+ * Returns the world transform of ccs.Bone.
+ * @override
+ * @returns {cc.AffineTransform}
+ */
+ getNodeToWorldTransform: function () {
+ return cc.affineTransformConcat(this._worldTransform, this._armature.getNodeToWorldTransform());
+ },
+
+ /**
+ * Returns the display render node.
+ * @returns {cc.Node}
+ */
+ getDisplayRenderNode: function () {
+ return this._displayManager.getDisplayRenderNode();
+ },
+
+ /**
+ * Returns the type of display render node
+ * @returns {Number}
+ */
+ getDisplayRenderNodeType: function () {
+ return this._displayManager.getDisplayRenderNodeType();
+ },
+
+ /**
+ * Add display and use _displayData init the display.
+ * If index already have a display, then replace it.
+ * If index is current display index, then also change display to _index
+ * @param {ccs.DisplayData} displayData it include the display information, like DisplayType.
+ * If you want to create a sprite display, then create a CCSpriteDisplayData param
+ *@param {Number} index the index of the display you want to replace or add to
+ * -1 : append display from back
+ */
+ addDisplay: function (displayData, index) {
+ index = index || 0;
+ return this._displayManager.addDisplay(displayData, index);
+ },
+
+ /**
+ * Removes display by index.
+ * @param {Number} index display renderer's index
+ */
+ removeDisplay: function (index) {
+ this._displayManager.removeDisplay(index);
+ },
+
+ /**
+ * Changes display by index
+ * @deprecated since v3.0, please use changeDisplayWithIndex instead.
+ * @param {Number} index
+ * @param {Boolean} force
+ */
+ changeDisplayByIndex: function (index, force) {
+ cc.log("changeDisplayByIndex is deprecated. Use changeDisplayWithIndex instead.");
+ this.changeDisplayWithIndex(index, force);
+ },
+
+ /**
+ * Changes display by name
+ * @deprecated since v3.0, please use changeDisplayWithName instead.
+ * @param {String} name
+ * @param {Boolean} force
+ */
+ changeDisplayByName: function (name, force) {
+ cc.log("changeDisplayByName is deprecated. Use changeDisplayWithName instead.");
+ this.changeDisplayWithName(name, force);
+ },
+
+ /**
+ * Changes display with index
+ * @param {Number} index
+ * @param {Boolean} force
+ */
+ changeDisplayWithIndex: function (index, force) {
+ this._displayManager.changeDisplayWithIndex(index, force);
+ },
+
+ /**
+ * Changes display with name
+ * @param {String} name
+ * @param {Boolean} force
+ */
+ changeDisplayWithName: function (name, force) {
+ this._displayManager.changeDisplayWithName(name, force);
+ },
+
+ /**
+ * Returns the collide detector of ccs.Bone.
+ * @returns {*}
+ */
+ getColliderDetector: function () {
+ var decoDisplay = this._displayManager.getCurrentDecorativeDisplay();
+ if (decoDisplay) {
+ var detector = decoDisplay.getColliderDetector();
+ if (detector)
+ return detector;
+ }
+ return null;
+ },
+
+ /**
+ * Sets collider filter to ccs.Bone.
+ * @param {ccs.ColliderFilter} filter
+ */
+ setColliderFilter: function (filter) {
+ var displayList = this._displayManager.getDecorativeDisplayList();
+ for (var i = 0; i < displayList.length; i++) {
+ var locDecoDisplay = displayList[i];
+ var locDetector = locDecoDisplay.getColliderDetector();
+ if (locDetector)
+ locDetector.setColliderFilter(filter);
+ }
+ },
+
+ /**
+ * Returns collider filter of ccs.Bone.
+ * @returns {cc.ColliderFilter}
+ */
+ getColliderFilter: function () {
+ var decoDisplay = this.displayManager.getCurrentDecorativeDisplay();
+ if (decoDisplay) {
+ var detector = decoDisplay.getColliderDetector();
+ if (detector)
+ return detector.getColliderFilter();
+ }
+ return null;
+ },
+
+ /**
+ * Sets ccs.Bone's transform dirty flag.
+ * @param {Boolean} dirty
+ */
+ setTransformDirty: function (dirty) {
+ this._boneTransformDirty = dirty;
+ },
+
+ /**
+ * Returns ccs.Bone's transform dirty flag whether is dirty.
+ * @return {Boolean}
+ */
+ isTransformDirty: function () {
+ return this._boneTransformDirty;
+ },
+
+ /**
+ * displayManager dirty getter
+ * @return {ccs.DisplayManager}
+ */
+ getDisplayManager: function () {
+ return this._displayManager;
+ },
+
+ /**
+ * When CCArmature play a animation, if there is not a CCMovementBoneData of this bone in this CCMovementData, this bone will hide.
+ * Set IgnoreMovementBoneData to true, then this bone will also show.
+ * @param {Boolean} bool
+ */
+ setIgnoreMovementBoneData: function (bool) {
+ this._ignoreMovementBoneData = bool;
+ },
+
+ /**
+ * Returns whether is ignore movement bone data.
+ * @returns {Boolean}
+ */
+ isIgnoreMovementBoneData: function () {
+ return this._ignoreMovementBoneData;
+ },
+
+ /**
+ * Returns the blendFunc of ccs.Bone.
+ * @return {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
+ },
+
+ /**
+ * Sets blend dirty flag
+ * @param {Boolean} dirty
+ */
+ setBlendDirty: function (dirty) {
+ this._blendDirty = dirty;
+ },
+
+ /**
+ * Returns the blend dirty flag whether is dirty.
+ * @returns {Boolean|*|ccs.Bone._blendDirty}
+ */
+ isBlendDirty: function () {
+ return this._blendDirty;
+ },
+
+ /**
+ * Returns the tweenData of ccs.Bone.
+ * @return {ccs.FrameData}
+ */
+ getTweenData: function () {
+ return this._tweenData;
+ },
+
+ /**
+ * Returns the world information of ccs.Bone.
+ * @returns {ccs.BaseData}
+ */
+ getWorldInfo: function () {
+ return this._worldInfo;
+ },
+
+ /**
+ * Returns the children of ccs.Bone
+ * @return {Array}
+ * @deprecated since v3.0, please use getChildren instead.
+ */
+ getChildrenBone: function () {
+ return this._children;
+ },
+
+ /**
+ * Returns the worldTransform of ccs.Bone.
+ * @return {cc.AffineTransform}
+ * @deprecated since v3.0, please use getNodeToArmatureTransform instead.
+ */
+ nodeToArmatureTransform: function () {
+ return this.getNodeToArmatureTransform();
+ },
+
+ /**
+ * @deprecated
+ * Returns the world affine transform matrix. The matrix is in Pixels.
+ * @returns {cc.AffineTransform}
+ */
+ nodeToWorldTransform: function () {
+ return this.getNodeToWorldTransform();
+ },
+
+ /**
+ * Returns the collider body list in this bone.
+ * @returns {Array|null}
+ * @deprecated since v3.0, please use getColliderDetector to get a delector, and calls its getColliderBodyList instead.
+ */
+ getColliderBodyList: function () {
+ var detector = this.getColliderDetector();
+ if (detector)
+ return detector.getColliderBodyList();
+ return null;
+ },
+
+ /**
+ * Returns whether is ignore movement bone data.
+ * @return {Boolean}
+ * @deprecated since v3.0, please isIgnoreMovementBoneData instead.
+ */
+ getIgnoreMovementBoneData: function () {
+ return this.isIgnoreMovementBoneData();
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new ccs.Bone.CanvasRenderCmd(this);
+ else
+ return new ccs.Bone.WebGLRenderCmd(this);
+ }
+});
+
+var _p = ccs.Bone.prototype;
+
+// Extended properties
+/** @expose */
+_p.boneData;
+cc.defineGetterSetter(_p, "boneData", _p.getBoneData, _p.setBoneData);
+/** @expose */
+_p.armature;
+cc.defineGetterSetter(_p, "armature", _p.getArmature, _p.setArmature);
+/** @expose */
+_p.childArmature;
+cc.defineGetterSetter(_p, "childArmature", _p.getChildArmature, _p.setChildArmature);
+/** @expose */
+_p.childrenBone;
+cc.defineGetterSetter(_p, "childrenBone", _p.getChildrenBone);
+/** @expose */
+_p.tween;
+cc.defineGetterSetter(_p, "tween", _p.getTween);
+/** @expose */
+_p.tweenData;
+cc.defineGetterSetter(_p, "tweenData", _p.getTweenData);
+/** @expose */
+_p.colliderFilter;
+cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter);
+
+_p = null;
+
+/**
+ * Allocates and initializes a bone.
+ * @return {ccs.Bone}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.Bone.create = function (name) {
+ return new ccs.Bone(name);
+};
+
+ccs.Bone.RenderCmd = {
+ _updateColor: function () {
+ var node = this._node;
+ var display = node._displayManager.getDisplayRenderNode();
+ if (display !== null) {
+ var displayCmd = display._renderCmd;
+ display.setColor(this._displayedColor);
+ display.setOpacity(this._displayedOpacity);
+ displayCmd._syncDisplayColor(node._tweenData);
+ displayCmd._syncDisplayOpacity(node._tweenData.a);
+ displayCmd._updateColor();
+ }
+ },
+
+ transform: function (parentCmd, recursive) {
+ if (!this._transform) {
+ this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ }
+
+ var node = this._node,
+ t = this._transform,
+ wt = this._worldTransform,
+ pt = parentCmd ? parentCmd._worldTransform : null;
+
+ if (pt) {
+ this.originTransform();
+ cc.affineTransformConcatIn(t, node._worldTransform);
+ }
+
+ if (pt) {
+ wt.a = t.a * pt.a + t.b * pt.c;
+ wt.b = t.a * pt.b + t.b * pt.d;
+ wt.c = t.c * pt.a + t.d * pt.c;
+ wt.d = t.c * pt.b + t.d * pt.d;
+ wt.tx = t.tx * pt.a + t.ty * pt.c + pt.tx;
+ wt.ty = t.tx * pt.b + t.ty * pt.d + pt.ty;
+ }
+ else {
+ wt.a = t.a;
+ wt.b = t.b;
+ wt.c = t.c;
+ wt.d = t.d;
+ wt.tx = t.tx;
+ wt.ty = t.ty;
+ }
+ }
+};
+
+(function () {
+ ccs.Bone.CanvasRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = false;
+ };
+
+ var proto = ccs.Bone.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+ cc.inject(ccs.Bone.RenderCmd, proto);
+ proto.constructor = ccs.Bone.CanvasRenderCmd;
+})();
+
+(function () {
+ if (!cc.Node.WebGLRenderCmd)
+ return;
+ ccs.Bone.WebGLRenderCmd = function (renderable) {
+ this._rootCtor(renderable);
+ this._needDraw = false;
+ };
+
+ var proto = ccs.Bone.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ cc.inject(ccs.Bone.RenderCmd, proto);
+ proto.constructor = ccs.Bone.WebGLRenderCmd;
+})();
diff --git a/extensions/cocostudio/armature/animation/CCArmatureAnimation.js b/extensions/cocostudio/armature/animation/CCArmatureAnimation.js
new file mode 100644
index 0000000000..09ab2fe7b0
--- /dev/null
+++ b/extensions/cocostudio/armature/animation/CCArmatureAnimation.js
@@ -0,0 +1,672 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * movement event type enum
+ * @constant
+ * @type {Object}
+ */
+ccs.MovementEventType = {
+ start: 0,
+ complete: 1,
+ loopComplete: 2
+};
+
+/**
+ * The animation event class, it has the callback, target and arguments.
+ * @deprecated since v3.0.
+ * @class
+ * @extends ccs.Class
+ */
+ccs.AnimationEvent = ccs.Class.extend(/** @lends ccs.AnimationEvent# */{
+ _arguments: null,
+ _callFunc: null,
+ _selectorTarget: null,
+
+ /**
+ * Constructor of ccs.AnimationEvent
+ * @param {function} callFunc
+ * @param {object} target
+ * @param {object} [data]
+ */
+ ctor: function (callFunc,target, data) {
+ this._data = data;
+ this._callFunc = callFunc;
+ this._selectorTarget = target;
+ },
+ call: function () {
+ if (this._callFunc)
+ this._callFunc.apply(this._selectorTarget, this._arguments);
+ },
+ setArguments: function (args) {
+ this._arguments = args;
+ }
+});
+
+/**
+ * The movement event class for Armature.
+ * @constructor
+ *
+ * @property {ccs.Armature} armature - The armature reference of movement event.
+ * @property {Number} movementType - The type of movement.
+ * @property {String} movementID - The ID of movement.
+ */
+ccs.MovementEvent = function () {
+ this.armature = null;
+ this.movementType = ccs.MovementEventType.start;
+ this.movementID = "";
+};
+
+/**
+ * The frame event class for Armature.
+ * @constructor
+ *
+ * @property {ccs.Bone} bone - The bone reference of frame event.
+ * @property {String} frameEventName - The name of frame event.
+ * @property {Number} originFrameIndex - The index of origin frame.
+ * @property {Number} currentFrameIndex - The index of current frame.
+ */
+ccs.FrameEvent = function () {
+ this.bone = null;
+ this.frameEventName = "";
+ this.originFrameIndex = 0;
+ this.currentFrameIndex = 0;
+};
+
+/**
+ * The Animation class for Armature, it plays armature animation, and controls speed scale and manages animation frame.
+ * @class
+ * @extends ccs.ProcessBase
+ *
+ * @param {ccs.Armature} [armature] The armature
+ *
+ * @property {ccs.AnimationData} animationData - Animation data
+ * @property {Object} userObject - User custom object
+ * @property {Boolean} ignoreFrameEvent - Indicate whether the frame event is ignored
+ * @property {Number} speedScale - Animation play speed scale
+ * @property {Number} animationScale - Animation play speed scale
+ */
+ccs.ArmatureAnimation = ccs.ProcessBase.extend(/** @lends ccs.ArmatureAnimation# */{
+ _animationData: null,
+ _movementData: null,
+ _armature: null,
+ _movementID: "",
+ _toIndex: 0,
+ _tweenList: null,
+ _speedScale: 1,
+ _ignoreFrameEvent: false,
+ _frameEventQueue: null,
+ _movementEventQueue: null,
+ _movementList: null,
+ _onMovementList: false,
+ _movementListLoop: false,
+ _movementIndex: 0,
+ _movementListDurationTo: -1,
+
+ _movementEventCallFunc: null,
+ _frameEventCallFunc: null,
+ _movementEventTarget: null,
+ _frameEventTarget:null,
+ _movementEventListener: null,
+ _frameEventListener: null,
+
+ ctor: function (armature) {
+ ccs.ProcessBase.prototype.ctor.call(this);
+
+ this._tweenList = [];
+ this._movementList = [];
+ this._frameEventQueue = [];
+ this._movementEventQueue = [];
+ this._armature = null;
+
+ armature && ccs.ArmatureAnimation.prototype.init.call(this, armature);
+ },
+
+ /**
+ * Initializes with an armature object
+ * @param {ccs.Armature} armature
+ * @return {Boolean}
+ */
+ init: function (armature) {
+ this._armature = armature;
+ this._tweenList.length = 0;
+ return true;
+ },
+
+ /**
+ * Pauses armature animation.
+ */
+ pause: function () {
+ var locTweenList = this._tweenList;
+ for (var i = 0; i < locTweenList.length; i++)
+ locTweenList[i].pause();
+ ccs.ProcessBase.prototype.pause.call(this);
+ },
+
+ /**
+ * Resumes armature animation.
+ */
+ resume: function () {
+ var locTweenList = this._tweenList;
+ for (var i = 0; i < locTweenList.length; i++)
+ locTweenList[i].resume();
+ ccs.ProcessBase.prototype.resume.call(this);
+ },
+
+ /**
+ * Stops armature animation.
+ */
+ stop: function () {
+ var locTweenList = this._tweenList;
+ for (var i = 0; i < locTweenList.length; i++)
+ locTweenList[i].stop();
+ locTweenList.length = 0;
+ ccs.ProcessBase.prototype.stop.call(this);
+ },
+
+ /**
+ * Sets animation play speed scale.
+ * @deprecated since v3.0, please use setSpeedScale instead.
+ * @param {Number} animationScale
+ */
+ setAnimationScale: function (animationScale) {
+ this.setSpeedScale(animationScale);
+ },
+
+ /**
+ * Returns animation play speed scale.
+ * @deprecated since v3.0, please use getSpeedScale instead.
+ * @returns {Number}
+ */
+ getAnimationScale: function () {
+ return this.getSpeedScale();
+ },
+
+ /**
+ * Sets animation play speed scale.
+ * @param {Number} speedScale
+ */
+ setSpeedScale: function (speedScale) {
+ if (speedScale === this._speedScale)
+ return;
+ this._speedScale = speedScale;
+ this._processScale = !this._movementData ? this._speedScale : this._speedScale * this._movementData.scale;
+ var dict = this._armature.getBoneDic();
+ for (var key in dict) {
+ var bone = dict[key];
+ bone.getTween().setProcessScale(this._processScale);
+ if (bone.getChildArmature())
+ bone.getChildArmature().getAnimation().setSpeedScale(this._processScale);
+ }
+ },
+
+ /**
+ * Returns animation play speed scale.
+ * @returns {Number}
+ */
+ getSpeedScale: function () {
+ return this._speedScale;
+ },
+
+ /**
+ * play animation by animation name.
+ * @param {String} animationName The animation name you want to play
+ * @param {Number} [durationTo=-1]
+ * the frames between two animation changing-over.It's meaning is changing to this animation need how many frames
+ * -1 : use the value from CCMovementData get from flash design panel
+ * @param {Number} [loop=-1]
+ * Whether the animation is loop.
+ * loop < 0 : use the value from CCMovementData get from flash design panel
+ * loop = 0 : this animation is not loop
+ * loop > 0 : this animation is loop
+ * @example
+ * // example
+ * armature.getAnimation().play("run",-1,1);//loop play
+ * armature.getAnimation().play("run",-1,0);//not loop play
+ */
+ play: function (animationName, durationTo, loop) {
+ cc.assert(this._animationData, "this.animationData can not be null");
+
+ this._movementData = this._animationData.getMovement(animationName);
+ cc.assert(this._movementData, "this._movementData can not be null");
+
+ durationTo = (durationTo === undefined) ? -1 : durationTo;
+ loop = (loop === undefined) ? -1 : loop;
+
+ //! Get key frame count
+ this._rawDuration = this._movementData.duration;
+ this._movementID = animationName;
+ this._processScale = this._speedScale * this._movementData.scale;
+
+ //! Further processing parameters
+ durationTo = (durationTo === -1) ? this._movementData.durationTo : durationTo;
+ var durationTween = this._movementData.durationTween === 0 ? this._rawDuration : this._movementData.durationTween;
+
+ var tweenEasing = this._movementData.tweenEasing;
+ //loop = (!loop || loop < 0) ? this._movementData.loop : loop;
+ loop = (loop < 0) ? this._movementData.loop : loop;
+ this._onMovementList = false;
+
+ ccs.ProcessBase.prototype.play.call(this, durationTo, durationTween, loop, tweenEasing);
+
+ if (this._rawDuration === 0)
+ this._loopType = ccs.ANIMATION_TYPE_SINGLE_FRAME;
+ else {
+ this._loopType = loop ? ccs.ANIMATION_TYPE_TO_LOOP_FRONT : ccs.ANIMATION_TYPE_NO_LOOP;
+ this._durationTween = durationTween;
+ }
+
+ this._tweenList.length = 0;
+
+ var movementBoneData, map = this._armature.getBoneDic();
+ for(var element in map) {
+ var bone = map[element];
+ movementBoneData = this._movementData.movBoneDataDic[bone.getName()];
+
+ var tween = bone.getTween();
+ if(movementBoneData && movementBoneData.frameList.length > 0) {
+ this._tweenList.push(tween);
+ movementBoneData.duration = this._movementData.duration;
+ tween.play(movementBoneData, durationTo, durationTween, loop, tweenEasing);
+ tween.setProcessScale(this._processScale);
+
+ if (bone.getChildArmature()) {
+ bone.getChildArmature().getAnimation().setSpeedScale(this._processScale);
+ if (!bone.getChildArmature().getAnimation().isPlaying())
+ bone.getChildArmature().getAnimation().playWithIndex(0);
+ }
+ } else {
+ if(!bone.isIgnoreMovementBoneData()){
+ //! this bone is not include in this movement, so hide it
+ bone.getDisplayManager().changeDisplayWithIndex(-1, false);
+ tween.stop();
+ }
+ }
+ }
+ this._armature.update(0);
+ },
+
+ /**
+ * Plays animation with index, the other param is the same to play.
+ * @param {Number} animationIndex
+ * @param {Number} durationTo
+ * @param {Number} durationTween
+ * @param {Number} loop
+ * @param {Number} [tweenEasing]
+ * @deprecated since v3.0, please use playWithIndex instead.
+ */
+ playByIndex: function (animationIndex, durationTo, durationTween, loop, tweenEasing) {
+ cc.log("playByIndex is deprecated. Use playWithIndex instead.");
+ this.playWithIndex(animationIndex, durationTo, loop);
+ },
+
+ /**
+ * Plays animation with index, the other param is the same to play.
+ * @param {Number|Array} animationIndex
+ * @param {Number} durationTo
+ * @param {Number} loop
+ */
+ playWithIndex: function (animationIndex, durationTo, loop) {
+ var movName = this._animationData.movementNames;
+ cc.assert((animationIndex > -1) && (animationIndex < movName.length));
+
+ var animationName = movName[animationIndex];
+ this.play(animationName, durationTo, loop);
+ },
+
+ /**
+ * Plays animation with names
+ * @param {Array} movementNames
+ * @param {Number} durationTo
+ * @param {Boolean} loop
+ */
+ playWithNames: function (movementNames, durationTo, loop) {
+ durationTo = (durationTo === undefined) ? -1 : durationTo;
+ loop = (loop === undefined) ? true : loop;
+
+ this._movementListLoop = loop;
+ this._movementListDurationTo = durationTo;
+ this._onMovementList = true;
+ this._movementIndex = 0;
+ if(movementNames instanceof Array)
+ this._movementList = movementNames;
+ else
+ this._movementList.length = 0;
+ this.updateMovementList();
+ },
+
+ /**
+ * Plays animation by indexes
+ * @param {Array} movementIndexes
+ * @param {Number} durationTo
+ * @param {Boolean} loop
+ */
+ playWithIndexes: function (movementIndexes, durationTo, loop) {
+ durationTo = (durationTo === undefined) ? -1 : durationTo;
+ loop = (loop === undefined) ? true : loop;
+
+ this._movementList.length = 0;
+ this._movementListLoop = loop;
+ this._movementListDurationTo = durationTo;
+ this._onMovementList = true;
+ this._movementIndex = 0;
+
+ var movName = this._animationData.movementNames;
+
+ for (var i = 0; i < movementIndexes.length; i++) {
+ var name = movName[movementIndexes[i]];
+ this._movementList.push(name);
+ }
+
+ this.updateMovementList();
+ },
+
+ /**
+ *
+ * Goes to specified frame and plays current movement.
+ * You need first switch to the movement you want to play, then call this function.
+ *
+ * example : playByIndex(0);
+ * gotoAndPlay(0);
+ * playByIndex(1);
+ * gotoAndPlay(0);
+ * gotoAndPlay(15);
+ *
+ * @param {Number} frameIndex
+ */
+ gotoAndPlay: function (frameIndex) {
+ if (!this._movementData || frameIndex < 0 || frameIndex >= this._movementData.duration) {
+ cc.log("Please ensure you have played a movement, and the frameIndex is in the range.");
+ return;
+ }
+
+ var ignoreFrameEvent = this._ignoreFrameEvent;
+ this._ignoreFrameEvent = true;
+ this._isPlaying = true;
+ this._isComplete = this._isPause = false;
+
+ ccs.ProcessBase.prototype.gotoFrame.call(this, frameIndex);
+ this._currentPercent = this._curFrameIndex / (this._movementData.duration - 1);
+ this._currentFrame = this._nextFrameIndex * this._currentPercent;
+
+ var locTweenList = this._tweenList;
+ for (var i = 0; i < locTweenList.length; i++)
+ locTweenList[i].gotoAndPlay(frameIndex);
+ this._armature.update(0);
+ this._ignoreFrameEvent = ignoreFrameEvent;
+ },
+
+ /**
+ * Goes to specified frame and pauses current movement.
+ * @param {Number} frameIndex
+ */
+ gotoAndPause: function (frameIndex) {
+ this.gotoAndPlay(frameIndex);
+ this.pause();
+ },
+
+ /**
+ * Returns the length of armature's movements
+ * @return {Number}
+ */
+ getMovementCount: function () {
+ return this._animationData.getMovementCount();
+ },
+
+ /**
+ * Updates the state of ccs.Tween list, calls frame event's callback and calls movement event's callback.
+ * @param {Number} dt
+ */
+ update: function (dt) {
+ ccs.ProcessBase.prototype.update.call(this, dt);
+
+ var locTweenList = this._tweenList;
+ for (var i = 0; i < locTweenList.length; i++)
+ locTweenList[i].update(dt);
+
+ var frameEvents = this._frameEventQueue, event;
+ while (frameEvents.length > 0) {
+ event = frameEvents.shift();
+ this._ignoreFrameEvent = true;
+ if(this._frameEventCallFunc)
+ this._frameEventCallFunc.call(this._frameEventTarget, event.bone, event.frameEventName, event.originFrameIndex, event.currentFrameIndex);
+ if(this._frameEventListener)
+ this._frameEventListener(event.bone, event.frameEventName, event.originFrameIndex, event.currentFrameIndex);
+ this._ignoreFrameEvent = false;
+ }
+
+ var movementEvents = this._movementEventQueue;
+ while (movementEvents.length > 0) {
+ event = movementEvents.shift();
+ if(this._movementEventCallFunc)
+ this._movementEventCallFunc.call(this._movementEventTarget, event.armature, event.movementType, event.movementID);
+ if (this._movementEventListener)
+ this._movementEventListener(event.armature, event.movementType, event.movementID);
+ }
+ },
+
+ /**
+ * Updates will call this handler, you can handle your logic here
+ */
+ updateHandler: function () { //TODO set it to protected in v3.1
+ var locCurrentPercent = this._currentPercent;
+ if (locCurrentPercent >= 1) {
+ switch (this._loopType) {
+ case ccs.ANIMATION_TYPE_NO_LOOP:
+ this._loopType = ccs.ANIMATION_TYPE_MAX;
+ this._currentFrame = (locCurrentPercent - 1) * this._nextFrameIndex;
+ locCurrentPercent = this._currentFrame / this._durationTween;
+ if (locCurrentPercent < 1.0) {
+ this._nextFrameIndex = this._durationTween;
+ this.movementEvent(this._armature, ccs.MovementEventType.start, this._movementID);
+ break;
+ }
+ break;
+ case ccs.ANIMATION_TYPE_MAX:
+ case ccs.ANIMATION_TYPE_SINGLE_FRAME:
+ locCurrentPercent = 1;
+ this._isComplete = true;
+ this._isPlaying = false;
+
+ this.movementEvent(this._armature, ccs.MovementEventType.complete, this._movementID);
+
+ this.updateMovementList();
+ break;
+ case ccs.ANIMATION_TYPE_TO_LOOP_FRONT:
+ this._loopType = ccs.ANIMATION_TYPE_LOOP_FRONT;
+ locCurrentPercent = ccs.fmodf(locCurrentPercent, 1);
+ this._currentFrame = this._nextFrameIndex === 0 ? 0 : ccs.fmodf(this._currentFrame, this._nextFrameIndex);
+ this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1;
+ this.movementEvent(this, ccs.MovementEventType.start, this._movementID);
+ break;
+ default:
+ //locCurrentPercent = ccs.fmodf(locCurrentPercent, 1);
+ this._currentFrame = ccs.fmodf(this._currentFrame, this._nextFrameIndex);
+ this._toIndex = 0;
+ this.movementEvent(this._armature, ccs.MovementEventType.loopComplete, this._movementID);
+ break;
+ }
+ this._currentPercent = locCurrentPercent;
+ }
+ },
+
+ /**
+ * Returns the Id of current movement
+ * @returns {String}
+ */
+ getCurrentMovementID: function () {
+ if (this._isComplete)
+ return "";
+ return this._movementID;
+ },
+
+ /**
+ * Sets movement event callback to animation.
+ * @param {function} callFunc
+ * @param {Object} target
+ */
+ setMovementEventCallFunc: function (callFunc, target) {
+ if(arguments.length === 1){
+ this._movementEventListener = callFunc;
+ }else if(arguments.length === 2){
+ this._movementEventTarget = target;
+ this._movementEventCallFunc = callFunc;
+ }
+ },
+
+ /**
+ * Sets frame event callback to animation.
+ * @param {function} callFunc
+ * @param {Object} target
+ */
+ setFrameEventCallFunc: function (callFunc, target) {
+ if(arguments.length === 1){
+ this._frameEventListener = callFunc;
+ }else if(arguments.length === 2){
+ this._frameEventTarget = target;
+ this._frameEventCallFunc = callFunc;
+ }
+ },
+
+ /**
+ * Sets user object to animation.
+ * @param {Object} userObject
+ */
+ setUserObject: function (userObject) {
+ this._userObject = userObject;
+ },
+
+ /**
+ * Emits a frame event
+ * @param {ccs.Bone} bone
+ * @param {String} frameEventName
+ * @param {Number} originFrameIndex
+ * @param {Number} currentFrameIndex
+ */
+ frameEvent: function (bone, frameEventName, originFrameIndex, currentFrameIndex) {
+ if ((this._frameEventTarget && this._frameEventCallFunc) || this._frameEventListener) {
+ var frameEvent = new ccs.FrameEvent();
+ frameEvent.bone = bone;
+ frameEvent.frameEventName = frameEventName;
+ frameEvent.originFrameIndex = originFrameIndex;
+ frameEvent.currentFrameIndex = currentFrameIndex;
+ this._frameEventQueue.push(frameEvent);
+ }
+ },
+
+ /**
+ * Emits a movement event
+ * @param {ccs.Armature} armature
+ * @param {Number} movementType
+ * @param {String} movementID
+ */
+ movementEvent: function (armature, movementType, movementID) {
+ if ((this._movementEventTarget && this._movementEventCallFunc) || this._movementEventListener) {
+ var event = new ccs.MovementEvent();
+ event.armature = armature;
+ event.movementType = movementType;
+ event.movementID = movementID;
+ this._movementEventQueue.push(event);
+ }
+ },
+
+ /**
+ * Updates movement list.
+ */
+ updateMovementList: function () {
+ if (this._onMovementList) {
+ var movementObj, locMovementList = this._movementList;
+ if (this._movementListLoop) {
+ movementObj = locMovementList[this._movementIndex];
+ this.play(movementObj, movementObj.durationTo, 0);
+ this._movementIndex++;
+ if (this._movementIndex >= locMovementList.length)
+ this._movementIndex = 0;
+ } else {
+ if (this._movementIndex < locMovementList.length) {
+ movementObj = locMovementList[this._movementIndex];
+ this.play(movementObj, movementObj.durationTo, 0);
+ this._movementIndex++;
+ } else
+ this._onMovementList = false;
+ }
+ this._onMovementList = true;
+ }
+ },
+
+ /**
+ * Sets animation data to animation.
+ * @param {ccs.AnimationData} data
+ */
+ setAnimationData: function (data) {
+ if(this._animationData !== data)
+ this._animationData = data;
+ },
+
+ /**
+ * Returns animation data of animation.
+ * @return {ccs.AnimationData}
+ */
+ getAnimationData: function () {
+ return this._animationData;
+ },
+
+ /**
+ * Returns the user object of animation.
+ * @return {Object}
+ */
+ getUserObject: function () {
+ return this._userObject;
+ },
+
+ /**
+ * Determines if the frame event is ignored
+ * @returns {boolean}
+ */
+ isIgnoreFrameEvent: function () {
+ return this._ignoreFrameEvent;
+ }
+});
+
+var _p = ccs.ArmatureAnimation.prototype;
+
+// Extended properties
+/** @expose */
+_p.speedScale;
+cc.defineGetterSetter(_p, "speedScale", _p.getSpeedScale, _p.setSpeedScale);
+/** @expose */
+_p.animationScale;
+cc.defineGetterSetter(_p, "animationScale", _p.getAnimationScale, _p.setAnimationScale);
+
+_p = null;
+
+/**
+ * Allocates and initializes a ArmatureAnimation.
+ * @return {ccs.ArmatureAnimation}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.ArmatureAnimation.create = function (armature) {
+ return new ccs.ArmatureAnimation(armature);
+};
diff --git a/extensions/cocostudio/armature/animation/CCProcessBase.js b/extensions/cocostudio/armature/animation/CCProcessBase.js
new file mode 100644
index 0000000000..a4707d3854
--- /dev/null
+++ b/extensions/cocostudio/armature/animation/CCProcessBase.js
@@ -0,0 +1,365 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//animation type
+/**
+ * The animation just have one frame
+ * @constant
+ * @type {number}
+ */
+ccs.ANIMATION_TYPE_SINGLE_FRAME = -4;
+/**
+ * The animation isn't loop
+ * @constant
+ * @type {number}
+ */
+ccs.ANIMATION_TYPE_NO_LOOP = -3;
+/**
+ * The animation to loop from front
+ * @constant
+ * @type {number}
+ */
+ccs.ANIMATION_TYPE_TO_LOOP_FRONT = -2;
+/**
+ * The animation to loop from back
+ * @constant
+ * @type {number}
+ */
+ccs.ANIMATION_TYPE_TO_LOOP_BACK = -1;
+/**
+ * The animation loop from front
+ * @constant
+ * @type {number}
+ */
+ccs.ANIMATION_TYPE_LOOP_FRONT = 0;
+/**
+ * The animation loop from back
+ * @constant
+ * @type {number}
+ */
+ccs.ANIMATION_TYPE_LOOP_BACK = 1;
+/**
+ * The animation max
+ * @constant
+ * @type {number}
+ */
+ccs.ANIMATION_TYPE_MAX = 2;
+
+/**
+ * The Base Process class for Cocostudio.
+ * @class
+ * @extends ccs.Class
+ *
+ * @property {Number} currentFrameIndex - <@readonly> The current frame's index
+ * @property {Boolean} paused - <@readonly> Indicate whether the process is paused
+ * @property {Boolean} completed - <@readonly> Indicate whether the process is done
+ * @property {Number} currentPercent - <@readonly> The current percentage of the process
+ * @property {Number} rawDuration - <@readonly> The duration
+ * @property {Number} loop - <@readonly> The number of loop
+ * @property {Number} tweenEasing - <@readonly> The tween easing
+ * @property {Number} animationInterval - The animation internal
+ * @property {Number} processScale - The process scale
+ * @property {Boolean} playing - <@readonly> Indicate whether the process is playing
+ */
+ccs.ProcessBase = ccs.Class.extend(/** @lends ccs.ProcessBase# */{
+ _processScale: 1,
+ _isComplete: true,
+ _isPause: true,
+ _isPlaying: false,
+ _currentPercent: 0.0,
+ _rawDuration: 0,
+ _loopType: 0,
+ _tweenEasing: 0,
+ animationInternal: null,
+ _currentFrame: 0,
+ _durationTween: 0,
+ _nextFrameIndex: 0,
+ _curFrameIndex: null,
+ _isLoopBack: false,
+
+ /**
+ * Constructor of ccs.ProcessBase
+ */
+ ctor: function () {
+ this._processScale = 1;
+ this._isComplete = true;
+ this._isPause = true;
+ this._isPlaying = false;
+ this._currentFrame = 0;
+ this._currentPercent = 0.0;
+ this._durationTween = 0;
+ this._rawDuration = 0;
+ this._loopType = ccs.ANIMATION_TYPE_LOOP_BACK;
+ this._tweenEasing = ccs.TweenType.LINEAR;
+ this.animationInternal = 1 / 60;
+ this._curFrameIndex = 0;
+ this._durationTween = 0;
+ this._isLoopBack = false;
+ },
+
+ /**
+ * Pauses the Process
+ */
+ pause: function () {
+ this._isPause = true;
+ this._isPlaying = false;
+ },
+
+ /**
+ * Resumes the Process
+ */
+ resume: function () {
+ this._isPause = false;
+ this._isPlaying = true;
+ },
+
+ /**
+ * Stops the Process
+ */
+ stop: function () {
+ this._isComplete = true;
+ this._isPlaying = false;
+ },
+
+ /**
+ * Plays animation by animation name.
+ * @param {Number} durationTo The frames between two animation changing-over.
+ * It's meaning is changing to this animation need how many frames
+ * -1 : use the value from MovementData get from flash design panel
+ * @param {Number} durationTween The frame count you want to play in the game.
+ * if _durationTween is 80, then the animation will played 80 frames in a loop
+ * -1 : use the value from MovementData get from flash design panel
+ * @param {Number} loop Whether the animation is loop
+ * loop < 0 : use the value from MovementData get from flash design panel
+ * loop = 0 : this animation is not loop
+ * loop > 0 : this animation is loop
+ * @param {Number} tweenEasing Tween easing is used for calculate easing effect
+ * TWEEN_EASING_MAX : use the value from MovementData get from flash design panel
+ * -1 : fade out
+ * 0 : line
+ * 1 : fade in
+ * 2 : fade in and out
+ */
+ play: function (durationTo, durationTween, loop, tweenEasing) {
+ this._isComplete = false;
+ this._isPause = false;
+ this._isPlaying = true;
+ this._currentFrame = 0;
+ /*
+ * Set m_iTotalFrames to durationTo, it is used for change tween between two animation.
+ * When changing end, m_iTotalFrames will be set to _durationTween
+ */
+ this._nextFrameIndex = durationTo;
+ this._tweenEasing = tweenEasing;
+ },
+
+ /**
+ * Update process' state.
+ * @param {Number} dt
+ */
+ update: function (dt) {
+ if (this._isComplete || this._isPause)
+ return;
+
+ /*
+ * Fileter the m_iDuration <=0 and dt >1
+ * If dt>1, generally speaking the reason is the device is stuck.
+ */
+ if (this._rawDuration <= 0 || dt > 1)
+ return;
+
+ var locNextFrameIndex = this._nextFrameIndex === undefined ? 0 : this._nextFrameIndex;
+ var locCurrentFrame = this._currentFrame;
+ if (locNextFrameIndex <= 0) {
+ this._currentPercent = 1;
+ locCurrentFrame = 0;
+ } else {
+ /*
+ * update currentFrame, every update add the frame passed.
+ * dt/this.animationInternal determine it is not a frame animation. If frame speed changed, it will not make our
+ * animation speed slower or quicker.
+ */
+ locCurrentFrame += this._processScale * (dt / this.animationInternal);
+ this._currentPercent = locCurrentFrame / locNextFrameIndex;
+
+ /*
+ * if currentFrame is bigger or equal than this._nextFrameIndex, then reduce it util currentFrame is
+ * smaller than this._nextFrameIndex
+ */
+ locCurrentFrame = ccs.fmodf(locCurrentFrame, locNextFrameIndex);
+ }
+ this._currentFrame = locCurrentFrame;
+ this.updateHandler();
+ },
+
+ /**
+ * Goes to specified frame by frameIndex.
+ * @param {Number} frameIndex
+ */
+ gotoFrame: function (frameIndex) {
+ var locLoopType = this._loopType;
+ if (locLoopType === ccs.ANIMATION_TYPE_NO_LOOP)
+ locLoopType = ccs.ANIMATION_TYPE_MAX;
+ else if (locLoopType === ccs.ANIMATION_TYPE_TO_LOOP_FRONT)
+ locLoopType = ccs.ANIMATION_TYPE_LOOP_FRONT;
+ this._loopType = locLoopType;
+ this._curFrameIndex = frameIndex;
+ this._nextFrameIndex = this._durationTween;
+ },
+
+ /**
+ * Returns the index of current frame.
+ * @return {Number}
+ */
+ getCurrentFrameIndex: function () {
+ this._curFrameIndex = (this._rawDuration - 1) * this._currentPercent;
+ return this._curFrameIndex;
+ },
+
+ /**
+ * Updates will call this handler, you can handle your logic here
+ */
+ updateHandler: function () {
+ //override
+ },
+
+ /**
+ * Returns whether the animation is pause
+ * @returns {boolean}
+ */
+ isPause: function () {
+ return this._isPause;
+ },
+
+ /**
+ * Returns whether the animation is complete
+ * @returns {boolean}
+ */
+ isComplete: function () {
+ return this._isComplete;
+ },
+
+ /**
+ * Returns current percent of ccs.ProcessBase
+ * @returns {number}
+ */
+ getCurrentPercent: function () {
+ return this._currentPercent;
+ },
+
+ /**
+ * Returns the raw duration of ccs.ProcessBase
+ * @returns {number}
+ */
+ getRawDuration: function () {
+ return this._rawDuration;
+ },
+
+ /**
+ * Returns loop type of ccs.ProcessBase
+ * @returns {number}
+ */
+ getLoop: function () {
+ return this._loopType;
+ },
+
+ /**
+ * Returns tween easing of ccs.ProcessBase
+ * @returns {number}
+ */
+ getTweenEasing: function () {
+ return this._tweenEasing;
+ },
+
+ /**
+ * Returns animation interval of ccs.ProcessBase
+ * @returns {number}
+ */
+ getAnimationInternal: function () { //TODO rename getAnimationInternal to getAnimationInterval in v3.1
+ return this.animationInternal;
+ },
+
+ /**
+ * Sets animation interval to ccs.ProcessBase.
+ * @param animationInternal
+ */
+ setAnimationInternal: function (animationInternal) {
+ this.animationInternal = animationInternal;
+ },
+
+ /**
+ * Returns process scale
+ * @returns {number}
+ */
+ getProcessScale: function () {
+ return this._processScale;
+ },
+
+ /**
+ * Sets process scale
+ * @param processScale
+ */
+ setProcessScale: function (processScale) {
+ this._processScale = processScale;
+ },
+
+ /**
+ * Returns whether the animation is playing
+ * @returns {boolean}
+ */
+ isPlaying: function () {
+ return this._isPlaying;
+ }
+});
+
+var _p = ccs.ProcessBase.prototype;
+
+// Extended properties
+/** @expose */
+_p.currentFrameIndex;
+cc.defineGetterSetter(_p, "currentFrameIndex", _p.getCurrentFrameIndex);
+/** @expose */
+_p.paused;
+cc.defineGetterSetter(_p, "paused", _p.isPause);
+/** @expose */
+_p.completed;
+cc.defineGetterSetter(_p, "completed", _p.isComplete);
+/** @expose */
+_p.currentPercent;
+cc.defineGetterSetter(_p, "currentPercent", _p.getCurrentPercent);
+/** @expose */
+_p.rawDuration;
+cc.defineGetterSetter(_p, "rawDuration", _p.getRawDuration);
+/** @expose */
+_p.loop;
+cc.defineGetterSetter(_p, "loop", _p.getLoop);
+/** @expose */
+_p.tweenEasing;
+cc.defineGetterSetter(_p, "tweenEasing", _p.getTweenEasing);
+/** @expose */
+_p.playing;
+cc.defineGetterSetter(_p, "playing", _p.isPlaying);
+
+_p = null;
diff --git a/extensions/CocoStudio/Armature/animation/CCTween.js b/extensions/cocostudio/armature/animation/CCTween.js
similarity index 54%
rename from extensions/CocoStudio/Armature/animation/CCTween.js
rename to extensions/cocostudio/armature/animation/CCTween.js
index 1a0ef754ca..5706d1d595 100644
--- a/extensions/CocoStudio/Armature/animation/CCTween.js
+++ b/extensions/cocostudio/armature/animation/CCTween.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -23,11 +24,15 @@
****************************************************************************/
/**
- * Base class for cc.Tween objects.
+ * The tween class for Armature.
* @class
- * @extends cc.ProcessBase
+ * @extends ccs.ProcessBase
+ *
+ * @param {ccs.Bone} The bone to be animated
+ *
+ * @property {ccs.ArmatureAnimation} animation - The animation
*/
-cc.Tween = cc.ProcessBase.extend({
+ccs.Tween = ccs.ProcessBase.extend(/** @lends ccs.Tween# */{
_tweenData:null,
_to:null,
_from:null,
@@ -40,104 +45,78 @@ cc.Tween = cc.ProcessBase.extend({
_toIndex:0,
_fromIndex:0,
_animation:null,
- ctor:function () {
- cc.ProcessBase.prototype.ctor.call(this);
- this._tweenData = null;
- this._to = null;
- this._from = null;
- this._between = null;
- this._bone = null;
- this._movementBoneData = null;
- this._frameTweenEasing = cc.TweenType.Linear;
- this._toIndex = 0;
- this._fromIndex = 0;
- this._animation = null;
+ _passLastFrame:false,
+
+ ctor:function (bone) {
+ ccs.ProcessBase.prototype.ctor.call(this);
+ this._frameTweenEasing = ccs.TweenType.LINEAR;
+
+ ccs.Tween.prototype.init.call(this, bone);
},
/**
- * init with a CCBone
- * @param {cc.Bone} bone
+ * initializes a ccs.Tween with a CCBone
+ * @param {ccs.Bone} bone
* @return {Boolean}
*/
init:function (bone) {
- this._from = new cc.FrameData();
- this._between = new cc.FrameData();
+ this._from = new ccs.FrameData();
+ this._between = new ccs.FrameData();
this._bone = bone;
this._tweenData = this._bone.getTweenData();
this._tweenData.displayIndex = -1;
- this._animation = this._bone.getArmature() != null ? this._bone.getArmature().getAnimation() : null;
+
+ this._animation = (this._bone !== null && this._bone.getArmature() !== null) ?
+ this._bone.getArmature().getAnimation() :
+ null;
return true;
},
/**
- * play animation by animation name.
- * @param {Number} animationName The animation name you want to play
+ * Plays the tween.
+ * @param {ccs.MovementBoneData} movementBoneData
* @param {Number} durationTo
- * he frames between two animation changing-over.It's meaning is changing to this animation need how many frames
- * -1 : use the value from CCMovementData get from flash design panel
- * @param {Number} durationTween he
- * frame count you want to play in the game.if _durationTween is 80, then the animation will played 80 frames in a loop
- * -1 : use the value from CCMovementData get from flash design panel
- * @param {Number} loop
- * Whether the animation is loop.
- * loop < 0 : use the value from CCMovementData get from flash design panel
- * loop = 0 : this animation is not loop
- * loop > 0 : this animation is loop
- * @param {Number} tweenEasing
- * CCTween easing is used for calculate easing effect
- * TWEEN_EASING_MAX : use the value from CCMovementData get from flash design panel
- * -1 : fade out
- * 0 : line
- * 1 : fade in
- * 2 : fade in and out
+ * @param {Number} durationTween
+ * @param {Boolean} loop
+ * @param {ccs.TweenType} tweenEasing
*/
play:function (movementBoneData, durationTo, durationTween, loop, tweenEasing) {
- cc.ProcessBase.prototype.play.call(this, null, durationTo, durationTween, loop, tweenEasing);
- this._loopType = loop;
+ ccs.ProcessBase.prototype.play.call(this, durationTo, durationTween, loop, tweenEasing);
+ this._loopType = (loop)?ccs.ANIMATION_TYPE_TO_LOOP_FRONT:ccs.ANIMATION_TYPE_NO_LOOP;
this._totalDuration = 0;
this._betweenDuration = 0;
this._fromIndex = this._toIndex = 0;
- var difMovement = movementBoneData != this._movementBoneData;
-
- this._movementBoneData = movementBoneData;
+ var difMovement = movementBoneData !== this._movementBoneData;
+ this.setMovementBoneData(movementBoneData);
this._rawDuration = this._movementBoneData.duration;
var nextKeyFrame = this._movementBoneData.getFrameData(0);
this._tweenData.displayIndex = nextKeyFrame.displayIndex;
- if (this._bone.getArmature().getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) {
- cc.TransformHelp.nodeSub(this._tweenData, this._bone.getBoneData());
+ if (this._bone.getArmature().getArmatureData().dataVersion >= ccs.CONST_VERSION_COMBINED) {
+ ccs.TransformHelp.nodeSub(this._tweenData, this._bone.getBoneData());
this._tweenData.scaleX += 1;
this._tweenData.scaleY += 1;
}
- if (this._rawDuration==0) {
- this._loopType = CC_ANIMATION_TYPE_SINGLE_FRAME;
- if (durationTo == 0) {
+ if (this._rawDuration === 0) {
+ this._loopType = ccs.ANIMATION_TYPE_SINGLE_FRAME;
+ if (durationTo === 0)
this.setBetween(nextKeyFrame, nextKeyFrame);
- } else {
+ else
this.setBetween(this._tweenData, nextKeyFrame);
- }
- this._frameTweenEasing = cc.TweenType.Linear;
+ this._frameTweenEasing = ccs.TweenType.LINEAR;
}
else if (this._movementBoneData.frameList.length > 1) {
- if (loop) {
- this._loopType = CC_ANIMATION_TYPE_TO_LOOP_BACK;
- }
- else {
- this._loopType = CC_ANIMATION_TYPE_NO_LOOP;
- }
-
this._durationTween = durationTween * this._movementBoneData.scale;
- if (loop && this._movementBoneData.delay != 0) {
+ if (loop && this._movementBoneData.delay !== 0)
this.setBetween(this._tweenData, this.tweenNodeTo(this.updateFrameData(1 - this._movementBoneData.delay), this._between));
- }
else {
- if (!difMovement || durationTo == 0)
+ if (!difMovement || durationTo === 0)
this.setBetween(nextKeyFrame, nextKeyFrame);
else
this.setBetween(this._tweenData, nextKeyFrame);
@@ -146,32 +125,58 @@ cc.Tween = cc.ProcessBase.extend({
this.tweenNodeTo(0);
},
+ /**
+ * Goes to specified frame and plays frame.
+ * @param {Number} frameIndex
+ */
+ gotoAndPlay: function (frameIndex) {
+ ccs.ProcessBase.prototype.gotoFrame.call(this, frameIndex);
+
+ this._totalDuration = 0;
+ this._betweenDuration = 0;
+ this._fromIndex = this._toIndex = 0;
+
+ this._isPlaying = true;
+ this._isComplete = this._isPause = false;
+
+ this._currentPercent = this._curFrameIndex / (this._rawDuration-1);
+ this._currentFrame = this._nextFrameIndex * this._currentPercent;
+ },
+
+ /**
+ * Goes to specified frame and pauses frame.
+ * @param {Number} frameIndex
+ */
+ gotoAndPause: function (frameIndex) {
+ this.gotoAndPlay(frameIndex);
+ this.pause();
+ },
+
/**
* update will call this handler, you can handle your logic here
*/
updateHandler:function () {
- var locCurrentPercent = this._currentPercent;
+ var locCurrentPercent = this._currentPercent == null ? 1 : this._currentPercent;
var locLoopType = this._loopType;
if (locCurrentPercent >= 1) {
switch (locLoopType) {
- case CC_ANIMATION_TYPE_SINGLE_FRAME:
+ case ccs.ANIMATION_TYPE_SINGLE_FRAME:
locCurrentPercent = 1;
this._isComplete = true;
+ this._isPlaying = false;
break;
- case CC_ANIMATION_TYPE_NO_LOOP:
- locLoopType = CC_ANIMATION_TYPE_MAX;
- if (this._durationTween <= 0) {
+ case ccs.ANIMATION_TYPE_NO_LOOP:
+ locLoopType = ccs.ANIMATION_TYPE_MAX;
+ if (this._durationTween <= 0)
locCurrentPercent = 1;
- }
- else {
+ else
locCurrentPercent = (locCurrentPercent - 1) * this._nextFrameIndex / this._durationTween;
- }
if (locCurrentPercent >= 1) {
locCurrentPercent = 1;
this._isComplete = true;
+ this._isPlaying = false;
break;
- }
- else {
+ } else {
this._nextFrameIndex = this._durationTween;
this._currentFrame = locCurrentPercent * this._nextFrameIndex;
this._totalDuration = 0;
@@ -179,13 +184,13 @@ cc.Tween = cc.ProcessBase.extend({
this._fromIndex = this._toIndex = 0;
break;
}
- case CC_ANIMATION_TYPE_TO_LOOP_BACK:
- locLoopType = CC_ANIMATION_TYPE_LOOP_BACK;
+ case ccs.ANIMATION_TYPE_TO_LOOP_FRONT:
+ locLoopType = ccs.ANIMATION_TYPE_LOOP_FRONT;
this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1;
- if (this._movementBoneData.delay != 0) {
+
+ if (this._movementBoneData.delay !== 0) {
this._currentFrame = (1 - this._movementBoneData.delay) * this._nextFrameIndex;
locCurrentPercent = this._currentFrame / this._nextFrameIndex;
-
} else {
locCurrentPercent = 0;
this._currentFrame = 0;
@@ -195,81 +200,85 @@ cc.Tween = cc.ProcessBase.extend({
this._betweenDuration = 0;
this._fromIndex = this._toIndex = 0;
break;
- case CC_ANIMATION_TYPE_MAX:
+ case ccs.ANIMATION_TYPE_MAX:
locCurrentPercent = 1;
this._isComplete = true;
+ this._isPlaying = false;
break;
default:
- locCurrentPercent = cc.fmodf(locCurrentPercent, 1);
- this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex);
- this._totalDuration = 0;
- this._betweenDuration = 0;
- this._fromIndex = this._toIndex = 0;
+ this._currentFrame = ccs.fmodf(this._currentFrame, this._nextFrameIndex);
break;
}
}
- if (locCurrentPercent < 1 && locLoopType < CC_ANIMATION_TYPE_TO_LOOP_BACK) {
+ if (locCurrentPercent < 1 && locLoopType < ccs.ANIMATION_TYPE_TO_LOOP_BACK)
locCurrentPercent = Math.sin(locCurrentPercent * cc.PI / 2);
- }
this._currentPercent = locCurrentPercent;
this._loopType = locLoopType;
- if (locLoopType > CC_ANIMATION_TYPE_TO_LOOP_BACK) {
- locCurrentPercent = this.updateFrameData(locCurrentPercent, true);
- }
- if (this._frameTweenEasing != cc.TweenType.TWEEN_EASING_MAX) {
+ if (locLoopType > ccs.ANIMATION_TYPE_TO_LOOP_BACK)
+ locCurrentPercent = this.updateFrameData(locCurrentPercent);
+ if (this._frameTweenEasing !== ccs.TweenType.TWEEN_EASING_MAX)
this.tweenNodeTo(locCurrentPercent);
- }
-
},
/**
* Calculate the between value of _from and _to, and give it to between frame data
- * @param {cc.FrameData} from
- * @param {cc.FrameData} to
+ * @param {ccs.FrameData} from
+ * @param {ccs.FrameData} to
+ * @param {Boolean} [limit=true]
*/
- setBetween:function (from, to) {
- do
- {
+ setBetween:function (from, to, limit) { //TODO set tweenColorTo to protected in v3.1
+ if(limit === undefined)
+ limit = true;
+ do {
if (from.displayIndex < 0 && to.displayIndex >= 0) {
this._from.copy(to);
- this._between.subtract(to, to);
+ this._between.subtract(to, to, limit);
break;
}
if (to.displayIndex < 0 && from.displayIndex >= 0) {
this._from.copy(from);
- this._between.subtract(to, to);
+ this._between.subtract(to, to, limit);
break;
}
this._from.copy(from);
- this._between.subtract(from, to);
+ this._between.subtract(from, to, limit);
} while (0);
+ if (!from.isTween){
+ this._tweenData.copy(from);
+ this._tweenData.isTween = true;
+ }
this.arriveKeyFrame(from);
},
/**
* Update display index and process the key frame event when arrived a key frame
- * @param {cc.FrameData} keyFrameData
+ * @param {ccs.FrameData} keyFrameData
*/
- arriveKeyFrame:function (keyFrameData) {
+ arriveKeyFrame:function (keyFrameData) { //TODO set tweenColorTo to protected in v3.1
if (keyFrameData) {
var locBone = this._bone;
- var displayIndex = keyFrameData.displayIndex;
var displayManager = locBone.getDisplayManager();
- if (!displayManager.getForceChangeDisplay()) {
- displayManager.changeDisplayByIndex(displayIndex, false);
- }
+ //! Change bone's display
+ var displayIndex = keyFrameData.displayIndex;
+
+ if (!displayManager.getForceChangeDisplay())
+ displayManager.changeDisplayWithIndex(displayIndex, false);
+
+ //! Update bone zorder, bone's zorder is determined by frame zorder and bone zorder
this._tweenData.zOrder = keyFrameData.zOrder;
locBone.updateZOrder();
- locBone.setBlendType(keyFrameData.blendType);
+
+ //! Update blend type
+ this._bone.setBlendFunc(keyFrameData.blendFunc);
+
var childAramture = locBone.getChildArmature();
if (childAramture) {
- if (keyFrameData.movement != "") {
+ if (keyFrameData.movement !== "")
childAramture.getAnimation().play(keyFrameData.movement);
- }
}
}
},
@@ -277,15 +286,17 @@ cc.Tween = cc.ProcessBase.extend({
/**
* According to the percent to calculate current CCFrameData with tween effect
* @param {Number} percent
- * @param {cc.FrameData} node
- * @return {cc.FrameData}
+ * @param {ccs.FrameData} [node]
+ * @return {ccs.FrameData}
*/
- tweenNodeTo:function (percent, node) {
- if (!node) {
+ tweenNodeTo:function (percent, node) { //TODO set tweenColorTo to protected in v3.1
+ if (!node)
node = this._tweenData;
- }
+
var locFrom = this._from;
var locBetween = this._between;
+ if (!locFrom.isTween)
+ percent = 0;
node.x = locFrom.x + percent * locBetween.x;
node.y = locFrom.y + percent * locBetween.y;
node.scaleX = locFrom.scaleX + percent * locBetween.scaleX;
@@ -300,7 +311,12 @@ cc.Tween = cc.ProcessBase.extend({
return node;
},
- tweenColorTo:function(percent,node){
+ /**
+ * According to the percent to calculate current color with tween effect
+ * @param {Number} percent
+ * @param {ccs.FrameData} node
+ */
+ tweenColorTo:function(percent,node){ //TODO set tweenColorTo to protected in v3.1
var locFrom = this._from;
var locBetween = this._between;
node.a = locFrom.a + percent * locBetween.a;
@@ -313,14 +329,14 @@ cc.Tween = cc.ProcessBase.extend({
/**
* Calculate which frame arrived, and if current frame have event, then call the event listener
* @param {Number} currentPercent
- * @param {Boolean} activeFrame
* @return {Number}
*/
- updateFrameData:function (currentPercent) {
- if (currentPercent > 1 && this._movementBoneData.delay != 0) {
- currentPercent = cc.fmodf(currentPercent,1);
- }
- var playedTime = this._rawDuration * currentPercent;
+ updateFrameData:function (currentPercent) { //TODO set tweenColorTo to protected in v3.1
+ if (currentPercent > 1 && this._movementBoneData.delay !== 0)
+ currentPercent = ccs.fmodf(currentPercent,1);
+
+ var playedTime = (this._rawDuration-1) * currentPercent;
+
var from, to;
var locTotalDuration = this._totalDuration,locBetweenDuration = this._betweenDuration, locToIndex = this._toIndex;
// if play to current frame's front or back, then find current frame again
@@ -329,98 +345,104 @@ cc.Tween = cc.ProcessBase.extend({
* get frame length, if this._toIndex >= _length, then set this._toIndex to 0, start anew.
* this._toIndex is next index will play
*/
- var length = this._movementBoneData.frameList.length;
var frames = this._movementBoneData.frameList;
+ var length = frames.length;
+
if (playedTime < frames[0].frameID){
from = to = frames[0];
this.setBetween(from, to);
- return currentPercent;
- }
- else if(playedTime >= frames[length - 1].frameID){
- from = to = frames[length - 1];
- this.setBetween(from, to);
- return currentPercent;
+ return this._currentPercent;
}
+ if (playedTime >= frames[length - 1].frameID) {
+ // If _passLastFrame is true and playedTime >= frames[length - 1]->frameID, then do not need to go on.
+ if (this._passLastFrame) {
+ from = to = frames[length - 1];
+ this.setBetween(from, to);
+ return this._currentPercent;
+ }
+ this._passLastFrame = true;
+ } else
+ this._passLastFrame = false;
+
do {
+ this._fromIndex = locToIndex;
from = frames[this._fromIndex];
locTotalDuration = from.frameID;
- if (++locToIndex >= length) {
+
+ locToIndex = this._fromIndex + 1;
+ if (locToIndex >= length)
locToIndex = 0;
- }
- this._fromIndex = locToIndex;
to = frames[locToIndex];
//! Guaranteed to trigger frame event
- if(from.event){
- this._animation.callFrameEvent([this._bone, from.event,from.frameID, playedTime]);
- }
+ if(from.strEvent && !this._animation.isIgnoreFrameEvent())
+ this._animation.frameEvent(this._bone, from.strEvent,from.frameID, playedTime);
- if (playedTime == from.frameID) {
+ if (playedTime === from.frameID|| (this._passLastFrame && this._fromIndex === length-1))
break;
- }
- }
- while (playedTime < from.frameID || playedTime >= to.frameID);
+ } while (playedTime < from.frameID || playedTime >= to.frameID);
locBetweenDuration = to.frameID - from.frameID;
this._frameTweenEasing = from.tweenEasing;
- this.setBetween(from, to);
+ this.setBetween(from, to, false);
+
this._totalDuration = locTotalDuration;
this._betweenDuration = locBetweenDuration;
this._toIndex = locToIndex;
}
-
- currentPercent = locBetweenDuration == 0 ? 0 : (playedTime - locTotalDuration) / locBetweenDuration;
+ currentPercent = locBetweenDuration === 0 ? 0 : (playedTime - this._totalDuration) / this._betweenDuration;
/*
* if frame tween easing equal to TWEEN_EASING_MAX, then it will not do tween.
*/
- var tweenType = null;
- var locTWEEN_EASING_MAX = cc.TweenType.TWEEN_EASING_MAX;
- if (this._frameTweenEasing != locTWEEN_EASING_MAX) {
- tweenType = (this._tweenEasing == locTWEEN_EASING_MAX) ? this._frameTweenEasing : this._tweenEasing;
- if (tweenType != locTWEEN_EASING_MAX&&tweenType != cc.TweenType.Linear) {
- currentPercent = cc.TweenFunction.tweenTo(0, 1, currentPercent, 1, tweenType);
- }
+ var tweenType = (this._frameTweenEasing !== ccs.TweenType.LINEAR) ? this._frameTweenEasing : this._tweenEasing;
+ if (tweenType !== ccs.TweenType.TWEEN_EASING_MAX && tweenType !== ccs.TweenType.LINEAR && !this._passLastFrame) {
+ currentPercent = ccs.TweenFunction.tweenTo(currentPercent, tweenType, this._from.easingParams);
}
return currentPercent;
},
/**
- * animation setter
- * @param {cc.ArmatureAnimation} animation
+ * Sets Armature animation to ccs.Tween.
+ * @param {ccs.ArmatureAnimation} animation
*/
setAnimation:function (animation) {
this._animation = animation;
},
/**
- * animation getter
- * @return {cc.ArmatureAnimation}
+ * Returns Armature animation of ccs.Tween.
+ * @return {ccs.ArmatureAnimation}
*/
getAnimation:function () {
return this._animation;
},
- release:function () {
- this._from = null;
- this._between = null;
+ /**
+ * Sets movement bone data to ccs.Tween.
+ * @param data
+ */
+ setMovementBoneData: function(data){
+ this._movementBoneData = data;
}
});
+var _p = ccs.Tween.prototype;
+
+// Extended properties
+/** @expose */
+_p.animation;
+cc.defineGetterSetter(_p, "animation", _p.getAnimation, _p.setAnimation);
+
+_p = null;
+
/**
- * allocates and initializes a ArmatureAnimation.
- * @constructs
- * @param {cc.Bone} bone
- * @return {cc.ArmatureAnimation}
- * @example
- * // example
- * var animation = cc.ArmatureAnimation.create();
+ * Allocates and initializes a ArmatureAnimation.
+ * @param {ccs.Bone} bone
+ * @return {ccs.Tween}
+ * @deprecated since v3.1, please use new construction instead
*/
-cc.Tween.create = function (bone) {
- var tween = new cc.Tween();
- if (tween && tween.init(bone)) {
- return tween;
- }
- return null;
+ccs.Tween.create = function (bone) {
+ return new ccs.Tween(bone);
};
diff --git a/extensions/cocostudio/armature/datas/CCDatas.js b/extensions/cocostudio/armature/datas/CCDatas.js
new file mode 100644
index 0000000000..6aa958b36a
--- /dev/null
+++ b/extensions/cocostudio/armature/datas/CCDatas.js
@@ -0,0 +1,807 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//BlendType
+/**
+ * The value of the blend type of normal
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_NORMAL = 0;
+
+/**
+ * The value of the blend type of layer
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_LAYER = 1;
+
+/**
+ * The value of the blend type of darken
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_DARKEN = 2;
+
+/**
+ * The value of the blend type of multiply
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_MULTIPLY = 3;
+
+/**
+ * The value of the blend type of lighten
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_LIGHTEN = 4;
+
+/**
+ * The value of the blend type of screen
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_SCREEN = 5;
+
+/**
+ * The value of the blend type of overlay
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_OVERLAY = 6;
+
+/**
+ * The value of the blend type of highlight
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_HIGHLIGHT = 7;
+
+/**
+ * The value of the blend type of add
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_ADD = 8;
+
+/**
+ * The value of the blend type of subtract
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_SUBTRACT = 9;
+
+/**
+ * The value of the blend type of difference
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_DIFFERENCE = 10;
+
+/**
+ * The value of the blend type of invert
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_INVERT = 11;
+
+/**
+ * The value of the blend type of alpha
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_ALPHA = 12;
+
+/**
+ * The value of the blend type of erase
+ * @constant
+ * @type Number
+ */
+ccs.BLEND_TYPE_ERASE = 13;
+
+//DisplayType
+/**
+ * The Sprite flag of display render type.
+ * @constant
+ * @type Number
+ */
+ccs.DISPLAY_TYPE_SPRITE = 0;
+/**
+ * The Armature flag of display render type.
+ * @constant
+ * @type Number
+ */
+ccs.DISPLAY_TYPE_ARMATURE = 1;
+/**
+ * The Particle flag of display render type.
+ * @constant
+ * @type Number
+ */
+ccs.DISPLAY_TYPE_PARTICLE = 2;
+ccs.DISPLAY_TYPE_MAX = 3;
+
+/**
+ *
+ * The base data class for Armature. it contains position, zOrder, skew, scale, color datas.
+ * x y skewX skewY scaleX scaleY used to calculate transform matrix
+ * skewX, skewY can have rotation effect
+ * To get more matrix information, you can have a look at this pape : http://www.senocular.com/flash/tutorials/transformmatrix/
+ *
+ * @class
+ * @extends ccs.Class
+ *
+ * @property {Number} x - x
+ * @property {Number} y - y
+ * @property {Number} zOrder - zOrder
+ * @property {Number} skewX - skewX
+ * @property {Number} skewY - skewY
+ * @property {Number} scaleX - scaleX
+ * @property {Number} scaleY - scaleY
+ * @property {Number} tweenRotate - tween Rotate
+ * @property {Number} isUseColorInfo - is Use Color Info
+ * @property {Number} r - r of color
+ * @property {Number} g - g of color
+ * @property {Number} b - b of color
+ * @property {Number} a - a of color
+ */
+ccs.BaseData = ccs.Class.extend(/** @lends ccs.BaseData# */{
+ x:0,
+ y:0,
+ zOrder:0,
+ skewX:0,
+ skewY:0,
+ scaleX:1,
+ scaleY:1,
+ tweenRotate:0, //! SkewX, SkewY, and TweenRotate effect the rotation
+ isUseColorInfo:false, //! Whether or not this frame have the color changed Info
+ r:255,
+ g:255,
+ b:255,
+ a:255,
+
+ /**
+ * Construction of ccs.BaseData
+ */
+ ctor:function () {
+ this.x = 0;
+ this.y = 0;
+ this.zOrder = 0;
+ this.skewX = 0;
+ this.skewY = 0;
+ this.scaleX = 1;
+ this.scaleY = 1;
+ this.tweenRotate = 0;
+ this.isUseColorInfo = false;
+ this.r = 255;
+ this.g = 255;
+ this.b = 255;
+ this.a = 255;
+ },
+
+ /**
+ * Copy data from node
+ * @function
+ * @param {ccs.BaseData} node
+ */
+ copy:function (node) {
+ this.x = node.x;
+ this.y = node.y;
+ this.zOrder = node.zOrder;
+
+ this.scaleX = node.scaleX;
+ this.scaleY = node.scaleY;
+ this.skewX = node.skewX;
+ this.skewY = node.skewY;
+
+ this.tweenRotate = node.tweenRotate;
+
+ this.isUseColorInfo = node.isUseColorInfo;
+ this.r = node.r;
+ this.g = node.g;
+ this.b = node.b;
+ this.a = node.a;
+ },
+
+ /**
+ * Sets color to base data.
+ * @function
+ * @param {cc.Color} color
+ */
+ setColor:function(color){
+ this.r = color.r;
+ this.g = color.g;
+ this.b = color.b;
+ this.a = color.a;
+ },
+
+ /**
+ * Returns the color of ccs.BaseData
+ * @function
+ * @returns {cc.Color}
+ */
+ getColor:function(){
+ return cc.color(this.r, this.g, this.b, this.a);
+ },
+
+ /**
+ * Calculate two baseData's between value(to - from) and set to self
+ * @function
+ * @param {ccs.BaseData} from
+ * @param {ccs.BaseData} to
+ * @param {Boolean} limit
+ */
+ subtract:function (from, to, limit) {
+ this.x = to.x - from.x;
+ this.y = to.y - from.y;
+ this.scaleX = to.scaleX - from.scaleX;
+ this.scaleY = to.scaleY - from.scaleY;
+ this.skewX = to.skewX - from.skewX;
+ this.skewY = to.skewY - from.skewY;
+
+ if (this.isUseColorInfo || from.isUseColorInfo || to.isUseColorInfo) {
+ this.a = to.a - from.a;
+ this.r = to.r - from.r;
+ this.g = to.g - from.g;
+ this.b = to.b - from.b;
+ this.isUseColorInfo = true;
+ } else {
+ this.a = this.r = this.g = this.b = 0;
+ this.isUseColorInfo = false;
+ }
+
+ if (limit) {
+ if (this.skewX > ccs.M_PI)
+ this.skewX -= ccs.DOUBLE_PI;
+ if (this.skewX < -ccs.M_PI)
+ this.skewX += ccs.DOUBLE_PI;
+ if (this.skewY > ccs.M_PI)
+ this.skewY -= ccs.DOUBLE_PI;
+ if (this.skewY < -ccs.M_PI)
+ this.skewY += ccs.DOUBLE_PI;
+ }
+
+ if (to.tweenRotate) {
+ this.skewX += to.tweenRotate * ccs.PI * 2;
+ this.skewY -= to.tweenRotate * ccs.PI * 2;
+ }
+ }
+});
+
+/**
+ * The class use for save display data.
+ * @class
+ * @extends ccs.Class
+ *
+ * @property {Number} displayType - the display type
+ * @property {String} displayName - the display name
+ */
+ccs.DisplayData = ccs.Class.extend(/** @lends ccs.DisplayData# */{
+ displayType: ccs.DISPLAY_TYPE_MAX,
+ displayName: "",
+
+ /**
+ * Construction of ccs.DisplayData
+ */
+ ctor: function () {
+ this.displayType = ccs.DISPLAY_TYPE_MAX;
+ },
+ /**
+ * Changes display name to texture type
+ * @function
+ * @param {String} displayName
+ * @returns {String}
+ */
+ changeDisplayToTexture:function (displayName) {
+ // remove .xxx
+ var textureName = displayName;
+ var startPos = textureName.lastIndexOf(".");
+
+ if (startPos !== -1)
+ textureName = textureName.substring(0, startPos);
+ return textureName;
+ },
+
+ /**
+ * copy data
+ * @function
+ * @param {ccs.DisplayData} displayData
+ */
+ copy:function (displayData) {
+ this.displayName = displayData.displayName;
+ this.displayType = displayData.displayType;
+ }
+});
+
+/**
+ * The sprite display data class.
+ * @class
+ * @extends ccs.DisplayData
+ *
+ * @property {ccs.BaseData} skinData - the skin data
+ */
+ccs.SpriteDisplayData = ccs.DisplayData.extend(/** @lends ccs.SpriteDisplayData# */{
+ skinData:null,
+
+ /**
+ * Construction of ccs.SpriteDisplayData
+ */
+ ctor:function () {
+ this.skinData = new ccs.BaseData();
+ this.displayType = ccs.DISPLAY_TYPE_SPRITE;
+ },
+ /**
+ * copy data
+ * @function
+ * @param {ccs.SpriteDisplayData} displayData
+ */
+ copy:function (displayData) {
+ ccs.DisplayData.prototype.copy.call(this,displayData);
+ this.skinData = displayData.skinData;
+ }
+});
+
+/**
+ * The armature display data class
+ * @class ccs.ArmatureDisplayData
+ * @extends ccs.DisplayData
+ */
+ccs.ArmatureDisplayData = ccs.DisplayData.extend(/** @lends ccs.ArmatureDisplayData# */{
+ /**
+ * Construction of ccs.ArmatureDisplayData
+ */
+ ctor:function () {
+ this.displayName = "";
+ this.displayType = ccs.DISPLAY_TYPE_ARMATURE;
+ }
+});
+
+/**
+ * The particle display data class.
+ * @class ccs.ParticleDisplayData
+ * @extends ccs.DisplayData
+ */
+ccs.ParticleDisplayData = ccs.DisplayData.extend(/** @lends ccs.ParticleDisplayData# */{
+ /**
+ * Construction of ccs.ParticleDisplayData
+ */
+ ctor:function () {
+ this.displayType = ccs.DISPLAY_TYPE_PARTICLE;
+ }
+});
+
+/**
+ *
+ * BoneData used to init a Bone.
+ * BoneData keeps a DisplayData list, a Bone can have many display to change.
+ * The display information saved in the DisplayData
+ *
+ * @class ccs.BoneData
+ * @extends ccs.BaseData
+ *
+ * @property {Array} displayDataList - the display data list
+ * @property {String} name - the name of Bone
+ * @property {String} parentName - the parent name of bone
+ * @property {cc.AffineTransform} boneDataTransform - the bone transform data
+ */
+ccs.BoneData = ccs.BaseData.extend(/** @lends ccs.BoneData# */{
+ displayDataList: null,
+ name: "",
+ parentName: "",
+ boneDataTransform: null,
+
+ /**
+ * Construction of ccs.BoneData
+ */
+ ctor: function () {
+ this.displayDataList = [];
+ this.name = "";
+ this.parentName = "";
+ this.boneDataTransform = null;
+ },
+
+ /**
+ * Initializes a ccs.BoneData
+ * @returns {boolean}
+ */
+ init: function () {
+ this.displayDataList.length = 0;
+ return true;
+ },
+ /**
+ * Adds display data to list
+ * @function
+ * @param {ccs.DisplayData} displayData
+ */
+ addDisplayData:function (displayData) {
+ this.displayDataList.push(displayData);
+ },
+
+ /**
+ * Returns display data with index.
+ * @function
+ * @param {Number} index
+ * @returns {ccs.DisplayData}
+ */
+ getDisplayData:function (index) {
+ return this.displayDataList[index];
+ }
+});
+
+/**
+ *
+ * ArmatureData saved the Armature name and BoneData needed for the CCBones in this Armature
+ * When we create a Armature, we need to get each Bone's BoneData as it's init information.
+ * So we can get a BoneData from the Dictionary saved in the ArmatureData.
+ *
+ * @class ccs.ArmatureData
+ * @extends ccs.Class
+ *
+ * @property {Object} boneDataDic - the bone data dictionary
+ * @property {String} name - the name of armature data
+ * @property {Number} dataVersion - the data version of armature data
+ */
+ccs.ArmatureData = ccs.Class.extend(/** @lends ccs.ArmatureData# */{
+ boneDataDic:null,
+ name:"",
+ dataVersion:0.1,
+
+ /**
+ * Construction of ccs.ArmatureData
+ */
+ ctor:function () {
+ this.boneDataDic = {};
+ this.name = "";
+ this.dataVersion = 0.1;
+ },
+
+ /**
+ * Initializes a ccs.ArmatureData
+ * @returns {boolean}
+ */
+ init:function () {
+ return true;
+ },
+
+ /**
+ * Adds bone data to dictionary
+ * @param {ccs.BoneData} boneData
+ */
+ addBoneData:function (boneData) {
+ this.boneDataDic[boneData.name] = boneData;
+ },
+
+ /**
+ * Gets bone data dictionary
+ * @returns {Object}
+ */
+ getBoneDataDic:function () {
+ return this.boneDataDic;
+ },
+ /**
+ * Gets bone data by bone name
+ * @function
+ * @param {String} boneName
+ * @returns {ccs.BoneData}
+ */
+ getBoneData:function (boneName) {
+ return this.boneDataDic[boneName];
+ }
+});
+
+/**
+ * FrameData saved the frame data needed for armature animation in this Armature.
+ * @class ccs.FrameData
+ * @extends ccs.BaseData
+ *
+ * @property {Number} duration - the duration of frame
+ * @property {Number} tweenEasing - the easing type of frame
+ * @property {Number} easingParamNumber - the count of easing parameters.
+ * @property {Object} easingParams - the dictionary of easing parameters.
+ * @property {Number} displayIndex - the display renderer index.
+ * @property {String} movement - the movement name.
+ * @property {String} event - the event name
+ * @property {String} sound - the sound path.
+ * @property {String} soundEffect - the sound effect path.
+ * @property {Object} blendFunc - the blendFunc of frame.
+ * @property {Number} frameID - the frame ID of frame
+ * @property {Boolean} isTween - the flag which frame whether is tween.
+ */
+ccs.FrameData = ccs.BaseData.extend(/** @lends ccs.FrameData# */{
+ duration:0,
+ tweenEasing:0,
+ easingParamNumber: 0,
+ easingParams: null,
+ displayIndex:-1,
+ movement:"",
+ event:"",
+ sound:"",
+ soundEffect:"",
+ blendFunc:null,
+ frameID:0,
+ isTween:true,
+
+ /**
+ * Construction of ccs.FrameData.
+ */
+ ctor:function () {
+ ccs.BaseData.prototype.ctor.call(this);
+ this.duration = 1;
+ this.tweenEasing = ccs.TweenType.LINEAR;
+ this.easingParamNumber = 0;
+ this.easingParams = [];
+ this.displayIndex = 0;
+ this.movement = "";
+ this.event = "";
+ this.sound = "";
+ this.soundEffect = "";
+ this.blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
+ this.frameID = 0;
+ this.isTween = true;
+ },
+
+ /**
+ * copy data
+ * @function
+ * @param frameData
+ */
+ copy:function (frameData) {
+ ccs.BaseData.prototype.copy.call(this, frameData);
+ this.duration = frameData.duration;
+ this.displayIndex = frameData.displayIndex;
+
+ this.tweenEasing = frameData.tweenEasing;
+ this.easingParamNumber = frameData.easingParamNumber;
+
+// this.movement = frameData.movement;
+// this.event = frameData.event;
+// this.sound = frameData.sound;
+// this.soundEffect = frameData.soundEffect;
+// this.easingParams.length = 0;
+ if (this.easingParamNumber !== 0){
+ this.easingParams.length = 0;
+ for (var i = 0; i
+ * The animation data information of Cocos Armature. It include all movement information for the Armature.
+ * The struct is AnimationData -> MovementData -> MovementBoneData -> FrameData
+ * -> MovementFrameData
+ *
+ * @class ccs.AnimationData
+ * @extends ccs.Class
+ */
+ccs.AnimationData = function(){
+ this.movementDataDic = {};
+ this.movementNames = [];
+ this.name = "";
+};
+
+/**
+ * adds movement data to the movement data dictionary
+ * @param {ccs.MovementData} moveData
+ */
+ccs.AnimationData.prototype.addMovement = function(moveData){
+ this.movementDataDic[moveData.name] = moveData;
+ this.movementNames.push(moveData.name);
+};
+
+/**
+ * gets movement data from movement data dictionary
+ * @param {String} moveName
+ * @returns {ccs.MovementData}
+ */
+ccs.AnimationData.prototype.getMovement = function(moveName){
+ return this.movementDataDic[moveName];
+};
+
+/**
+ * gets the count of movement data dictionary
+ * @returns {Number}
+ */
+ccs.AnimationData.prototype.getMovementCount = function(){
+ return Object.keys(this.movementDataDic).length;
+};
+
+/**
+ * contour vertex
+ * @class ccs.ContourVertex2
+ * @param {Number} x
+ * @param {Number} y
+ * @constructor
+ */
+ccs.ContourVertex2 = function (x, y) {
+ this.x = x || 0;
+ this.y = y || 0;
+};
+
+/**
+ * The Contour data information of Cocos Armature.
+ * @class ccs.ContourData
+ * @constructor
+ */
+ccs.ContourData = function(){
+ this.vertexList = [];
+};
+
+ccs.ContourData.prototype.init = function(){
+ this.vertexList.length = 0;
+ return true;
+};
+
+/**
+ * add a vertex object to vertex list
+ * @param {cc.Point} p
+ */
+ccs.ContourData.prototype.addVertex = function(p){
+ //var v = new ccs.ContourVertex2(p.x, p.y); //ccs.ContourVertex2 is same as cc.Point, so we needn't create a ccs.ContourVertex2 object
+ this.vertexList.push(p);
+};
+
+/**
+ * The texture data information of Cocos Armature
+ * @class ccs.TextureData
+ */
+ccs.TextureData = function(){
+ this.height = 0;
+ this.width = 0;
+ this.pivotX = 0.5;
+ this.pivotY = 0.5;
+ this.name = "";
+ this.contourDataList = [];
+};
+
+ccs.TextureData.prototype.init = function(){
+ this.contourDataList.length = 0;
+};
+
+/**
+ * Adds a contourData to contourDataList
+ * @param {ccs.ContourData} contourData
+ */
+ccs.TextureData.prototype.addContourData = function(contourData){
+ this.contourDataList.push(contourData);
+};
+
+/**
+ * gets a contourData from contourDataList by index
+ * @param {Number} index
+ * @returns {ccs.ContourData}
+ */
+ccs.TextureData.prototype.getContourData = function(index){
+ return this.contourDataList[index];
+};
diff --git a/extensions/CocoStudio/Armature/display/CCBatchNode.js b/extensions/cocostudio/armature/display/CCBatchNode.js
similarity index 51%
rename from extensions/CocoStudio/Armature/display/CCBatchNode.js
rename to extensions/cocostudio/armature/display/CCBatchNode.js
index d8f1b5031c..f20c238850 100644
--- a/extensions/CocoStudio/Armature/display/CCBatchNode.js
+++ b/extensions/cocostudio/armature/display/CCBatchNode.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,49 +23,75 @@
THE SOFTWARE.
****************************************************************************/
-cc.BatchNode = cc.Node.extend({
+/**
+ * A batchNode to Armature
+ * @class ccs.BatchNode
+ * @extends cc.Node
+ */
+ccs.BatchNode = cc.Node.extend(/** @lends ccs.BatchNode# */{
_atlas:null,
+ _className:"BatchNode",
+
ctor:function () {
this._atlas = null;
+
+ ccs.BatchNode.prototype.init.call(this);
},
+
init:function () {
var ret = cc.Node.prototype.init.call(this);
- this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR));
+ this.setShaderProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR));
return ret;
},
addChild:function (child, zOrder, tag) {
cc.Node.prototype.addChild.call(this, child, zOrder, tag);
- if (child instanceof cc.Armature) {
+ if (child instanceof cc.Armature){
child.setBatchNode(this);
}
},
- visit:function () {
+ removeChild: function(child, cleanup){
+ if (child instanceof cc.Armature)
+ child.setBatchNode(null);
+ cc.Node.prototype.removeChild.call(this, child, cleanup);
+ },
+
+ visit:function (renderer, parentTransform, parentTransformUpdated) {
// quick return if not visible. children won't be drawn.
- if (!this._visible) {
+ if (!this._visible)
return;
- }
- this.kmGLPushMatrix();
- if (this._grid && this._grid.isActive()) {
- this._grid.beforeDraw();
- }
- this.transform();
+
+ var dirty = parentTransformUpdated || this._transformUpdated;
+ if(dirty)
+ this._modelViewTransform = this.transform(parentTransform);
+ this._transformUpdated = false;
+
+ // IMPORTANT:
+ // To ease the migration to v3.0, we still support the kmGL stack,
+ // but it is deprecated and your code should not rely on it
+ cc.kmGLPushMatrixWitMat4(this._stackMatrix);
+
+ if (this.grid && this.grid.isActive())
+ this.grid.beforeDraw();
+
this.sortAllChildren();
- this.draw();
- // reset for next frame
- this._orderOfArrival = 0;
- if (this._grid && this._grid.isActive()) {
- this._grid.afterDraw(this);
- }
- this.kmGLPopMatrix();
+ this.draw(renderer, this._modelViewTransform, dirty);
+
+ if (this.grid && this.grid.isActive())
+ this.grid.afterDraw(this);
+
+ cc.kmGLPopMatrix();
},
- draw:function (ctx) {
- cc.NODE_DRAW_SETUP(this);
+ draw:function (renderer, transform, transformUpdated) {
+ var locChildren = this._children;
+ if(locChildren.length === 0)
+ return;
+
var child = null;
- for (var i = 0; i < this._children.length; i++) {
- child = this._children[i];
+ for (var i = 0, len = locChildren.length; i < len; i++) {
+ child = locChildren[i];
child.visit();
if (child instanceof cc.Armature) {
this._atlas = child.getTextureAtlas();
@@ -76,10 +103,12 @@ cc.BatchNode = cc.Node.extend({
}
}
});
-cc.BatchNode.create = function () {
- var batchNode = new cc.BatchNode();
- if (batchNode && batchNode.init()) {
- return batchNode;
- }
- return null;
+
+/**
+ *
+ * @returns {ccs.BatchNode}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.BatchNode.create = function () {
+ return new ccs.BatchNode();
};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js b/extensions/cocostudio/armature/display/CCDecorativeDisplay.js
similarity index 60%
rename from extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js
rename to extensions/cocostudio/armature/display/CCDecorativeDisplay.js
index f2544159db..f7a7c3d4bf 100644
--- a/extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js
+++ b/extensions/cocostudio/armature/display/CCDecorativeDisplay.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,58 +23,96 @@
THE SOFTWARE.
****************************************************************************/
-cc.DecotativeDisplay = cc.Class.extend({
- _display:null,
- _colliderDetector:null,
- _displayData:null,
+/**
+ * Decorative a display node for Cocos Armature
+ * @class
+ * @extends ccs.Class
+ */
+ccs.DecorativeDisplay = ccs.Class.extend(/** @lends ccs.DecorativeDisplay# */{
+ _display: null,
+ _colliderDetector: null,
+ _displayData: null,
ctor:function () {
this._display = null;
this._colliderDetector = null;
this._displayData = null;
+
+ //ccs.DecorativeDisplay.prototype.init.call(this);
},
+ /**
+ * Initializes a ccs.DecorativeDisplay
+ * @returns {boolean}
+ */
init:function () {
return true;
},
+ /**
+ * Sets display node to decorative
+ * @param {cc.Node} display
+ */
setDisplay:function (display) {
+ if(display._parent){
+ display._parent.removeChild(display);
+ delete display._parent;
+ }
this._display = display;
},
+ /**
+ * Returns the display node
+ * @returns {cc.Node}
+ */
getDisplay:function () {
return this._display;
},
+ /**
+ * Sets collide detector
+ * @param {ccs.ColliderDetector} colliderDetector
+ */
setColliderDetector:function (colliderDetector) {
this._colliderDetector = colliderDetector;
},
+ /**
+ * Returns collide detector
+ * @returns {ccs.ColliderDetector}
+ */
getColliderDetector:function () {
return this._colliderDetector;
},
+ /**
+ * Sets display data
+ * @param {ccs.DisplayData} displayData
+ */
setDisplayData:function (displayData) {
this._displayData = displayData;
},
+
+ /**
+ * Returns display data
+ * @returns {ccs.DisplayData}
+ */
getDisplayData:function () {
return this._displayData;
},
+
release:function () {
- CC_SAFE_RELEASE(this._display);
this._display = null;
- CC_SAFE_RELEASE(this._displayData);
this._displayData = null;
- CC_SAFE_RELEASE(this._colliderDetector);
this._colliderDetector = null;
}
-
});
-cc.DecotativeDisplay.create = function () {
- var decotativeDisplay = new cc.DecotativeDisplay();
- if (decotativeDisplay && decotativeDisplay.init()) {
- return decotativeDisplay;
- }
- return null;
+/**
+ * Allocates and initializes a decorative display.
+ * @return {ccs.DecorativeDisplay}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.DecorativeDisplay.create = function () {
+ return new ccs.DecorativeDisplay();
};
\ No newline at end of file
diff --git a/extensions/cocostudio/armature/display/CCDisplayFactory.js b/extensions/cocostudio/armature/display/CCDisplayFactory.js
new file mode 100644
index 0000000000..772bade72c
--- /dev/null
+++ b/extensions/cocostudio/armature/display/CCDisplayFactory.js
@@ -0,0 +1,219 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @ignore
+ */
+ccs.displayFactory = {
+ addDisplay: function (bone, decoDisplay, displayData) {
+ switch (displayData.displayType) {
+ case ccs.DISPLAY_TYPE_SPRITE:
+ this.addSpriteDisplay(bone, decoDisplay, displayData);
+ break;
+ case ccs.DISPLAY_TYPE_PARTICLE:
+ this.addParticleDisplay(bone, decoDisplay, displayData);
+ break;
+ case ccs.DISPLAY_TYPE_ARMATURE:
+ this.addArmatureDisplay(bone, decoDisplay, displayData);
+ break;
+ default:
+ break;
+ }
+ },
+
+ createDisplay: function (bone, decoDisplay) {
+ switch (decoDisplay.getDisplayData().displayType) {
+ case ccs.DISPLAY_TYPE_SPRITE:
+ this.createSpriteDisplay(bone, decoDisplay);
+ break;
+ case ccs.DISPLAY_TYPE_PARTICLE:
+ this.createParticleDisplay(bone, decoDisplay);
+ break;
+ case ccs.DISPLAY_TYPE_ARMATURE:
+ this.createArmatureDisplay(bone, decoDisplay);
+ break;
+ default:
+ break;
+ }
+ },
+
+ _helpTransform: {a:1, b:0, c:0, d:1, tx:0, ty:0},
+ updateDisplay: function (bone, dt, dirty) {
+ var display = bone.getDisplayRenderNode();
+ if(!display)
+ return;
+
+ switch (bone.getDisplayRenderNodeType()) {
+ case ccs.DISPLAY_TYPE_SPRITE:
+ if (dirty) {
+ display._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
+ display.updateArmatureTransform();
+ }
+ break;
+ case ccs.DISPLAY_TYPE_PARTICLE:
+ this.updateParticleDisplay(bone, display, dt);
+ break;
+ case ccs.DISPLAY_TYPE_ARMATURE:
+ this.updateArmatureDisplay(bone, display, dt);
+ break;
+ default:
+ var transform = bone.getNodeToArmatureTransform();
+ display.setAdditionalTransform(transform);
+ break;
+ }
+ if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
+ if (dirty) {
+ var decoDisplay = bone.getDisplayManager().getCurrentDecorativeDisplay();
+ var detector = decoDisplay.getColliderDetector();
+ if (detector) {
+ var node = decoDisplay.getDisplay();
+ var displayTransform = node.getNodeToParentTransform();
+ var helpTransform = this._helpTransform;
+ helpTransform.a = displayTransform.a;
+ helpTransform.b = displayTransform.b;
+ helpTransform.c = displayTransform.c;
+ helpTransform.d = displayTransform.d;
+ helpTransform.tx = displayTransform.tx;
+ helpTransform.ty = displayTransform.ty;
+ var anchorPoint = cc.pointApplyAffineTransform(node.getAnchorPointInPoints(), helpTransform);
+ helpTransform.tx = anchorPoint.x;
+ helpTransform.ty = anchorPoint.y;
+ var t = cc.affineTransformConcat(helpTransform, bone.getArmature().getNodeToParentTransform());
+ detector.updateTransform(t);
+ }
+ }
+ }
+ },
+
+ addSpriteDisplay: function (bone, decoDisplay, displayData) {
+ var sdp = new ccs.SpriteDisplayData();
+ sdp.copy(displayData);
+ decoDisplay.setDisplayData(sdp);
+ this.createSpriteDisplay(bone, decoDisplay);
+ },
+
+ createSpriteDisplay: function (bone, decoDisplay) {
+ var skin = null;
+ var displayData = decoDisplay.getDisplayData();
+ //! remove .xxx
+ var textureName = displayData.displayName;
+ var startPos = textureName.lastIndexOf(".");
+ if (startPos !== -1)
+ textureName = textureName.substring(0, startPos);
+ //! create display
+ if (textureName === "")
+ skin = new ccs.Skin();
+ else
+ skin = new ccs.Skin("#" + textureName + ".png");
+
+ decoDisplay.setDisplay(skin);
+
+ skin.setBone(bone);
+ this.initSpriteDisplay(bone, decoDisplay, displayData.displayName, skin);
+
+ var armature = bone.getArmature();
+ if (armature) {
+ if (armature.getArmatureData().dataVersion >= ccs.CONST_VERSION_COMBINED)
+ skin.setSkinData(displayData.skinData);
+ else
+ skin.setSkinData(bone.boneData);
+ }
+ },
+
+ initSpriteDisplay: function (bone, decoDisplay, displayName, skin) {
+ //! remove .xxx
+ var textureName = displayName;
+ var startPos = textureName.lastIndexOf(".");
+
+ if (startPos !== -1)
+ textureName = textureName.substring(0, startPos);
+
+ var textureData = ccs.armatureDataManager.getTextureData(textureName);
+ if (textureData) {
+ //! Init display anchorPoint, every Texture have a anchor point
+ skin.setAnchorPoint(cc.p(textureData.pivotX, textureData.pivotY));
+ }
+
+ if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
+ if (textureData && textureData.contourDataList.length > 0) {
+ //! create ContourSprite
+ var colliderDetector = new ccs.ColliderDetector(bone);
+ colliderDetector.addContourDataList(textureData.contourDataList);
+ decoDisplay.setColliderDetector(colliderDetector);
+ }
+ }
+ },
+
+ addArmatureDisplay: function (bone, decoDisplay, displayData) {
+ var adp = new ccs.ArmatureDisplayData();
+ adp.copy(displayData);
+ decoDisplay.setDisplayData(adp);
+
+ this.createArmatureDisplay(bone, decoDisplay);
+ },
+
+ createArmatureDisplay: function (bone, decoDisplay) {
+ var displayData = decoDisplay.getDisplayData();
+ var armature = new ccs.Armature(displayData.displayName, bone);
+ decoDisplay.setDisplay(armature);
+ },
+
+ updateArmatureDisplay: function (bone, armature, dt) {
+ if (armature) {
+ armature.sortAllChildren();
+ armature.update(dt);
+ }
+ },
+
+ addParticleDisplay: function (bone, decoDisplay, displayData) {
+ var adp = new ccs.ParticleDisplayData();
+ adp.copy(displayData);
+ decoDisplay.setDisplayData(adp);
+ this.createParticleDisplay(bone, decoDisplay);
+ },
+
+ createParticleDisplay: function (bone, decoDisplay) {
+ var displayData = decoDisplay.getDisplayData();
+ var system = new cc.ParticleSystem(displayData.displayName);
+
+ system.removeFromParent();
+ system.cleanup();
+
+ var armature = bone.getArmature();
+ if (armature)
+ system.setParent(bone.getArmature());
+
+ decoDisplay.setDisplay(system);
+ },
+
+ updateParticleDisplay: function (bone, particleSystem, dt) {
+ var node = new ccs.BaseData();
+ ccs.TransformHelp.matrixToNode(bone.nodeToArmatureTransform(), node);
+ particleSystem.setPosition(node.x, node.y);
+ particleSystem.setScaleX(node.scaleX);
+ particleSystem.setScaleY(node.scaleY);
+ particleSystem.update(dt);
+ }
+};
\ No newline at end of file
diff --git a/extensions/cocostudio/armature/display/CCDisplayManager.js b/extensions/cocostudio/armature/display/CCDisplayManager.js
new file mode 100644
index 0000000000..584f864b69
--- /dev/null
+++ b/extensions/cocostudio/armature/display/CCDisplayManager.js
@@ -0,0 +1,465 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The display manager for CocoStudio Armature bone.
+ * @Class ccs.DisplayManager
+ * @extend cc.Class
+ *
+ * @param {ccs.Bone} bone The bone for the display manager
+ */
+ccs.DisplayManager = ccs.Class.extend(/** @lends ccs.DisplayManager */{
+ _decoDisplayList: null,
+ _currentDecoDisplay: null,
+ _displayRenderNode: null,
+ _displayIndex: null,
+ _forceChangeDisplay: false,
+ _bone: null,
+ _visible: true,
+ _displayType: null,
+
+ ctor: function (bone) {
+ this._decoDisplayList = [];
+ this._currentDecoDisplay = null;
+ this._displayRenderNode = null;
+ this._displayIndex = null;
+ this._forceChangeDisplay = false;
+ this._bone = null;
+ this._visible = true;
+ this._displayType = ccs.DISPLAY_TYPE_MAX;
+
+ bone && ccs.DisplayManager.prototype.init.call(this, bone);
+ },
+
+ /**
+ * Initializes a ccs.DisplayManager.
+ * @param bone
+ * @returns {boolean}
+ */
+ init: function (bone) {
+ this._bone = bone;
+ this.initDisplayList(bone.getBoneData());
+ return true;
+ },
+
+ /**
+ *
+ * Add display and use _DisplayData init the display.
+ * If index already have a display, then replace it.
+ * If index is current display index, then also change display to _index
+ *
+ * @param {ccs.DisplayData|cc.Node} display it include the display information, like DisplayType. If you want to create a sprite display, then create a SpriteDisplayData param
+ * @param {Number} index the index of the display you want to replace or add to. -1 : append display from back
+ */
+ addDisplay: function (display, index) {
+ var decoDisplay, locDisplayList = this._decoDisplayList;
+ if ((index >= 0) && (index < locDisplayList.length))
+ decoDisplay = locDisplayList[index];
+ else {
+ decoDisplay = new ccs.DecorativeDisplay();
+ locDisplayList.push(decoDisplay);
+ }
+
+ if (display instanceof ccs.DisplayData) {
+ ccs.displayFactory.addDisplay(this._bone, decoDisplay, display);
+ //! if changed display index is current display index, then change current display to the new display
+ if (index === this._displayIndex) {
+ this._displayIndex = -1;
+ this.changeDisplayWithIndex(index, false);
+ }
+ return;
+ }
+
+ var displayData = null;
+ if (display instanceof ccs.Skin) {
+ display.setBone(this._bone);
+ displayData = new ccs.SpriteDisplayData();
+ ccs.displayFactory.initSpriteDisplay(this._bone, decoDisplay, display.getDisplayName(), display);
+
+ var spriteDisplayData = decoDisplay.getDisplayData();
+ if (spriteDisplayData instanceof ccs.SpriteDisplayData) {
+ display.setSkinData(spriteDisplayData.skinData);
+ displayData.skinData = spriteDisplayData.skinData;
+ } else {
+ var find = false;
+ for (var i = locDisplayList.length - 2; i >= 0; i--) {
+ var dd = locDisplayList[i];
+ var sdd = dd.getDisplayData();
+ if (sdd instanceof ccs.SpriteDisplayData) {
+ find = true;
+ display.setSkinData(sdd.skinData);
+ displayData.skinData = sdd.skinData;
+ break;
+ }
+ }
+ if (!find)
+ display.setSkinData(new ccs.BaseData());
+ }
+ } else if (display instanceof cc.ParticleSystem) {
+ displayData = new ccs.ParticleDisplayData();
+ display.removeFromParent();
+ display._performRecursive(cc.Node._stateCallbackType.cleanup);
+ var armature = this._bone.getArmature();
+ if (armature)
+ display.setParent(armature);
+ } else if (display instanceof ccs.Armature) {
+ displayData = new ccs.ArmatureDisplayData();
+ displayData.displayName = display.getName();
+ display.setParentBone(this._bone);
+ } else
+ displayData = new ccs.DisplayData();
+ decoDisplay.setDisplay(display);
+ decoDisplay.setDisplayData(displayData);
+
+ //! if changed display index is current display index, then change current display to the new display
+ if (index === this._displayIndex) {
+ this._displayIndex = -1;
+ this.changeDisplayWithIndex(index, false);
+ }
+ },
+
+ _addDisplayOther: function (decoDisplay, display) {
+ var displayData = null;
+ if (display instanceof ccs.Skin) {
+ var skin = display;
+ skin.setBone(this._bone);
+ displayData = new ccs.SpriteDisplayData();
+ displayData.displayName = skin.getDisplayName();
+ ccs.displayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin);
+ var spriteDisplayData = decoDisplay.getDisplayData();
+ if (spriteDisplayData instanceof ccs.SpriteDisplayData)
+ skin.setSkinData(spriteDisplayData.skinData);
+ else {
+ var find = false;
+ for (var i = this._decoDisplayList.length - 2; i >= 0; i--) {
+ var dd = this._decoDisplayList[i];
+ var sdd = dd.getDisplayData();
+ if (sdd) {
+ find = true;
+ skin.setSkinData(sdd.skinData);
+ displayData.skinData = sdd.skinData;
+ break;
+ }
+ }
+ if (!find) {
+ skin.setSkinData(new ccs.BaseData());
+ }
+ skin.setSkinData(new ccs.BaseData());
+ }
+
+ }
+ else if (display instanceof cc.ParticleSystem) {
+ displayData = new ccs.ParticleDisplayData();
+ displayData.displayName = display._plistFile;
+ }
+ else if (display instanceof ccs.Armature) {
+ displayData = new ccs.ArmatureDisplayData();
+ displayData.displayName = display.getName();
+ display.setParentBone(this._bone);
+ }
+ else {
+ displayData = new ccs.DisplayData();
+ }
+ decoDisplay.setDisplay(display);
+ decoDisplay.setDisplayData(displayData);
+ },
+
+ /**
+ * Removes display node from list.
+ * @param {Number} index
+ */
+ removeDisplay: function (index) {
+ this._decoDisplayList.splice(index, 1);
+ if (index === this._displayIndex) {
+ this.setCurrentDecorativeDisplay(null);
+ this._displayIndex = -1;
+ }
+ },
+
+ /**
+ * Returns the display node list.
+ * @returns {Array}
+ */
+ getDecorativeDisplayList: function () {
+ return this._decoDisplayList;
+ },
+
+ /**
+ *
+ * Change display by index. You can just use this method to change display in the display list.
+ * The display list is just used for this bone, and it is the displays you may use in every frame.
+ * Note : if index is the same with prev index, the method will not effect
+ *
+ * @param {Number} index The index of the display you want to change
+ * @param {Boolean} force If true, then force change display to specified display, or current display will set to display index edit in the flash every key frame.
+ */
+ changeDisplayWithIndex: function (index, force) {
+ if (index >= this._decoDisplayList.length) {
+ cc.log("the index value is out of range");
+ return;
+ }
+ this._forceChangeDisplay = force;
+
+ //if index is equal to current display index,then do nothing
+ if (this._displayIndex === index)
+ return;
+
+ this._displayIndex = index;
+
+ //! If displayIndex < 0, it means you want to hide you display
+ if (index < 0) {
+ if (this._displayRenderNode) {
+ this._displayRenderNode.removeFromParent(true);
+ this.setCurrentDecorativeDisplay(null);
+ }
+ return;
+ }
+ this.setCurrentDecorativeDisplay(this._decoDisplayList[index]);
+ },
+
+ /**
+ * Change display by name. @see changeDisplayWithIndex.
+ * @param {String} name
+ * @param {Boolean} force
+ */
+ changeDisplayWithName: function (name, force) {
+ var locDisplayList = this._decoDisplayList;
+ for (var i = 0; i < locDisplayList.length; i++) {
+ if (locDisplayList[i].getDisplayData().displayName === name) {
+ this.changeDisplayWithIndex(i, force);
+ break;
+ }
+ }
+ },
+
+ /**
+ * Sets current decorative display.
+ * @param {ccs.DecorativeDisplay} decoDisplay
+ */
+ setCurrentDecorativeDisplay: function (decoDisplay) {
+ var locCurrentDecoDisplay = this._currentDecoDisplay;
+ if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
+ if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector())
+ locCurrentDecoDisplay.getColliderDetector().setActive(false);
+ }
+
+ this._currentDecoDisplay = decoDisplay;
+ locCurrentDecoDisplay = this._currentDecoDisplay;
+ if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
+ if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector())
+ locCurrentDecoDisplay.getColliderDetector().setActive(true);
+ }
+
+ var displayRenderNode = (!locCurrentDecoDisplay) ? null : locCurrentDecoDisplay.getDisplay();
+
+ var locRenderNode = this._displayRenderNode, locBone = this._bone;
+ if (locRenderNode) {
+ if (locRenderNode instanceof ccs.Armature)
+ locBone.setChildArmature(null);
+ locRenderNode.removeFromParent(true);
+ }
+ this._displayRenderNode = displayRenderNode;
+
+ if (displayRenderNode) {
+ if (displayRenderNode instanceof ccs.Armature) {
+ this._bone.setChildArmature(displayRenderNode);
+ displayRenderNode.setParentBone(this._bone);
+ } else if (displayRenderNode instanceof cc.ParticleSystem) {
+ if (displayRenderNode instanceof ccs.Armature) {
+ locBone.setChildArmature(displayRenderNode);
+ displayRenderNode.setParentBone(locBone);
+ } else if (displayRenderNode instanceof cc.ParticleSystem)
+ displayRenderNode.resetSystem();
+ }
+
+ displayRenderNode.setColor(locBone.getDisplayedColor());
+ displayRenderNode.setOpacity(locBone.getDisplayedOpacity());
+
+ this._displayRenderNode.setVisible(this._visible);
+ this._displayType = this._currentDecoDisplay.getDisplayData().displayType;
+ } else
+ this._displayType = ccs.DISPLAY_TYPE_MAX;
+
+
+ cc.renderer.childrenOrderDirty = true;
+ },
+
+ /**
+ * Returns the current display render node.
+ * @returns {cc.Node}
+ */
+ getDisplayRenderNode: function () {
+ return this._displayRenderNode;
+ },
+
+ /**
+ * Returns the type of display render node.
+ * @returns {Number}
+ */
+ getDisplayRenderNodeType: function () {
+ return this._displayType;
+ },
+
+ /**
+ * Returns the index of display render node.
+ * @returns {Number}
+ */
+ getCurrentDisplayIndex: function () {
+ return this._displayIndex;
+ },
+
+ /**
+ * Returns the current decorative display
+ * @returns {ccs.DecorativeDisplay}
+ */
+ getCurrentDecorativeDisplay: function () {
+ return this._currentDecoDisplay;
+ },
+
+ /**
+ * Gets a decorative display by index.
+ * @param index
+ * @returns {ccs.DecorativeDisplay}
+ */
+ getDecorativeDisplayByIndex: function (index) {
+ return this._decoDisplayList[index];
+ },
+
+ /**
+ *
+ * Use BoneData to init the display list.
+ * If display is a sprite, and it have texture info in the TextureData, then use TextureData to init the display node's anchor point
+ * If the display is a Armature, then create a new Armature
+ *
+ * @param {ccs.BoneData} boneData
+ */
+ initDisplayList: function (boneData) {
+ this._decoDisplayList.length = 0;
+ if (!boneData)
+ return;
+ var displayList = boneData.displayDataList, decoList = this._decoDisplayList, locBone = this._bone;
+ for (var i = 0; i < displayList.length; i++) {
+ var displayData = displayList[i];
+ var decoDisplay = new ccs.DecorativeDisplay();
+ decoDisplay.setDisplayData(displayData);
+ ccs.displayFactory.createDisplay(locBone, decoDisplay);
+ decoList.push(decoDisplay);
+ }
+ },
+
+ /**
+ * Check if the position is inside the bone.
+ * @param {cc.Point|Number} point
+ * @param {Number} [y]
+ * @returns {boolean}
+ */
+ containPoint: function (point, y) {
+ if (!this._visible || this._displayIndex < 0)
+ return false;
+
+ if (y !== undefined)
+ point = cc.p(point, y);
+
+ if (this._currentDecoDisplay.getDisplayData().displayType === ccs.DISPLAY_TYPE_SPRITE) {
+ /*
+ * First we first check if the point is in the sprite content rect. If false, then we continue to check
+ * the contour point. If this step is also false, then we can say the bone not contain this point.
+ *
+ */
+ var sprite = this._currentDecoDisplay.getDisplay();
+ sprite = sprite.getChildByTag(0);
+ return ccs.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, point);
+ }
+ return false;
+ },
+
+ /**
+ *
+ * Sets whether the display is visible
+ * The default value is true, a node is default to visible
+ *
+ * @param {boolean} visible
+ */
+ setVisible: function (visible) {
+ if (!this._displayRenderNode)
+ return;
+ this._visible = visible;
+ this._displayRenderNode.setVisible(visible);
+ },
+
+ /**
+ * Determines if the display is visible
+ * @returns {boolean} true if the node is visible, false if the node is hidden.
+ */
+ isVisible: function () {
+ return this._visible;
+ },
+
+ getContentSize: function () {
+ if (!this._displayRenderNode)
+ return cc.size(0, 0);
+ return this._displayRenderNode.getContentSize();
+ },
+
+ getBoundingBox: function () {
+ if (!this._displayRenderNode)
+ return cc.rect(0, 0, 0, 0);
+ return this._displayRenderNode.getBoundingBox();
+ },
+
+ getAnchorPoint: function () {
+ if (!this._displayRenderNode)
+ return cc.p(0, 0);
+ return this._displayRenderNode.getAnchorPoint();
+ },
+
+ getAnchorPointInPoints: function () {
+ if (!this._displayRenderNode)
+ return cc.p(0, 0);
+ return this._displayRenderNode.getAnchorPointInPoints();
+ },
+
+ getForceChangeDisplay: function () {
+ return this._forceChangeDisplay;
+ },
+
+ release: function () {
+ this._decoDisplayList = null;
+ if (this._displayRenderNode) {
+ this._displayRenderNode.removeFromParent(true);
+ this._displayRenderNode = null;
+ }
+ }
+});
+
+/**
+ * Allocates and initializes a display manager with ccs.Bone.
+ * @param {ccs.Bone} bone
+ * @returns {ccs.DisplayManager}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.DisplayManager.create = function (bone) {
+ return new ccs.DisplayManager(bone);
+};
diff --git a/extensions/cocostudio/armature/display/CCSkin.js b/extensions/cocostudio/armature/display/CCSkin.js
new file mode 100644
index 0000000000..9f75ceb42e
--- /dev/null
+++ b/extensions/cocostudio/armature/display/CCSkin.js
@@ -0,0 +1,207 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * ccs.Bone uses ccs.Skin to displays on screen.
+ * @class
+ * @extends ccs.Sprite
+ *
+ * @param {String} [fileName]
+ * @param {cc.Rect} [rect]
+ *
+ * @property {Object} skinData - The data of the skin
+ * @property {ccs.Bone} bone - The bone of the skin
+ * @property {String} displayName - <@readonly> The displayed name of skin
+ *
+ */
+ccs.Skin = ccs.Sprite.extend(/** @lends ccs.Skin# */{
+ _skinData: null,
+ bone: null,
+ _skinTransform: null,
+ _displayName: "",
+ _armature: null,
+ _className: "Skin",
+
+ ctor: function (fileName, rect) {
+ cc.Sprite.prototype.ctor.call(this);
+ this._skinData = null;
+ this.bone = null;
+ this._displayName = "";
+ this._skinTransform = cc.affineTransformIdentity();
+ this._armature = null;
+
+ if (fileName == null || fileName === "") {
+ ccs.Skin.prototype.init.call(this);
+ } else {
+ if(fileName[0] === "#"){
+ ccs.Skin.prototype.initWithSpriteFrameName.call(this, fileName.substr(1));
+ } else {
+ ccs.Skin.prototype.initWithFile.call(this, fileName, rect);
+ }
+ }
+ },
+
+ /**
+ * Initializes with sprite frame name
+ * @param {String} spriteFrameName
+ * @returns {Boolean}
+ */
+ initWithSpriteFrameName: function (spriteFrameName) {
+ if(spriteFrameName === "")
+ return false;
+ var pFrame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
+ var ret = true;
+ if(pFrame)
+ this.initWithSpriteFrame(pFrame);
+ else{
+ cc.log("Can't find CCSpriteFrame with %s. Please check your .plist file", spriteFrameName);
+ ret = false;
+ }
+ this._displayName = spriteFrameName;
+ return ret;
+ },
+
+ /**
+ * Initializes with texture file name.
+ * @param {String} fileName
+ * @param {cc.Rect} rect
+ * @returns {Boolean}
+ */
+ initWithFile: function (fileName, rect) {
+ var ret = rect ? cc.Sprite.prototype.initWithFile.call(this, fileName, rect)
+ : cc.Sprite.prototype.initWithFile.call(this, fileName);
+ this._displayName = fileName;
+ return ret;
+ },
+
+ /**
+ * Sets skin data to ccs.Skin.
+ * @param {ccs.BaseData} skinData
+ */
+ setSkinData: function (skinData) {
+ this._skinData = skinData;
+ this.setScaleX(skinData.scaleX);
+ this.setScaleY(skinData.scaleY);
+ this.setRotationX(cc.radiansToDegrees(skinData.skewX));
+ this.setRotationY(cc.radiansToDegrees(-skinData.skewY));
+ this.setPosition(skinData.x, skinData.y);
+
+ this._renderCmd.transform();
+ },
+
+ /**
+ * Returns skin date of ccs.Skin.
+ * @returns {ccs.BaseData}
+ */
+ getSkinData: function () {
+ return this._skinData;
+ },
+
+ /**
+ * Updates armature skin's transform with skin transform and bone's transform.
+ */
+ updateArmatureTransform: function () {
+ this._renderCmd.transform();
+ },
+
+ /**
+ * Returns skin's world transform.
+ * @returns {cc.AffineTransform}
+ */
+ getNodeToWorldTransform: function(){
+ return this._renderCmd.getNodeToWorldTransform();
+ },
+
+ getNodeToWorldTransformAR: function(){
+ return this._renderCmd.getNodeToWorldTransformAR();
+ },
+
+ /**
+ * Sets the bone reference to ccs.Skin.
+ * @param bone
+ */
+ setBone: function (bone) {
+ this.bone = bone;
+ var armature = this.bone.getArmature();
+ if(armature)
+ this._armature = armature;
+ },
+
+ /**
+ * Returns the bone reference of ccs.Skin.
+ * @returns {null}
+ */
+ getBone: function () {
+ return this.bone;
+ },
+
+ /**
+ * display name getter
+ * @returns {String}
+ */
+ getDisplayName: function () {
+ return this._displayName;
+ },
+
+ _createRenderCmd: function(){
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new ccs.Skin.CanvasRenderCmd(this);
+ else
+ return new ccs.Skin.WebGLRenderCmd(this);
+ }
+});
+
+var _p = ccs.Skin.prototype;
+
+// Extended properties
+/** @expose */
+_p.skinData;
+cc.defineGetterSetter(_p, "skinData", _p.getSkinData, _p.setSkinData);
+/** @expose */
+_p.displayName;
+cc.defineGetterSetter(_p, "displayName", _p.getDisplayName);
+
+_p = null;
+
+/**
+ * allocates and initializes a skin.
+ * @param {String} [fileName] fileName or sprite frame name
+ * @param {cc.Rect} [rect]
+ * @returns {ccs.Skin}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.Skin.create = function (fileName, rect) {
+ return new ccs.Skin(fileName, rect);
+};
+
+/**
+ * allocates and initializes a skin.
+ * @param {String} spriteFrameName
+ * @returns {ccs.Skin}
+ * @deprecated since v3.1, please use new construction instead
+ */
+ccs.Skin.createWithSpriteFrameName = function (spriteFrameName) {
+ return new ccs.Skin("#" + spriteFrameName);
+};
diff --git a/extensions/cocostudio/armature/display/CCSkinRenderCmd.js b/extensions/cocostudio/armature/display/CCSkinRenderCmd.js
new file mode 100644
index 0000000000..eabcd02f00
--- /dev/null
+++ b/extensions/cocostudio/armature/display/CCSkinRenderCmd.js
@@ -0,0 +1,126 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ ccs.Skin.RenderCmd = {
+ _realWorldTM: null,
+ transform: function (parentCmd, recursive) {
+ if (!this._transform) {
+ this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ this._worldTransform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ }
+
+ var node = this._node,
+ pt = parentCmd ? parentCmd._worldTransform : null,
+ t = this._transform,
+ wt = this._worldTransform,
+ dirty = this._dirtyFlag & cc.Node._dirtyFlags.transformDirty;
+
+ if (dirty || pt) {
+ this.originTransform();
+ cc.affineTransformConcatIn(this._transform, node.bone.getNodeToArmatureTransform());
+ this._dirtyFlag &= ~cc.Node._dirtyFlags.transformDirty;
+ }
+
+ if (pt) {
+ wt.a = t.a * pt.a + t.b * pt.c;
+ wt.b = t.a * pt.b + t.b * pt.d;
+ wt.c = t.c * pt.a + t.d * pt.c;
+ wt.d = t.c * pt.b + t.d * pt.d;
+ wt.tx = t.tx * pt.a + t.ty * pt.c + pt.tx;
+ wt.ty = t.tx * pt.b + t.ty * pt.d + pt.ty;
+
+ var vertices = this._vertices;
+ if (vertices) {
+ var lx = node._offsetPosition.x, rx = lx + node._rect.width,
+ by = node._offsetPosition.y, ty = by + node._rect.height;
+
+ vertices[0].x = lx * wt.a + ty * wt.c + wt.tx; // tl
+ vertices[0].y = lx * wt.b + ty * wt.d + wt.ty;
+ vertices[1].x = lx * wt.a + by * wt.c + wt.tx; // bl
+ vertices[1].y = lx * wt.b + by * wt.d + wt.ty;
+ vertices[2].x = rx * wt.a + ty * wt.c + wt.tx; // tr
+ vertices[2].y = rx * wt.b + ty * wt.d + wt.ty;
+ vertices[3].x = rx * wt.a + by * wt.c + wt.tx; // br
+ vertices[3].y = rx * wt.b + by * wt.d + wt.ty;
+ }
+ }
+ else {
+ wt.a = t.a;
+ wt.b = t.b;
+ wt.c = t.c;
+ wt.d = t.d;
+ wt.tx = t.tx;
+ wt.ty = t.ty;
+ }
+ var rwtm = this._realWorldTM;
+ if (rwtm) {
+ rwtm.a = t.a; rwtm.b = t.b; rwtm.c = t.c; rwtm.d = t.d; rwtm.tx = t.tx; rwtm.ty = t.ty;
+ cc.affineTransformConcatIn(rwtm, this._node.bone.getArmature()._renderCmd._worldTransform);
+ }
+ },
+
+ getNodeToWorldTransform: function () {
+ return cc.affineTransformConcat(this._transform, this._node.bone.getArmature().getNodeToWorldTransform());
+ },
+
+ getNodeToWorldTransformAR: function () {
+ var displayTransform = this._transform, node = this._node;
+ this._anchorPointInPoints = cc.pointApplyAffineTransform(this._anchorPointInPoints, displayTransform);
+ displayTransform.tx = this._anchorPointInPoints.x;
+ displayTransform.ty = this._anchorPointInPoints.y;
+ return cc.affineTransformConcat(displayTransform, node.bone.getArmature().getNodeToWorldTransform());
+ }
+ };
+
+ ccs.Skin.CanvasRenderCmd = function (renderable) {
+ this._spriteCmdCtor(renderable);
+ this._realWorldTM = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0};
+ };
+
+ var proto = ccs.Skin.CanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
+ cc.inject(ccs.Skin.RenderCmd, proto);
+
+ proto.constructor = ccs.Skin.CanvasRenderCmd;
+
+ proto._updateCurrentRegions = function () {
+ var temp = this._currentRegion;
+ this._currentRegion = this._oldRegion;
+ this._oldRegion = temp;
+ //hittest will call the transform, and set region flag to DirtyDouble, and the changes need to be considered for rendering
+ if (cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble === this._regionFlag && (!this._currentRegion.isEmpty())) {
+ this._oldRegion.union(this._currentRegion);
+ }
+ this._currentRegion.updateRegion(this.getLocalBB(), this._realWorldTM);
+ };
+
+ ccs.Skin.WebGLRenderCmd = function (renderable) {
+ this._spriteCmdCtor(renderable);
+ };
+
+ proto = ccs.Skin.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
+ cc.inject(ccs.Skin.RenderCmd, proto);
+ proto.constructor = ccs.Skin.WebGLRenderCmd;
+})();
diff --git a/extensions/cocostudio/armature/physics/CCColliderDetector.js b/extensions/cocostudio/armature/physics/CCColliderDetector.js
new file mode 100644
index 0000000000..dccbe5882d
--- /dev/null
+++ b/extensions/cocostudio/armature/physics/CCColliderDetector.js
@@ -0,0 +1,397 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @ignore
+ */
+ccs.PT_RATIO = 32;
+
+/**
+ * Base class for ccs.ColliderFilter
+ * @class
+ * @extends ccs.Class
+ */
+ccs.ColliderFilter = ccs.Class.extend(/** @lends ccs.ColliderFilter# */{
+ _collisionType: 0,
+ _group: 0,
+ _categoryBits: 0,
+ _groupIndex: 0,
+ _maskBits: 0,
+
+ ctor: function (collisionType, group) {
+ this._collisionType = collisionType || 0;
+ this._group = group || 0;
+ },
+
+ updateShape: function (shape) {
+ if(shape instanceof cp.Shape){
+ shape.collision_type = this._collisionType;
+ shape.group = this._group;
+ }else if(shape instanceof Box2D.b2FilterData){
+ var filter = new Box2D.b2FilterData();
+ filter.categoryBits = this._categoryBits;
+ filter.groupIndex = this._groupIndex;
+ filter.maskBits = this._maskBits;
+
+ shape.SetFilterData(filter);
+ }
+ }
+});
+
+/**
+ * Base class for ccs.ColliderBody
+ * @class
+ * @extends ccs.Class
+ *
+ * @property {ccs.ContourData} contourData - The contour data of collider body
+ * @property {ccs.Shape} shape - The shape of collider body
+ * @property {ccs.ColliderFilter} colliderFilter - The collider filter of collider body
+ *
+ */
+ccs.ColliderBody = ccs.Class.extend(/** @lends ccs.ColliderBody# */{
+ shape: null,
+ coutourData: null,
+ colliderFilter: null,
+ _calculatedVertexList: null,
+ ctor: function (contourData) {
+ this.shape = null;
+ this.coutourData = contourData;
+ this.colliderFilter = new ccs.ColliderFilter();
+ if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
+ this._calculatedVertexList = [];
+ }
+ },
+
+ /**
+ * contourData getter
+ * @returns {ccs.ContourData}
+ */
+ getContourData: function () {
+ return this.coutourData;
+ },
+
+ /**
+ * colliderFilter setter
+ * @param {ccs.ColliderFilter} colliderFilter
+ */
+ setColliderFilter: function (colliderFilter) {
+ this.colliderFilter = colliderFilter;
+ },
+
+ /**
+ * get calculated vertex list
+ * @returns {Array}
+ */
+ getCalculatedVertexList: function () {
+ return this._calculatedVertexList;
+ },
+
+ setB2Fixture: function(fixture){
+ this._fixture = fixture;
+ },
+
+ getB2Fixture: function(){
+ return this._fixture;
+ },
+
+ /**
+ * shape getter
+ * @param {ccs.Shape} shape
+ */
+ setShape: function (shape) {
+ this.shape = shape;
+ },
+
+ /**
+ * shape setter
+ * @return {ccs.Shape}
+ */
+ getShape: function () {
+ return this.shape;
+ },
+
+ /**
+ * contourData setter
+ * @param {ccs.ContourData} contourData
+ */
+ setContourData: function (contourData) {
+ this.coutourData = contourData;
+ },
+
+ /**
+ * colliderFilter getter
+ * @returns {ccs.ColliderFilter}
+ */
+ getColliderFilter: function () {
+ return this.colliderFilter;
+ }
+});
+
+/**
+ * Base class for ccs.ColliderDetector
+ * @class
+ * @extends ccs.Class
+ *
+ * @param {ccs.Bone} [bone]
+ *
+ * @property {ccs.ColliderFilter} colliderFilter - The collider filter of the collider detector
+ * @property {Boolean} active - Indicate whether the collider detector is active
+ * @property {Object} body - The collider body
+ */
+ccs.ColliderDetector = ccs.Class.extend(/** @lends ccs.ColliderDetector# */{
+ _colliderBodyList: null,
+ _bone: null,
+ _body: null,
+ _active: false,
+ _filter: null,
+ helpPoint: cc.p(0, 0),
+
+ ctor: function (bone) {
+ this._colliderBodyList = [];
+ this._bone = null;
+ this._body = null;
+ this._active = false;
+ this._filter = null;
+
+ ccs.ColliderDetector.prototype.init.call(this, bone);
+ },
+ init: function (bone) {
+ this._colliderBodyList.length = 0;
+ if (bone)
+ this._bone = bone;
+ this._filter = new ccs.ColliderFilter();
+ return true;
+ },
+
+ /**
+ * add contourData
+ * @param {ccs.ContourData} contourData
+ */
+ addContourData: function (contourData) {
+ var colliderBody = new ccs.ColliderBody(contourData);
+ this._colliderBodyList.push(colliderBody);
+
+ if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
+ var calculatedVertexList = colliderBody.getCalculatedVertexList();
+ var vertexList = contourData.vertexList;
+ for (var i = 0; i < vertexList.length; i++) {
+ var newVertex = new ccs.ContourVertex2(0, 0);
+ calculatedVertexList.push(newVertex);
+ }
+ }
+ },
+
+ /**
+ * add contourData
+ * @param {Array} contourDataList
+ */
+ addContourDataList: function (contourDataList) {
+ for (var i = 0; i < contourDataList.length; i++) {
+ this.addContourData(contourDataList[i]);
+ }
+ },
+
+ /**
+ * remove contourData
+ * @param contourData
+ */
+ removeContourData: function (contourData) {
+ var eraseList = [], i, locBodyList = this._colliderBodyList;
+ for (i = 0; i < locBodyList.length; i++) {
+ var body = locBodyList[i];
+ if (body && body.getContourData() === contourData)
+ eraseList.push(body);
+ }
+
+ for (i=0; igetB2Fixture()->GetShape();
+ shape = colliderBody.getShape();
+ }
+
+ var vs = contourData.vertexList;
+ var cvs = colliderBody.getCalculatedVertexList();
+
+ for (var j = 0; j < vs.length; j++) {
+ locHelpPoint.x = vs[j].x;
+ locHelpPoint.y = vs[j].y;
+ locHelpPoint = cc.pointApplyAffineTransform(locHelpPoint, t);
+
+ if (ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
+ var v = cc.p(0, 0);
+ v.x = locHelpPoint.x;
+ v.y = locHelpPoint.y;
+ cvs[j] = v;
+ }
+
+ if (shape) {
+ shape.verts[j * 2] = locHelpPoint.x;
+ shape.verts[j * 2 + 1] = locHelpPoint.y;
+ }
+ }
+ if (shape) {
+ for (var j = 0; j < vs.length; j++) {
+ var b = shape.verts[(j + 1) % shape.verts.length];
+ var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[j])));
+
+ if(shape.planes){
+ shape.planes[j].n = n;
+ shape.planes[j].d = cp.v.dot(n, shape.verts[j]);
+ }
+// var b = shape.verts[(i + 1) % shape.numVerts];
+// var n = cp.v.normalize(cp.v.perp(cp.v.sub(b, shape.verts[i])));
+//
+// shape.planes[i].n = n;
+// shape.planes[i].d = cp.v.dot(n, shape.verts[i]);
+ }
+ }
+ }
+ },
+
+ setBody: function (body) {
+ this._body = body;
+ var colliderBody, locBodyList = this._colliderBodyList;
+ for (var i = 0; i < locBodyList.length; i++) {
+ colliderBody = locBodyList[i];
+ var contourData = colliderBody.getContourData(), verts = [];
+ var vs = contourData.vertexList;
+ for (var j = 0; j < vs.length; j++) {
+ var v = vs[j];
+ verts.push(v.x);
+ verts.push(v.y);
+ }
+ var shape = new cp.PolyShape(this._body, verts, cp.vzero);
+ shape.sensor = true;
+ shape.data = this._bone;
+ if (this._active)
+ this._body.space.addShape(shape);
+ colliderBody.setShape(shape);
+ colliderBody.getColliderFilter().updateShape(shape);
+ }
+ },
+
+ getBody: function () {
+ return this._body;
+ }
+});
+
+var _p = ccs.ColliderDetector.prototype;
+
+// Extended properties
+/** @expose */
+_p.colliderFilter;
+cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter);
+/** @expose */
+_p.active;
+cc.defineGetterSetter(_p, "active", _p.getActive, _p.setActive);
+/** @expose */
+_p.body;
+cc.defineGetterSetter(_p, "body", _p.getBody, _p.setBody);
+
+_p = null;
+
+ccs.ColliderDetector.create = function (bone) {
+ return new ccs.ColliderDetector(bone);
+};
\ No newline at end of file
diff --git a/extensions/cocostudio/armature/utils/CCArmatureDataManager.js b/extensions/cocostudio/armature/utils/CCArmatureDataManager.js
new file mode 100644
index 0000000000..ca901bbb7d
--- /dev/null
+++ b/extensions/cocostudio/armature/utils/CCArmatureDataManager.js
@@ -0,0 +1,329 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * RelativeData uses to save plist files, armature files, animations and textures for armature data manager.
+ * @constructor
+ */
+ccs.RelativeData = function () {
+ this.plistFiles = [];
+ this.armatures = [];
+ this.animations = [];
+ this.textures = [];
+};
+
+/**
+ * ccs.armatureDataManager is a singleton object which format and manage armature configuration and armature animation
+ * @class
+ * @name ccs.armatureDataManager
+ */
+ccs.armatureDataManager = /** @lends ccs.armatureDataManager# */ {
+ _animationDatas: {},
+ _armatureDatas: {},
+ _textureDatas: {},
+ _autoLoadSpriteFile: false,
+ _relativeDatas: {},
+
+ s_sharedArmatureDataManager: null,
+
+ /**
+ * Removes armature cache data by configFilePath
+ * @param {String} configFilePath
+ */
+ removeArmatureFileInfo: function (configFilePath) {
+ var data = this.getRelativeData(configFilePath);
+ if (data) {
+ var i, obj;
+ for (i = 0; i < data.armatures.length; i++) {
+ obj = data.armatures[i];
+ this.removeArmatureData(obj);
+ }
+ for (i = 0; i < data.animations.length; i++) {
+ obj = data.animations[i];
+ this.removeAnimationData(obj);
+ }
+ for (i = 0; i < data.textures.length; i++) {
+ obj = data.textures[i];
+ this.removeTextureData(obj);
+ }
+ for (i = 0; i < data.plistFiles.length; i++) {
+ obj = data.plistFiles[i];
+ cc.spriteFrameCache.removeSpriteFramesFromFile(obj);
+ }
+ delete this._relativeDatas[configFilePath];
+ ccs.dataReaderHelper.removeConfigFile(configFilePath);
+ }
+ },
+
+ /**
+ * Adds armature data
+ * @param {string} id The id of the armature data
+ * @param {ccs.ArmatureData} armatureData
+ */
+ addArmatureData: function (id, armatureData, configFilePath) {
+ var data = this.getRelativeData(configFilePath);
+ if (data) {
+ data.armatures.push(id);
+ }
+ this._armatureDatas[id] = armatureData;
+ },
+
+ /**
+ * Gets armatureData by id
+ * @param {String} id
+ * @return {ccs.ArmatureData}
+ */
+ getArmatureData: function (id) {
+ var armatureData = null;
+ if (this._armatureDatas) {
+ armatureData = this._armatureDatas[id];
+ }
+ return armatureData;
+ },
+
+ /**
+ * Removes armature data from armature data manager.
+ * @param {string} id
+ */
+ removeArmatureData: function (id) {
+ if (this._armatureDatas[id])
+ delete this._armatureDatas[id];
+ },
+
+ /**
+ * Adds animation data to armature data manager.
+ * @param {String} id
+ * @param {ccs.AnimationData} animationData
+ */
+ addAnimationData: function (id, animationData, configFilePath) {
+ var data = this.getRelativeData(configFilePath);
+ if (data)
+ data.animations.push(id);
+ this._animationDatas[id] = animationData;
+ },
+
+ /**
+ * Gets animationData by id
+ * @param {String} id
+ * @return {ccs.AnimationData}
+ */
+ getAnimationData: function (id) {
+ var animationData = null;
+ if (this._animationDatas[id]) {
+ animationData = this._animationDatas[id];
+ }
+ return animationData;
+ },
+
+ /**
+ * Removes animation data
+ * @param {string} id
+ */
+ removeAnimationData: function (id) {
+ if (this._animationDatas[id])
+ delete this._animationDatas[id];
+ },
+
+ /**
+ * Adds texture data to Armature data manager.
+ * @param {String} id
+ * @param {ccs.TextureData} textureData
+ */
+ addTextureData: function (id, textureData, configFilePath) {
+ var data = this.getRelativeData(configFilePath);
+ if (data) {
+ data.textures.push(id);
+ }
+ this._textureDatas[id] = textureData;
+ },
+
+ /**
+ * Gets textureData by id
+ * @param {String} id
+ * @return {ccs.TextureData}
+ */
+ getTextureData: function (id) {
+ var textureData = null;
+ if (this._textureDatas) {
+ textureData = this._textureDatas[id];
+ }
+ return textureData;
+ },
+
+ /**
+ * Removes texture data by id
+ * @param {string} id
+ */
+ removeTextureData: function (id) {
+ if (this._textureDatas[id])
+ delete this._textureDatas[id];
+ },
+
+ /**
+ * Adds ArmatureFileInfo, it is managed by CCArmatureDataManager.
+ * @param {String} imagePath
+ * @param {String} plistPath
+ * @param {String} configFilePath
+ * @example
+ * //example1
+ * ccs.armatureDataManager.addArmatureFileInfo("res/test.json");
+ * //example2
+ * ccs.armatureDataManager.addArmatureFileInfo("res/test.png","res/test.plist","res/test.json");
+ */
+ addArmatureFileInfo: function ( /*imagePath, plistPath, configFilePath*/ ) {
+ var imagePath, plistPath, configFilePath;
+ switch (arguments.length) {
+ case 1:
+ configFilePath = arguments[0];
+
+ this.addRelativeData(configFilePath);
+
+ this._autoLoadSpriteFile = true;
+ ccs.dataReaderHelper.addDataFromFile(configFilePath);
+ break;
+ case 3:
+ imagePath = arguments[0];
+ plistPath = arguments[1];
+ configFilePath = arguments[2];
+
+ this.addRelativeData(configFilePath);
+
+ this._autoLoadSpriteFile = false;
+ ccs.dataReaderHelper.addDataFromFile(configFilePath);
+ this.addSpriteFrameFromFile(plistPath, imagePath);
+ }
+ },
+
+ /**
+ * Adds ArmatureFileInfo, it is managed by CCArmatureDataManager.
+ * @param {String} imagePath
+ * @param {String} plistPath
+ * @param {String} configFilePath
+ * @param {Function} selector
+ * @param {Object} target
+ */
+ addArmatureFileInfoAsync: function ( /*imagePath, plistPath, configFilePath, selector, target*/ ) {
+ var imagePath, plistPath, configFilePath, target, selector;
+ switch (arguments.length) {
+ case 3:
+ configFilePath = arguments[0];
+ target = arguments[2];
+ selector = arguments[1];
+ this.addRelativeData(configFilePath);
+ this._autoLoadSpriteFile = true;
+ ccs.dataReaderHelper.addDataFromFileAsync("", "", configFilePath, selector, target);
+ break;
+ case 5:
+ imagePath = arguments[0];
+ plistPath = arguments[1];
+ configFilePath = arguments[2];
+ target = arguments[4];
+ selector = arguments[3];
+ this.addRelativeData(configFilePath);
+
+ this._autoLoadSpriteFile = false;
+ ccs.dataReaderHelper.addDataFromFileAsync(imagePath, plistPath, configFilePath, selector, target);
+ this.addSpriteFrameFromFile(plistPath, imagePath);
+ }
+ },
+
+ /**
+ * Add sprite frame to CCSpriteFrameCache, it will save display name and it's relative image name
+ * @param {String} plistPath
+ * @param {String} imagePath
+ * @param {String} configFilePath
+ */
+ addSpriteFrameFromFile: function (plistPath, imagePath, configFilePath) {
+ var data = this.getRelativeData(configFilePath);
+ if (data)
+ data.plistFiles.push(plistPath);
+ ccs.spriteFrameCacheHelper.addSpriteFrameFromFile(plistPath, imagePath);
+ },
+
+ /**
+ * Returns whether or not need auto load sprite file
+ * @returns {boolean}
+ */
+ isAutoLoadSpriteFile: function () {
+ return this._autoLoadSpriteFile;
+ },
+
+ /**
+ * Returns armature Data of Armature data manager.
+ * @return {Object}
+ */
+ getArmatureDatas: function () {
+ return this._armatureDatas;
+ },
+
+ /**
+ * Returns animation data of Armature data manager.
+ * @return {Object}
+ */
+ getAnimationDatas: function () {
+ return this._animationDatas;
+ },
+
+ /**
+ * Returns texture data of Armature data manager.
+ * @return {Object}
+ */
+ getTextureDatas: function () {
+ return this._textureDatas;
+ },
+
+ /**
+ * Adds RelativeData of Armature data manager.
+ * @param {String} configFilePath
+ */
+ addRelativeData: function (configFilePath) {
+ if (!this._relativeDatas[configFilePath])
+ this._relativeDatas[configFilePath] = new ccs.RelativeData();
+ },
+
+ /**
+ * Gets RelativeData of Armature data manager.
+ * @param {String} configFilePath
+ * @returns {ccs.RelativeData}
+ */
+ getRelativeData: function (configFilePath) {
+ return this._relativeDatas[configFilePath];
+ },
+
+ /**
+ * Clear data
+ */
+ clear: function () {
+ for (var key in this._relativeDatas) {
+ this.removeArmatureFileInfo(key);
+ }
+ this._animationDatas = {};
+ this._armatureDatas = {};
+ this._textureDatas = {};
+ this._relativeDatas = {};
+ ccs.spriteFrameCacheHelper.clear();
+ ccs.dataReaderHelper.clear();
+ }
+};
diff --git a/extensions/CocoStudio/GUI/System/CocosGUI.js b/extensions/cocostudio/armature/utils/CCArmatureDefine.js
similarity index 65%
rename from extensions/CocoStudio/GUI/System/CocosGUI.js
rename to extensions/cocostudio/armature/utils/CCArmatureDefine.js
index cd7cfd1e13..a7db1b9203 100644
--- a/extensions/CocoStudio/GUI/System/CocosGUI.js
+++ b/extensions/cocostudio/armature/utils/CCArmatureDefine.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -21,12 +22,24 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
+/**
+ * @ignore
+ */
+ccs.VERSION_COMBINED = 0.30;
+ccs.VERSION_CHANGE_ROTATION_RANGE = 1.0;
+ccs.VERSION_COLOR_READING = 1.1;
+ccs.MAX_VERTEXZ_VALUE = 5000000.0;
+ccs.ARMATURE_MAX_CHILD = 50.0;
+ccs.ARMATURE_MAX_ZORDER = 100;
+ccs.ARMATURE_MAX_COUNT = ((ccs.MAX_VERTEXZ_VALUE) / (ccs.ARMATURE_MAX_CHILD) / ccs.ARMATURE_MAX_ZORDER);
+ccs.AUTO_ADD_SPRITE_FRAME_NAME_PREFIX = false;
+ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT = false;
+ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX = false;
/**
- * Get CocoStudio version
+ * Returns the version of Armature.
* @returns {string}
- * @constructor
*/
-cc.CocosGUIVersion = function(){
- return "CocosGUI v1.0.0.0";
-};
\ No newline at end of file
+ccs.armatureVersion = function(){
+ return "v1.1.0.0";
+};
diff --git a/extensions/cocostudio/armature/utils/CCDataReaderHelper.js b/extensions/cocostudio/armature/utils/CCDataReaderHelper.js
new file mode 100644
index 0000000000..b029fb2df8
--- /dev/null
+++ b/extensions/cocostudio/armature/utils/CCDataReaderHelper.js
@@ -0,0 +1,1223 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @ignore
+ */
+ccs.CONST_VERSION = "version";
+ccs.CONST_VERSION_2_0 = 2.0;
+ccs.CONST_VERSION_COMBINED = 0.3;
+
+ccs.CONST_ARMATURES = "armatures";
+ccs.CONST_ARMATURE = "armature";
+ccs.CONST_BONE = "b";
+ccs.CONST_DISPLAY = "d";
+
+ccs.CONST_ANIMATIONS = "animations";
+ccs.CONST_ANIMATION = "animation";
+ccs.CONST_MOVEMENT = "mov";
+ccs.CONST_FRAME = "f";
+
+ccs.CONST_TEXTURE_ATLAS = "TextureAtlas";
+ccs.CONST_SUB_TEXTURE = "SubTexture";
+
+ccs.CONST_SKELETON = "skeleton";
+
+ccs.CONST_A_NAME = "name";
+ccs.CONST_A_DURATION = "dr";
+ccs.CONST_A_FRAME_INDEX = "fi";
+ccs.CONST_A_DURATION_TO = "to";
+ccs.CONST_A_DURATION_TWEEN = "drTW";
+ccs.CONST_A_LOOP = "lp";
+ccs.CONST_A_MOVEMENT_SCALE = "sc";
+ccs.CONST_A_MOVEMENT_DELAY = "dl";
+ccs.CONST_A_DISPLAY_INDEX = "dI";
+
+ccs.CONST_A_PLIST = "plist";
+
+ccs.CONST_A_PARENT = "parent";
+ccs.CONST_A_SKEW_X = "kX";
+ccs.CONST_A_SKEW_Y = "kY";
+ccs.CONST_A_SCALE_X = "cX";
+ccs.CONST_A_SCALE_Y = "cY";
+ccs.CONST_A_Z = "z";
+ccs.CONST_A_EVENT = "evt";
+ccs.CONST_A_SOUND = "sd";
+ccs.CONST_A_SOUND_EFFECT = "sdE";
+ccs.CONST_A_TWEEN_EASING = "twE";
+ccs.CONST_A_EASING_PARAM = "twEP";
+ccs.CONST_A_TWEEN_ROTATE = "twR";
+ccs.CONST_A_IS_ARMATURE = "isArmature";
+ccs.CONST_A_DISPLAY_TYPE = "displayType";
+ccs.CONST_A_MOVEMENT = "mov";
+
+ccs.CONST_A_X = "x";
+ccs.CONST_A_Y = "y";
+
+ccs.CONST_A_COCOS2DX_X = "cocos2d_x";
+ccs.CONST_A_COCOS2DX_Y = "cocos2d_y";
+
+ccs.CONST_A_WIDTH = "width";
+ccs.CONST_A_HEIGHT = "height";
+ccs.CONST_A_PIVOT_X = "pX";
+ccs.CONST_A_PIVOT_Y = "pY";
+
+ccs.CONST_A_COCOS2D_PIVOT_X = "cocos2d_pX";
+ccs.CONST_A_COCOS2D_PIVOT_Y = "cocos2d_pY";
+
+ccs.CONST_A_BLEND_TYPE = "bd";
+ccs.CONST_A_BLEND_SRC = "bd_src";
+ccs.CONST_A_BLEND_DST = "bd_dst";
+
+ccs.CONST_A_ALPHA = "a";
+ccs.CONST_A_RED = "r";
+ccs.CONST_A_GREEN = "g";
+ccs.CONST_A_BLUE = "b";
+ccs.CONST_A_ALPHA_OFFSET = "aM";
+ccs.CONST_A_RED_OFFSET = "rM";
+ccs.CONST_A_GREEN_OFFSET = "gM";
+ccs.CONST_A_BLUE_OFFSET = "bM";
+ccs.CONST_A_COLOR_TRANSFORM = "colorTransform";
+ccs.CONST_A_TWEEN_FRAME = "tweenFrame";
+
+ccs.CONST_CONTOUR = "con";
+ccs.CONST_CONTOUR_VERTEX = "con_vt";
+
+ccs.CONST_FL_NAN = "NaN";
+
+ccs.CONST_FRAME_DATA = "frame_data";
+ccs.CONST_MOVEMENT_BONE_DATA = "mov_bone_data";
+ccs.CONST_MOVEMENT_DATA = "mov_data";
+ccs.CONST_ANIMATION_DATA = "animation_data";
+ccs.CONST_DISPLAY_DATA = "display_data";
+ccs.CONST_SKIN_DATA = "skin_data";
+ccs.CONST_BONE_DATA = "bone_data";
+ccs.CONST_ARMATURE_DATA = "armature_data";
+ccs.CONST_CONTOUR_DATA = "contour_data";
+ccs.CONST_TEXTURE_DATA = "texture_data";
+ccs.CONST_VERTEX_POINT = "vertex";
+ccs.CONST_COLOR_INFO = "color";
+
+ccs.CONST_CONFIG_FILE_PATH = "config_file_path";
+ccs.CONST_CONTENT_SCALE = "content_scale";
+
+/**
+ * @ignore
+ * @constructor
+ */
+ccs.DataInfo = function () {
+ this.asyncStruct = null;
+ this.configFileQueue = [];
+ this.contentScale = 1;
+ this.filename = "";
+ this.baseFilePath = "";
+ this.flashToolVersion = 0;
+ this.cocoStudioVersion = 0
+};
+
+/**
+ * ccs.dataReaderHelper is a singleton object for reading CocoStudio data
+ * @class
+ * @name ccs.dataReaderHelper
+ */
+ccs.dataReaderHelper = /** @lends ccs.dataReaderHelper# */{
+ ConfigType: {
+ DragonBone_XML: 0,
+ CocoStudio_JSON: 1,
+ CocoStudio_Binary: 2
+ },
+
+ _configFileList: [],
+ _flashToolVersion: ccs.CONST_VERSION_2_0,
+// _cocoStudioVersion: ccs.CONST_VERSION_COMBINED,
+ _positionReadScale: 1,
+ _asyncRefCount: 0,
+ _asyncRefTotalCount: 0,
+
+ _dataQueue: null,
+
+ //LoadData don't need
+
+ setPositionReadScale: function (scale) {
+ this._positionReadScale = scale;
+ },
+
+ getPositionReadScale: function () {
+ return this._positionReadScale;
+ },
+
+ /**
+ * Add armature data from file.
+ * @param {String} filePath
+ */
+ addDataFromFile: function (filePath) {
+ /*
+ * Check if file is already added to ArmatureDataManager, if then return.
+ */
+ if (this._configFileList.indexOf(filePath) !== -1)
+ return;
+ this._configFileList.push(filePath);
+
+ //! find the base file path
+ var basefilePath = this._initBaseFilePath(filePath);
+
+ // Read content from file
+ // Here the reader into the next process
+
+ var str = cc.path.extname(filePath).toLowerCase();
+
+ var dataInfo = new ccs.DataInfo();
+ dataInfo.filename = filePath;
+ dataInfo.basefilePath = basefilePath;
+ if (str === ".xml")
+ ccs.dataReaderHelper.addDataFromXML(filePath, dataInfo);
+ else if (str === ".json" || str === ".exportjson")
+ ccs.dataReaderHelper.addDataFromJson(filePath, dataInfo);
+ else if(str === ".csb")
+ ccs.dataReaderHelper.addDataFromBinaryCache(filePath, dataInfo);
+ },
+
+ /**
+ * Adds data from file with Async.
+ * @param {String} imagePath
+ * @param {String} plistPath
+ * @param {String} filePath
+ * @param {function} selector
+ * @param {Object} [target]
+ */
+ addDataFromFileAsync: function (imagePath, plistPath, filePath, selector, target) {
+ /*
+ * Check if file is already added to ArmatureDataManager, if then return.
+ */
+ if (this._configFileList.indexOf(filePath) !== -1) {
+ if (target && selector) {
+ if (this._asyncRefTotalCount === 0 && this._asyncRefCount === 0)
+ this._asyncCallBack(selector,target, 1);
+ else
+ this._asyncCallBack(selector, target, (this._asyncRefTotalCount - this._asyncRefCount) / this._asyncRefTotalCount);
+ }
+ return;
+ }
+// this._configFileList.push(filePath);
+
+ //! find the base file path
+// var basefilePath = this._initBaseFilePath(filePath);
+
+ this._asyncRefTotalCount++;
+ this._asyncRefCount++;
+ var self = this;
+ var fun = function () {
+ self.addDataFromFile(filePath);
+ self._asyncRefCount--;
+ self._asyncCallBack(selector,target, (self._asyncRefTotalCount - self._asyncRefCount) / self._asyncRefTotalCount);
+ };
+ cc.director.getScheduler().schedule(fun, this, 0.1, false, 0, false, "armatrueDataHelper");
+ },
+
+ /**
+ * Removes config file from config file list.
+ * @param {String} configFile
+ */
+ removeConfigFile: function (configFile) {
+// cc.arrayRemoveObject(this._configFileList, configFile);
+ var locFileList = this._configFileList;
+ var len = locFileList.length;
+ var it = locFileList[len];
+ for (var i = 0;i " + ccs.CONST_ARMATURES + " > " + ccs.CONST_ARMATURE + "");
+ var armatureDataManager = ccs.armatureDataManager, i;
+ for (i = 0; i < armaturesXML.length; i++) {
+ var armatureData = this.decodeArmature(armaturesXML[i], dataInfo);
+ armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
+ }
+
+ /*
+ * Begin decode animation data from xml
+ */
+ var animationsXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_ANIMATIONS + " > " + ccs.CONST_ANIMATION + "");
+ for (i = 0; i < animationsXML.length; i++) {
+ var animationData = this.decodeAnimation(animationsXML[i], dataInfo);
+ armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
+ }
+
+ var texturesXML = skeleton.querySelectorAll(ccs.CONST_SKELETON + " > " + ccs.CONST_TEXTURE_ATLAS + " > " + ccs.CONST_SUB_TEXTURE + "");
+ for (i = 0; i < texturesXML.length; i++) {
+ var textureData = this.decodeTexture(texturesXML[i], dataInfo);
+ armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
+ }
+ },
+
+ /**
+ * decode xml armature data.
+ * @param {XMLDocument} armatureXML
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.ArmatureData}
+ */
+ decodeArmature: function (armatureXML, dataInfo) {
+ var armatureData = new ccs.ArmatureData();
+ armatureData.init();
+ armatureData.name = armatureXML.getAttribute(ccs.CONST_A_NAME);
+
+ var bonesXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE + " > " + ccs.CONST_BONE);
+
+ for (var i = 0; i < bonesXML.length; i++) {
+ /*
+ * If this bone have parent, then get the parent bone xml
+ */
+ var boneXML = bonesXML[i];
+ var parentName = boneXML.getAttribute(ccs.CONST_A_PARENT);
+ var parentXML = null;
+ if (parentName) {
+ //parentXML = armatureXML.querySelectorAll(ccs.CONST_ARMATURE+" > "+ccs.CONST_BONE);
+ for (var j = 0; j < bonesXML.length; j++) {
+ parentXML = bonesXML[j];
+ if (parentName == bonesXML[j].getAttribute(ccs.CONST_A_NAME)) {
+ //todo
+ break;
+ }
+ }
+ }
+ var boneData = this.decodeBone(boneXML, parentXML, dataInfo);
+ armatureData.addBoneData(boneData);
+ }
+ return armatureData;
+ },
+
+ /**
+ * decode json armature data.
+ * @param {Object} json
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.ArmatureData}
+ */
+ decodeArmatureFromJSON: function (json, dataInfo) {
+ var armatureData = new ccs.ArmatureData();
+ armatureData.init();
+
+ var name = json[ccs.CONST_A_NAME];
+ if (name) {
+ armatureData.name = name;
+ }
+
+ dataInfo.cocoStudioVersion = armatureData.dataVersion = json[ccs.CONST_VERSION] || 0.1;
+
+ var boneDataList = json[ccs.CONST_BONE_DATA];
+ for (var i = 0; i < boneDataList.length; i++) {
+ var boneData = this.decodeBoneFromJson(boneDataList[i], dataInfo);
+ armatureData.addBoneData(boneData);
+ }
+ return armatureData;
+ },
+
+ /**
+ * decode xml bone data.
+ * @param {XMLDocument} boneXML
+ * @param {XMLDocument} parentXML
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.BoneData}
+ */
+ decodeBone: function (boneXML, parentXML, dataInfo) {
+ var boneData = new ccs.BoneData();
+ boneData.init();
+
+ boneData.name = boneXML.getAttribute(ccs.CONST_A_NAME);
+ boneData.parentName = boneXML.getAttribute(ccs.CONST_A_PARENT) || "";
+
+ boneData.zOrder = parseInt(boneXML.getAttribute(ccs.CONST_A_Z)) || 0;
+
+ var displaysXML = boneXML.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_DISPLAY);
+ for (var i = 0; i < displaysXML.length; i++) {
+ var displayXML = displaysXML[i];
+ var displayData = this.decodeBoneDisplay(displayXML, dataInfo);
+ boneData.addDisplayData(displayData);
+ }
+ return boneData;
+ },
+
+ /**
+ * decode json bone data.
+ * @param {Object} json json bone data.
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.BoneData}
+ */
+ decodeBoneFromJson: function (json, dataInfo) {
+ var boneData = new ccs.BoneData();
+ boneData.init();
+
+ this.decodeNodeFromJson(boneData, json, dataInfo);
+
+ boneData.name = json[ccs.CONST_A_NAME] || "";
+
+ boneData.parentName = json[ccs.CONST_A_PARENT] || "";
+ var displayDataList = json[ccs.CONST_DISPLAY_DATA] || [];
+ for (var i = 0; i < displayDataList.length; i++) {
+ var locDisplayData = this.decodeBoneDisplayFromJson(displayDataList[i], dataInfo);
+ boneData.addDisplayData(locDisplayData);
+ }
+ return boneData;
+ },
+
+ /**
+ * decode xml display data of bone
+ * @param {XMLDocument} displayXML
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.DisplayData}
+ */
+ decodeBoneDisplay: function (displayXML, dataInfo) {
+ var isArmature = parseFloat(displayXML.getAttribute(ccs.CONST_A_IS_ARMATURE)) || 0;
+ var displayData = null;
+
+ if (isArmature === 1) {
+ displayData = new ccs.ArmatureDisplayData();
+ displayData.displayType = ccs.DISPLAY_TYPE_ARMATURE;
+ } else {
+ displayData = new ccs.SpriteDisplayData();
+ displayData.displayType = ccs.DISPLAY_TYPE_SPRITE;
+ }
+
+ var displayName = displayXML.getAttribute(ccs.CONST_A_NAME) || "";
+ if (displayName) {
+ displayData.displayName = displayName;
+ }
+ return displayData;
+ },
+
+ /**
+ * Decodes json display data of bone.
+ * @param {Object} json
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.DisplayData}
+ */
+ decodeBoneDisplayFromJson: function (json, dataInfo) {
+ var displayType = json[ccs.CONST_A_DISPLAY_TYPE] || ccs.DISPLAY_TYPE_SPRITE;
+ var displayData = null;
+
+ switch (displayType) {
+ case ccs.DISPLAY_TYPE_SPRITE:
+ displayData = new ccs.SpriteDisplayData();
+
+ var name = json[ccs.CONST_A_NAME];
+ if(name != null){
+ displayData.displayName = name;
+ }
+
+ var dicArray = json[ccs.CONST_SKIN_DATA] || [];
+ var dic = dicArray[0];
+ if (dic) {
+ var skinData = displayData.skinData;
+ skinData.x = dic[ccs.CONST_A_X] * this._positionReadScale;
+ skinData.y = dic[ccs.CONST_A_Y] * this._positionReadScale;
+ skinData.scaleX = dic[ccs.CONST_A_SCALE_X] == null ? 1 : dic[ccs.CONST_A_SCALE_X];
+ skinData.scaleY = dic[ccs.CONST_A_SCALE_Y] == null ? 1 : dic[ccs.CONST_A_SCALE_Y];
+ skinData.skewX = dic[ccs.CONST_A_SKEW_X] == null ? 1 : dic[ccs.CONST_A_SKEW_X];
+ skinData.skewY = dic[ccs.CONST_A_SKEW_Y] == null ? 1 : dic[ccs.CONST_A_SKEW_Y];
+
+ skinData.x *= dataInfo.contentScale;
+ skinData.y *= dataInfo.contentScale;
+ }
+ break;
+ case ccs.DISPLAY_TYPE_ARMATURE:
+ displayData = new ccs.ArmatureDisplayData();
+ var name = json[ccs.CONST_A_NAME];
+ if(name != null){
+ displayData.displayName = json[ccs.CONST_A_NAME];
+ }
+ break;
+ case ccs.DISPLAY_TYPE_PARTICLE:
+ displayData = new ccs.ParticleDisplayData();
+ var plist = json[ccs.CONST_A_PLIST];
+ if(plist != null){
+ if(dataInfo.asyncStruct){
+ displayData.displayName = dataInfo.asyncStruct.basefilePath + plist;
+ }else{
+ displayData.displayName = dataInfo.basefilePath + plist;
+ }
+ }
+ break;
+ default:
+ displayData = new ccs.SpriteDisplayData();
+ break;
+ }
+ displayData.displayType = displayType;
+ return displayData;
+ },
+
+ /**
+ * Decodes xml animation data.
+ * @param {XMLDocument} animationXML
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.AnimationData}
+ */
+ decodeAnimation: function (animationXML, dataInfo) {
+ var aniData = new ccs.AnimationData();
+ var name = animationXML.getAttribute(ccs.CONST_A_NAME);
+ var armatureData = ccs.armatureDataManager.getArmatureData(name);
+ aniData.name = name;
+
+ var movementsXML = animationXML.querySelectorAll(ccs.CONST_ANIMATION + " > " + ccs.CONST_MOVEMENT);
+ var movementXML = null;
+
+ for (var i = 0; i < movementsXML.length; i++) {
+ movementXML = movementsXML[i];
+ var movementData = this.decodeMovement(movementXML, armatureData, dataInfo);
+ aniData.addMovement(movementData);
+ }
+ return aniData;
+ },
+
+ /**
+ * Decodes animation json data.
+ * @param {Object} json
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.AnimationData}
+ */
+ decodeAnimationFromJson: function (json, dataInfo) {
+ var aniData = new ccs.AnimationData();
+ var name = json[ccs.CONST_A_NAME];
+ if(name){
+ aniData.name = json[ccs.CONST_A_NAME];
+ }
+
+ var movementDataList = json[ccs.CONST_MOVEMENT_DATA] || [];
+ for (var i = 0; i < movementDataList.length; i++) {
+ var locMovementData = this.decodeMovementFromJson(movementDataList[i], dataInfo);
+ aniData.addMovement(locMovementData);
+ }
+ return aniData;
+ },
+
+ /**
+ * Decodes xml movement data.
+ * @param {XMLDocument} movementXML
+ * @param {ccs.ArmatureData} armatureData
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.MovementData}
+ */
+ decodeMovement: function (movementXML, armatureData, dataInfo) {
+ var movementData = new ccs.MovementData();
+ movementData.name = movementXML.getAttribute(ccs.CONST_A_NAME);
+
+ var duration, durationTo, durationTween, loop, tweenEasing = 0;
+
+ duration = movementXML.getAttribute(ccs.CONST_A_DURATION);
+ movementData.duration = duration == null ? 0 : parseFloat(duration);
+
+ durationTo = movementXML.getAttribute(ccs.CONST_A_DURATION_TO);
+ movementData.durationTo = durationTo == null ? 0 : parseFloat(durationTo);
+
+ durationTween = movementXML.getAttribute(ccs.CONST_A_DURATION_TWEEN);
+ movementData.durationTween = durationTween == null ? 0 : parseFloat(durationTween);
+
+ loop = movementXML.getAttribute(ccs.CONST_A_LOOP);
+ movementData.loop = loop ? Boolean(parseFloat(loop)) : true;
+
+ var easing = movementXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
+ if (easing) {
+ if (easing != ccs.CONST_FL_NAN) {
+ tweenEasing = easing == null ? 0 : parseFloat(easing);
+ movementData.tweenEasing = tweenEasing === 2 ? ccs.TweenType.SINE_EASEINOUT : tweenEasing;
+ } else
+ movementData.tweenEasing = ccs.TweenType.LINEAR;
+ }
+
+ var movBonesXml = movementXML.querySelectorAll(ccs.CONST_MOVEMENT + " > " + ccs.CONST_BONE);
+ var movBoneXml = null;
+ for (var i = 0; i < movBonesXml.length; i++) {
+ movBoneXml = movBonesXml[i];
+ var boneName = movBoneXml.getAttribute(ccs.CONST_A_NAME);
+
+ if (movementData.getMovementBoneData(boneName))
+ continue;
+
+ var boneData = armatureData.getBoneData(boneName);
+ var parentName = boneData.parentName;
+
+ var parentXML = null;
+ if (parentName !== "") {
+ for (var j = 0; j < movBonesXml.length; j++) {
+ parentXML = movBonesXml[j];
+ if (parentName === parentXML.getAttribute(ccs.CONST_A_NAME))
+ break;
+ }
+ }
+ var moveBoneData = this.decodeMovementBone(movBoneXml, parentXML, boneData, dataInfo);
+ movementData.addMovementBoneData(moveBoneData);
+ }
+ return movementData;
+ },
+
+ /**
+ * Decodes json movement data.
+ * @param {Object} json
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.MovementData}
+ */
+ decodeMovementFromJson: function (json, dataInfo) {
+ var movementData = new ccs.MovementData();
+
+ movementData.loop = json[ccs.CONST_A_LOOP] == null ? false : json[ccs.CONST_A_LOOP];
+ movementData.durationTween = json[ccs.CONST_A_DURATION_TWEEN] || 0;
+ movementData.durationTo = json[ccs.CONST_A_DURATION_TO] || 0;
+ movementData.duration = json[ccs.CONST_A_DURATION] || 0;
+
+ if(json[ccs.CONST_A_DURATION] == null){
+ movementData.scale = 1;
+ }else{
+ movementData.scale = json[ccs.CONST_A_MOVEMENT_SCALE] == null ? 1 : json[ccs.CONST_A_MOVEMENT_SCALE];
+ }
+
+ movementData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] == null ? ccs.TweenType.LINEAR : json[ccs.CONST_A_TWEEN_EASING];
+ var name = json[ccs.CONST_A_NAME];
+ if(name)
+ movementData.name = name;
+
+ var movementBoneList = json[ccs.CONST_MOVEMENT_BONE_DATA] || [];
+ for (var i = 0; i < movementBoneList.length; i++) {
+ var locMovementBoneData = this.decodeMovementBoneFromJson(movementBoneList[i], dataInfo);
+ movementData.addMovementBoneData(locMovementBoneData);
+ }
+ return movementData;
+ },
+
+ /**
+ * Decodes xml data of bone's movement.
+ * @param {XMLDocument} movBoneXml
+ * @param {XMLDocument} parentXml
+ * @param {ccs.BoneData} boneData
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.MovementBoneData}
+ */
+ decodeMovementBone: function (movBoneXml, parentXml, boneData, dataInfo) {
+ var movBoneData = new ccs.MovementBoneData();
+ movBoneData.init();
+
+ var scale, delay;
+ if (movBoneXml) {
+ scale = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_SCALE)) || 0;
+ movBoneData.scale = scale;
+
+ delay = parseFloat(movBoneXml.getAttribute(ccs.CONST_A_MOVEMENT_DELAY)) || 0;
+ if (delay > 0)
+ delay -= 1;
+ movBoneData.delay = delay;
+ }
+
+ var length = 0, parentTotalDuration = 0,currentDuration = 0;
+ var parentFrameXML = null,parentXMLList = [];
+
+ /*
+ * get the parent frame xml list, we need get the origin data
+ */
+ if (parentXml != null) {
+ var parentFramesXML = parentXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
+ for (var i = 0; i < parentFramesXML.length; i++)
+ parentXMLList.push(parentFramesXML[i]);
+ length = parentXMLList.length;
+ }
+
+ movBoneData.name = movBoneXml.getAttribute(ccs.CONST_A_NAME);
+
+ var framesXML = movBoneXml.querySelectorAll(ccs.CONST_BONE + " > " + ccs.CONST_FRAME);
+
+ var j = 0, totalDuration = 0;
+ for (var ii = 0; ii < framesXML.length; ii++) {
+ var frameXML = framesXML[ii];
+ if (parentXml) {
+ /*
+ * in this loop we get the corresponding parent frame xml
+ */
+ while (j < length && (parentFrameXML ? (totalDuration < parentTotalDuration || totalDuration >= parentTotalDuration + currentDuration) : true)) {
+ parentFrameXML = parentXMLList[j];
+ parentTotalDuration += currentDuration;
+ currentDuration = parseFloat(parentFrameXML.getAttribute(ccs.CONST_A_DURATION));
+ j++;
+ }
+ }
+ var boneFrameData = this.decodeFrame(frameXML, parentFrameXML, boneData, dataInfo);
+ movBoneData.addFrameData(boneFrameData);
+ boneFrameData.frameID = totalDuration;
+ totalDuration += boneFrameData.duration;
+ movBoneData.duration = totalDuration;
+ }
+
+ //Change rotation range from (-180 -- 180) to (-infinity -- infinity)
+ var frames = movBoneData.frameList, pi = Math.PI;
+ for (var i = frames.length - 1; i >= 0; i--) {
+ if (i > 0) {
+ var difSkewX = frames[i].skewX - frames[i - 1].skewX;
+ var difSkewY = frames[i].skewY - frames[i - 1].skewY;
+
+ if (difSkewX < -pi || difSkewX > pi) {
+ frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
+ }
+
+ if (difSkewY < -pi || difSkewY > pi) {
+ frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
+ }
+ }
+ }
+
+ var frameData = new ccs.FrameData();
+ frameData.copy(movBoneData.frameList[movBoneData.frameList.length - 1]);
+ frameData.frameID = movBoneData.duration;
+ movBoneData.addFrameData(frameData);
+ return movBoneData;
+ },
+
+ /**
+ * Decodes json data of bone's movement.
+ * @param {Object} json
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.MovementBoneData}
+ */
+ decodeMovementBoneFromJson: function (json, dataInfo) {
+ var movementBoneData = new ccs.MovementBoneData();
+ movementBoneData.init();
+ movementBoneData.delay = json[ccs.CONST_A_MOVEMENT_DELAY] || 0;
+
+ var name = json[ccs.CONST_A_NAME];
+ if(name)
+ movementBoneData.name = name;
+
+ var framesData = json[ccs.CONST_FRAME_DATA] || [];
+ var length = framesData.length;
+ for (var i = 0; i < length; i++) {
+ var dic = json[ccs.CONST_FRAME_DATA][i];
+ var frameData = this.decodeFrameFromJson(dic, dataInfo);
+ movementBoneData.addFrameData(frameData);
+
+ if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED){
+ frameData.frameID = movementBoneData.duration;
+ movementBoneData.duration += frameData.duration;
+ }
+ }
+
+ if (dataInfo.cocoStudioVersion < ccs.VERSION_CHANGE_ROTATION_RANGE) {
+ //! Change rotation range from (-180 -- 180) to (-infinity -- infinity)
+ var frames = movementBoneData.frameList;
+ var pi = Math.PI;
+ for (var i = frames.length - 1; i >= 0; i--) {
+ if (i > 0) {
+ var difSkewX = frames[i].skewX - frames[i - 1].skewX;
+ var difSkewY = frames[i].skewY - frames[i - 1].skewY;
+
+ if (difSkewX < -pi || difSkewX > pi) {
+ frames[i - 1].skewX = difSkewX < 0 ? frames[i - 1].skewX - 2 * pi : frames[i - 1].skewX + 2 * pi;
+ }
+
+ if (difSkewY < -pi || difSkewY > pi) {
+ frames[i - 1].skewY = difSkewY < 0 ? frames[i - 1].skewY - 2 * pi : frames[i - 1].skewY + 2 * pi;
+ }
+ }
+ }
+ }
+
+ if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED) {
+ if (movementBoneData.frameList.length > 0) {
+ var frameData = new ccs.FrameData();
+ frameData.copy(movementBoneData.frameList[movementBoneData.frameList.length - 1]);
+ movementBoneData.addFrameData(frameData);
+ frameData.frameID = movementBoneData.duration;
+ }
+ }
+ return movementBoneData;
+ },
+
+ /**
+ * Decodes xml data of frame.
+ * @param {XMLDocument} frameXML
+ * @param {XMLDocument} parentFrameXml
+ * @param {ccs.BoneData} boneData
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.FrameData}
+ */
+ decodeFrame: function (frameXML, parentFrameXml, boneData, dataInfo) {
+ var x = 0, y = 0, scale_x = 0, scale_y = 0, skew_x = 0, skew_y = 0, tweenRotate = 0;
+ var duration = 0, displayIndex = 0, zOrder = 0, tweenEasing = 0, blendType = 0;
+
+ var frameData = new ccs.FrameData();
+ frameData.strMovement = frameXML.getAttribute(ccs.CONST_A_MOVEMENT) || "";
+ frameData.movement = frameData.strMovement;
+ frameData.strEvent = frameXML.getAttribute(ccs.CONST_A_EVENT) || "";
+ frameData.event = frameData.strEvent;
+ frameData.strSound = frameXML.getAttribute(ccs.CONST_A_SOUND) || "";
+ frameData.sound = frameData.strSound;
+ frameData.strSoundEffect = frameXML.getAttribute(ccs.CONST_A_SOUND_EFFECT) || "";
+ frameData.soundEffect = frameData.strSoundEffect;
+
+ var isTween = frameXML.getAttribute(ccs.CONST_A_TWEEN_FRAME);
+ frameData.isTween = !(isTween !== undefined && (isTween === "false" || isTween === "0"));
+
+ if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
+ x = frameXML.getAttribute(ccs.CONST_A_COCOS2DX_X);
+ if(x){
+ frameData.x = parseFloat(x);
+ frameData.x *= this._positionReadScale;
+ }
+ y = frameXML.getAttribute(ccs.CONST_A_COCOS2DX_Y);
+ if(y){
+ frameData.y = -parseFloat(y);
+ frameData.y *= this._positionReadScale;
+ }
+ } else {
+ x = frameXML.getAttribute(ccs.CONST_A_X);
+ if(x) {
+ frameData.x = parseFloat(x);
+ frameData.x *= this._positionReadScale;
+ }
+ y = frameXML.getAttribute(ccs.CONST_A_Y);
+ if(y) {
+ frameData.y = -parseFloat(y);
+ frameData.y *= this._positionReadScale;
+ }
+ }
+
+ scale_x = frameXML.getAttribute(ccs.CONST_A_SCALE_X);
+ if( scale_x != null )
+ frameData.scaleX = parseFloat(scale_x);
+ scale_y = frameXML.getAttribute(ccs.CONST_A_SCALE_Y);
+ if( scale_y != null )
+ frameData.scaleY = parseFloat(scale_y);
+ skew_x = frameXML.getAttribute(ccs.CONST_A_SKEW_X);
+ if( skew_x != null )
+ frameData.skewX = cc.degreesToRadians(parseFloat(skew_x));
+ skew_y = frameXML.getAttribute(ccs.CONST_A_SKEW_Y);
+ if( skew_y != null )
+ frameData.skewY = cc.degreesToRadians(-parseFloat(skew_y));
+
+ duration = frameXML.getAttribute(ccs.CONST_A_DURATION);
+ if( duration != null )
+ frameData.duration = parseFloat(duration);
+ displayIndex = frameXML.getAttribute(ccs.CONST_A_DISPLAY_INDEX);
+ if( displayIndex != null )
+ frameData.displayIndex = parseFloat(displayIndex);
+ zOrder = frameXML.getAttribute(ccs.CONST_A_Z);
+ if( zOrder != null )
+ frameData.zOrder = parseInt(zOrder);
+ tweenRotate = frameXML.getAttribute(ccs.CONST_A_TWEEN_ROTATE);
+ if( tweenRotate != null )
+ frameData.tweenRotate = parseFloat(tweenRotate);
+
+ blendType = frameXML.getAttribute(ccs.CONST_A_BLEND_TYPE);
+ if ( blendType != null ) {
+ var blendFunc = frameData.blendFunc;
+ switch (blendType) {
+ case ccs.BLEND_TYPE_NORMAL:
+ blendFunc.src = cc.BLEND_SRC;
+ blendFunc.dst = cc.BLEND_DST;
+ break;
+ case ccs.BLEND_TYPE_ADD:
+ blendFunc.src = cc.SRC_ALPHA;
+ blendFunc.dst = cc.ONE;
+ break;
+ case ccs.BLEND_TYPE_MULTIPLY:
+ blendFunc.src = cc.DST_COLOR;
+ blendFunc.dst = cc.ONE_MINUS_SRC_ALPHA;
+ break;
+ case ccs.BLEND_TYPE_SCREEN:
+ blendFunc.src = cc.ONE;
+ blendFunc.dst = cc.ONE_MINUS_DST_COLOR;
+ break;
+ default:
+ frameData.blendFunc.src = cc.BLEND_SRC;
+ frameData.blendFunc.dst = cc.BLEND_DST;
+ break;
+ }
+ }
+
+ var colorTransformXML = frameXML.querySelectorAll(ccs.CONST_FRAME + " > " + ccs.CONST_A_COLOR_TRANSFORM);
+ if (colorTransformXML && colorTransformXML.length > 0) {
+ colorTransformXML = colorTransformXML[0];
+ var alpha, red, green, blue;
+ var alphaOffset, redOffset, greenOffset, blueOffset;
+
+ alpha = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA)) || 0;
+ red = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED)) || 0;
+ green = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN)) || 0;
+ blue = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE)) || 0;
+
+ alphaOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_ALPHA_OFFSET)) || 0;
+ redOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_RED_OFFSET)) || 0;
+ greenOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_GREEN_OFFSET)) || 0;
+ blueOffset = parseFloat(colorTransformXML.getAttribute(ccs.CONST_A_BLUE_OFFSET)) || 0;
+
+ frameData.a = 2.55 * alphaOffset + alpha;
+ frameData.r = 2.55 * redOffset + red;
+ frameData.g = 2.55 * greenOffset + green;
+ frameData.b = 2.55 * blueOffset + blue;
+
+ frameData.isUseColorInfo = true;
+ }
+
+ var _easing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
+ if(_easing != null) {
+ if(_easing != ccs.CONST_FL_NAN){
+ tweenEasing = frameXML.getAttribute(ccs.CONST_A_TWEEN_EASING);
+ if( tweenEasing )
+ frameData.tweenEasing = (tweenEasing === 2) ? ccs.TweenType.SINE_EASEINOUT : tweenEasing;
+ } else
+ frameData.tweenEasing = ccs.TweenType.LINEAR;
+ }
+
+ if (parentFrameXml) {
+ //* recalculate frame data from parent frame data, use for translate matrix
+ var helpNode = new ccs.BaseData();
+ if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
+ helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_X));
+ helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_COCOS2DX_Y));
+ } else {
+ helpNode.x = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_X));
+ helpNode.y = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_Y));
+ }
+ helpNode.skewX = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_X));
+ helpNode.skewY = parseFloat(parentFrameXml.getAttribute(ccs.CONST_A_SKEW_Y));
+
+ helpNode.y = -helpNode.y;
+ helpNode.skewX = cc.degreesToRadians(helpNode.skewX);
+ helpNode.skewY = cc.degreesToRadians(-helpNode.skewY);
+ ccs.TransformHelp.transformFromParent(frameData, helpNode);
+ }
+ return frameData;
+ },
+
+ /**
+ * Decodes json data of frame.
+ * @param {Object} json
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.FrameData}
+ */
+ decodeFrameFromJson: function (json, dataInfo) {
+ var frameData = new ccs.FrameData();
+
+ this.decodeNodeFromJson(frameData, json, dataInfo);
+
+ frameData.tweenEasing = json[ccs.CONST_A_TWEEN_EASING] || ccs.TweenType.LINEAR;
+ frameData.displayIndex = json[ccs.CONST_A_DISPLAY_INDEX];
+ var bd_src = json[ccs.CONST_A_BLEND_SRC] == null ? cc.BLEND_SRC : json[ccs.CONST_A_BLEND_SRC];
+ var bd_dst = json[ccs.CONST_A_BLEND_DST] == null ? cc.BLEND_DST : json[ccs.CONST_A_BLEND_DST];
+ frameData.blendFunc.src = bd_src;
+ frameData.blendFunc.dst = bd_dst;
+ frameData.isTween = json[ccs.CONST_A_TWEEN_FRAME] == null ? true : json[ccs.CONST_A_TWEEN_FRAME];
+
+ var event = json[ccs.CONST_A_EVENT];
+ if(event != null){
+ frameData.strEvent = event;
+ frameData.event = event;
+ }
+
+ if (dataInfo.cocoStudioVersion < ccs.CONST_VERSION_COMBINED)
+ frameData.duration = json[ccs.CONST_A_DURATION] == null ? 1 : json[ccs.CONST_A_DURATION];
+ else
+ frameData.frameID = json[ccs.CONST_A_FRAME_INDEX];
+
+ var twEPs = json[ccs.CONST_A_EASING_PARAM] || [];
+ for (var i = 0; i < twEPs.length; i++) {
+ frameData.easingParams[i] = twEPs[i];
+ }
+
+ return frameData;
+ },
+
+ /**
+ * Decodes xml data of texture
+ * @param {XMLDocument} textureXML
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.TextureData}
+ */
+ decodeTexture: function (textureXML, dataInfo) {
+ var textureData = new ccs.TextureData();
+ textureData.init();
+
+ if (textureXML.getAttribute(ccs.CONST_A_NAME)) {
+ textureData.name = textureXML.getAttribute(ccs.CONST_A_NAME);
+ }
+
+ var px, py;
+
+ if (dataInfo.flashToolVersion >= ccs.CONST_VERSION_2_0) {
+ px = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_X)) || 0;
+ py = parseFloat(textureXML.getAttribute(ccs.CONST_A_COCOS2D_PIVOT_Y)) || 0;
+ } else {
+ px = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_X)) || 0;
+ py = parseFloat(textureXML.getAttribute(ccs.CONST_A_PIVOT_Y)) || 0;
+ }
+
+ var width = parseFloat(textureXML.getAttribute(ccs.CONST_A_WIDTH)) || 0;
+ var height = parseFloat(textureXML.getAttribute(ccs.CONST_A_HEIGHT)) || 0;
+
+ var anchorPointX = px / width;
+ var anchorPointY = (height - py) / height;
+
+ textureData.pivotX = anchorPointX;
+ textureData.pivotY = anchorPointY;
+
+ var contoursXML = textureXML.querySelectorAll(ccs.CONST_SUB_TEXTURE + " > " + ccs.CONST_CONTOUR);
+ for (var i = 0; i < contoursXML.length; i++) {
+ textureData.addContourData(this.decodeContour(contoursXML[i], dataInfo));
+ }
+ return textureData;
+ },
+
+ /**
+ * Decodes json data of Texture.
+ * @param json
+ * @returns {ccs.TextureData}
+ */
+ decodeTextureFromJson: function (json) {
+ var textureData = new ccs.TextureData();
+ textureData.init();
+
+ var name = json[ccs.CONST_A_NAME];
+ if(name != null)
+ textureData.name = name;
+
+ textureData.width = json[ccs.CONST_A_WIDTH] || 0;
+ textureData.height = json[ccs.CONST_A_HEIGHT] || 0;
+ textureData.pivotX = json[ccs.CONST_A_PIVOT_X] || 0;
+ textureData.pivotY = json[ccs.CONST_A_PIVOT_Y] || 0;
+
+ var contourDataList = json[ccs.CONST_CONTOUR_DATA] || [];
+ for (var i = 0; i < contourDataList.length; i++) {
+ textureData.contourDataList.push(this.decodeContourFromJson(contourDataList[i]));
+ }
+ return textureData;
+ },
+
+ /**
+ * Decodes xml data of contour.
+ * @param {XMLDocument} contourXML
+ * @param {ccs.DataInfo} dataInfo
+ * @returns {ccs.ContourData}
+ */
+ decodeContour: function (contourXML, dataInfo) {
+ var contourData = new ccs.ContourData();
+ contourData.init();
+
+ var vertexDatasXML = contourXML.querySelectorAll(ccs.CONST_CONTOUR + " > " + ccs.CONST_CONTOUR_VERTEX);
+ var vertexDataXML;
+ for (var i = 0; i < vertexDatasXML.length; i++) {
+ vertexDataXML = vertexDatasXML[i];
+ var vertex = cc.p(0, 0);
+ vertex.x = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_X)) || 0;
+ vertex.y = parseFloat(vertexDataXML.getAttribute(ccs.CONST_A_Y)) || 0;
+
+ vertex.y = - vertex.y;
+ contourData.vertexList.push(vertex);
+ }
+ return contourData;
+ },
+
+ /**
+ * Decodes json data of contour.
+ * @param {Object} json
+ * @returns {ccs.ContourData}
+ */
+ decodeContourFromJson: function (json) {
+ var contourData = new ccs.ContourData();
+ contourData.init();
+
+ var vertexPointList = json[ccs.CONST_VERTEX_POINT] || [];
+ var len = vertexPointList.length;
+ for (var i = 0; i < len; i++) {
+ var dic = vertexPointList[i];
+ var vertex = cc.p(0, 0);
+ vertex.x = dic[ccs.CONST_A_X] || 0;
+ vertex.y = dic[ccs.CONST_A_Y] || 0;
+ contourData.vertexList.push(vertex);
+ }
+ return contourData;
+ },
+
+ /**
+ * Adds json armature data to armature data manager.
+ * @param {Object} dic json armature data
+ * @param {ccs.DataInfo} dataInfo
+ */
+ addDataFromJsonCache: function (dic, dataInfo) {
+ dataInfo.contentScale = dic[ccs.CONST_CONTENT_SCALE] == null ? 1 : dic[ccs.CONST_CONTENT_SCALE];
+
+ // Decode armatures
+ var armatureDataArr = dic[ccs.CONST_ARMATURE_DATA] || [], i;
+ var armatureData;
+ for (i = 0; i < armatureDataArr.length; i++) {
+ armatureData = this.decodeArmatureFromJSON(armatureDataArr[i], dataInfo);
+ ccs.armatureDataManager.addArmatureData(armatureData.name, armatureData, dataInfo.filename);
+ }
+
+ // Decode animations
+ var animationDataArr = dic[ccs.CONST_ANIMATION_DATA] || [];
+ var animationData;
+ for (i = 0; i < animationDataArr.length; i++) {
+ animationData = this.decodeAnimationFromJson(animationDataArr[i], dataInfo);
+ ccs.armatureDataManager.addAnimationData(animationData.name, animationData, dataInfo.filename);
+ }
+
+ // Decode textures
+ var textureDataArr = dic[ccs.CONST_TEXTURE_DATA] || [];
+ var textureData;
+ for (i = 0; i < textureDataArr.length; i++) {
+ textureData = this.decodeTextureFromJson(textureDataArr[i], dataInfo);
+ ccs.armatureDataManager.addTextureData(textureData.name, textureData, dataInfo.filename);
+ }
+
+ // Auto load sprite file
+ var autoLoad = dataInfo.asyncStruct == null ? ccs.armatureDataManager.isAutoLoadSpriteFile() : dataInfo.asyncStruct.autoLoadSpriteFile;
+// if (isLoadSpriteFrame) {
+ if (autoLoad) {
+ var configFiles = dic[ccs.CONST_CONFIG_FILE_PATH] || [];
+ var locFilePath, locPos, locPlistPath, locImagePath;
+ for (i = 0; i < configFiles.length; i++) {
+ locFilePath = configFiles[i];
+ locPos = locFilePath.lastIndexOf(".");
+ locFilePath = locFilePath.substring(0, locPos);
+ locPlistPath = dataInfo.basefilePath + locFilePath + ".plist";
+ locImagePath = dataInfo.basefilePath + locFilePath + ".png";
+ ccs.armatureDataManager.addSpriteFrameFromFile(locPlistPath, locImagePath, dataInfo.filename);
+ }
+ }
+
+ armatureData = null;
+ animationData = null;
+ },
+
+ /**
+ * Decodes json data of node.
+ * @param node
+ * @param json
+ * @param dataInfo
+ */
+ decodeNodeFromJson: function (node, json, dataInfo) {
+ node.x = json[ccs.CONST_A_X] * this._positionReadScale;
+ node.y = json[ccs.CONST_A_Y] * this._positionReadScale;
+
+ node.x *= dataInfo.contentScale;
+ node.y *= dataInfo.contentScale;
+
+ node.zOrder = json[ccs.CONST_A_Z];
+
+ node.skewX = json[ccs.CONST_A_SKEW_X] || 0;
+ node.skewY = json[ccs.CONST_A_SKEW_Y] || 0;
+ node.scaleX = json[ccs.CONST_A_SCALE_X] == null ? 1 : json[ccs.CONST_A_SCALE_X];
+ node.scaleY = json[ccs.CONST_A_SCALE_Y] == null ? 1 : json[ccs.CONST_A_SCALE_Y];
+
+ var colorDic;
+ if (dataInfo.cocoStudioVersion < ccs.VERSION_COLOR_READING) {
+ colorDic = json[0];
+ if (colorDic){
+ node.a = colorDic[ccs.CONST_A_ALPHA] == null ? 255 : colorDic[ccs.CONST_A_ALPHA];
+ node.r = colorDic[ccs.CONST_A_RED] == null ? 255 : colorDic[ccs.CONST_A_RED];
+ node.g = colorDic[ccs.CONST_A_GREEN] == null ? 255 : colorDic[ccs.CONST_A_GREEN];
+ node.b = colorDic[ccs.CONST_A_BLUE] == null ? 255 : colorDic[ccs.CONST_A_BLUE];
+ node.isUseColorInfo = true;
+ }
+ } else {
+ colorDic = json[ccs.CONST_COLOR_INFO] || null;
+ if (colorDic){
+ node.a = colorDic[ccs.CONST_A_ALPHA] == null ? 255 : colorDic[ccs.CONST_A_ALPHA];
+ node.r = colorDic[ccs.CONST_A_RED] == null ? 255 : colorDic[ccs.CONST_A_RED];
+ node.g = colorDic[ccs.CONST_A_GREEN] == null ? 255 : colorDic[ccs.CONST_A_GREEN];
+ node.b = colorDic[ccs.CONST_A_BLUE] == null ? 255 : colorDic[ccs.CONST_A_BLUE];
+ node.isUseColorInfo = true;
+ }
+ }
+ },
+
+ clear: function () {
+ this._configFileList = [];
+ this._asyncRefCount = 0;
+ this._asyncRefTotalCount = 0;
+ },
+
+ _asyncCallBack: function (selector, target, percent) {
+ if(selector && cc.isFunction(selector))
+ selector.call(target, percent);
+ if(target && selector && typeof selector === 'string')
+ target[selector](percent);
+ },
+ /**
+ * find the base file path
+ * @param filePath
+ * @returns {String}
+ * @private
+ */
+ _initBaseFilePath: function (filePath) {
+ var path = filePath;
+ var pos = path.lastIndexOf("/");
+ if (pos > -1)
+ path = path.substr(0, pos + 1);
+ else
+ path = "";
+ return path;
+ },
+
+ /**
+ * Adds xml armature data to armature data manager.
+ * @param {XMLDocument} xml
+ * @param {ccs.DataInfo} dataInfo
+ */
+ addDataFromXML: function (xml, dataInfo) {
+ /*
+ * Need to get the full path of the xml file, or the Tiny XML can't find the xml at IOS
+ */
+ var xmlStr = cc.loader.getRes(xml);
+ if (!xmlStr) throw new Error("Please load the resource first : " + xml);
+ var skeletonXML = cc.saxParser.parse(xmlStr);
+ var skeleton = skeletonXML.documentElement;
+ if (skeleton)
+ this.addDataFromCache(skeleton, dataInfo);
+ },
+
+ /**
+ * Adds json armature data to armature data manager.
+ * @param {String} filePath
+ * @param {ccs.DataInfo} dataInfo
+ */
+ addDataFromJson: function (filePath, dataInfo) {
+ var fileContent = cc.loader.getRes(filePath);
+ this.addDataFromJsonCache(fileContent, dataInfo);
+ }
+};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/utils/CCSpriteFrameCacheHelper.js b/extensions/cocostudio/armature/utils/CCSpriteFrameCacheHelper.js
similarity index 65%
rename from extensions/CocoStudio/Armature/utils/CCSpriteFrameCacheHelper.js
rename to extensions/cocostudio/armature/utils/CCSpriteFrameCacheHelper.js
index 1e6e52d011..a0496e96a7 100644
--- a/extensions/CocoStudio/Armature/utils/CCSpriteFrameCacheHelper.js
+++ b/extensions/cocostudio/armature/utils/CCSpriteFrameCacheHelper.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,35 +23,46 @@
THE SOFTWARE.
****************************************************************************/
-cc.SpriteFrameCacheHelper = cc.Class.extend({
- _textureAtlasDic:null,
+/**
+ * ccs.spriteFrameCacheHelper is a singleton object, it's a sprite frame cache helper
+ * @class
+ * @name ccs.spriteFrameCacheHelper
+ */
+ccs.spriteFrameCacheHelper = /** @lends ccs.spriteFrameCacheHelper# */ {
+ _textureAtlasDic:{},
_imagePaths:[],
- ctor:function () {
- this._textureAtlasDic = {};
- this._imagePaths = [];
- },
+
+ /**
+ * Adds sprite frame from file
+ * @param plistPath
+ * @param imagePath
+ */
addSpriteFrameFromFile:function (plistPath, imagePath) {
- cc.SpriteFrameCache.getInstance().addSpriteFrames(plistPath, imagePath);
+ cc.spriteFrameCache.addSpriteFrames(plistPath, imagePath);
},
- getTexureAtlasWithTexture:function (texture) {
+ /**
+ * Returns texture atlas with texture.
+ * @param texture
+ * @returns {*}
+ */
+ getTextureAtlasWithTexture:function (texture) {
//todo
return null;
var textureName = texture.getName();
var atlas = this._textureAtlasDic[textureName];
if (atlas == null) {
- atlas = cc.TextureAtlas.createWithTexture(texture, 20);
+ atlas = new cc.TextureAtlas(texture, 20);
this._textureAtlasDic[textureName] = atlas;
}
return atlas;
- }
-});
-cc.SpriteFrameCacheHelper.getInstance = function () {
- if (!this._instance) {
- this._instance = new cc.SpriteFrameCacheHelper();
- }
- return this._instance;
-};
-cc.SpriteFrameCacheHelper.purge = function () {
- this._instance = null;
+ },
+
+ /**
+ * Clear the sprite frame cache's data.
+ */
+ clear: function () {
+ this._textureAtlasDic = {};
+ this._imagePaths = [];
+ }
};
\ No newline at end of file
diff --git a/extensions/cocostudio/armature/utils/CCTransformHelp.js b/extensions/cocostudio/armature/utils/CCTransformHelp.js
new file mode 100644
index 0000000000..0d6228d5cd
--- /dev/null
+++ b/extensions/cocostudio/armature/utils/CCTransformHelp.js
@@ -0,0 +1,183 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * use to calculate the matrix of node from parent node
+ * @class ccs.TransformHelp
+ * @extend ccs.Class
+ */
+ccs.TransformHelp = ccs.TransformHelp || ccs.Class.extend({});
+
+ccs.TransformHelp.helpMatrix1 = cc.affineTransformMake(1, 0, 0, 1, 0, 0);
+ccs.TransformHelp.helpMatrix2 = cc.affineTransformMake(1, 0, 0, 1, 0, 0);
+ccs.TransformHelp.helpPoint1 = cc.p(0, 0);
+ccs.TransformHelp.helpPoint2 = cc.p(0, 0);
+ccs.TransformHelp.helpParentNode = {};
+
+/**
+ * Calculate a BaseData's transform matrix from parent node.
+ * @function
+ * @static
+ * @param {ccs.BaseData} bone
+ * Constructor
+ */
+ccs.TransformHelp.transformFromParent = function (bone, parentNode) {
+ this.nodeToMatrix(bone, this.helpMatrix1);
+ this.nodeToMatrix(parentNode, this.helpMatrix2);
+
+ this.helpMatrix2 = cc.affineTransformInvert(this.helpMatrix2);
+ this.helpMatrix1 = cc.affineTransformConcat(this.helpMatrix1, this.helpMatrix2);
+
+ this.matrixToNode(this.helpMatrix1, bone);
+};
+
+ccs.TransformHelp.transformToParent = function(node, parentNode){
+ this.nodeToMatrix(node, this.helpMatrix1);
+ this.nodeToMatrix(parentNode, this.helpMatrix2);
+
+ this.helpMatrix1 = cc.affineTransformConcat(this.helpMatrix1, this.helpMatrix2);
+
+ this.matrixToNode(this.helpMatrix1, node);
+};
+
+ccs.TransformHelp.transformFromParentWithoutScale = function(node, parentNode){
+// this.helpParentNode.copy(&parentNode);
+
+ for(var p in parentNode){
+ this.helpParentNode[p] = parentNode[p];
+ }
+ this.helpParentNode.scaleX = 1;
+ this.helpParentNode.scaleY = 1;
+
+ this.nodeToMatrix(node, this.helpMatrix1);
+ this.nodeToMatrix(this.helpParentNode, this.helpMatrix2);
+
+ this.helpMatrix2 = cc.affineTransformInvert(this.helpMatrix2);
+ this.helpMatrix1 = cc.affineTransformConcat(this.helpMatrix1, this.helpMatrix2);
+
+ this.matrixToNode(this.helpMatrix1, node);
+};
+
+ccs.TransformHelp.transformToParentWithoutScale = function(node, parentNode){
+ for(var p in parentNode){
+ this.helpParentNode[p] = parentNode[p];
+ }
+ this.helpParentNode.scaleX = 1;
+ this.helpParentNode.scaleY = 1;
+
+ this.nodeToMatrix(node, this.helpMatrix1);
+ this.nodeToMatrix(this.helpParentNode, this.helpMatrix2);
+
+ this.helpMatrix1 = cc.affineTransformConcat(this.helpMatrix1, this.helpMatrix2);
+
+ this.matrixToNode(this.helpMatrix1, node);
+
+};
+
+/**
+ * @function
+ * @static
+ * @param {ccs.BaseData} node
+ * @param {cc.AffineTransform} matrix
+ */
+ccs.TransformHelp.nodeToMatrix = function (node, matrix) {
+ if (node.skewX === -node.skewY) {
+ var sine = Math.sin(node.skewX);
+ var cosine = Math.cos(node.skewX);
+ matrix.a = node.scaleX * cosine;
+ matrix.b = node.scaleX * -sine;
+ matrix.c = node.scaleY * sine;
+ matrix.d = node.scaleY * cosine;
+ } else {
+ matrix.a = node.scaleX * Math.cos(node.skewY);
+ matrix.b = node.scaleX * Math.sin(node.skewY);
+ matrix.c = node.scaleY * Math.sin(node.skewX);
+ matrix.d = node.scaleY * Math.cos(node.skewX);
+ }
+ matrix.tx = node.x;
+ matrix.ty = node.y;
+};
+
+/**
+ * @function
+ * @static
+ * @param {cc.AffineTransform} matrix
+ * @param {ccs.BaseData} node
+ */
+ccs.TransformHelp.matrixToNode = function (matrix, node) {
+ /*
+ * In as3 language, there is a function called "deltaTransformPoint", it calculate a point used give Transform
+ * but not used the tx, ty value. we simulate the function here
+ */
+ this.helpPoint1.x = 0;
+ this.helpPoint1.y = 1;
+ this.helpPoint1 = cc.pointApplyAffineTransform(this.helpPoint1, matrix);
+ this.helpPoint1.x -= matrix.tx;
+ this.helpPoint1.y -= matrix.ty;
+
+ this.helpPoint2.x = 1;
+ this.helpPoint2.y = 0;
+ this.helpPoint2 = cc.pointApplyAffineTransform(this.helpPoint2, matrix);
+ this.helpPoint2.x -= matrix.tx;
+ this.helpPoint2.y -= matrix.ty;
+
+ node.skewX = -(Math.atan2(this.helpPoint1.y, this.helpPoint1.x) - 1.5707964); //todo
+ //node.skewX = -Math.atan2(this.helpPoint2.y, this.helpPoint2.x);
+ node.skewY = Math.atan2(this.helpPoint2.y, this.helpPoint2.x);
+ node.scaleX = Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b);
+ node.scaleY = Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d);
+ node.x = matrix.tx;
+ node.y = matrix.ty;
+};
+
+/**
+ * @function
+ * @static
+ * @param {ccs.BaseData} target
+ * @param {ccs.BaseData} source
+ */
+ccs.TransformHelp.nodeConcat = function (target, source) {
+ target.x += source.x;
+ target.y += source.y;
+ target.skewX += source.skewX;
+ target.skewY += source.skewY;
+ target.scaleX += source.scaleX;
+ target.scaleY += source.scaleY;
+};
+
+/**
+ * @function
+ * @static
+ * @param {ccs.BaseData} target
+ * @param {ccs.BaseData} source
+ */
+ccs.TransformHelp.nodeSub = function (target, source) {
+ target.x -= source.x;
+ target.y -= source.y;
+ target.skewX -= source.skewX;
+ target.skewY -= source.skewY;
+ target.scaleX -= source.scaleX;
+ target.scaleY -= source.scaleY;
+};
\ No newline at end of file
diff --git a/extensions/cocostudio/armature/utils/CCTweenFunction.js b/extensions/cocostudio/armature/utils/CCTweenFunction.js
new file mode 100644
index 0000000000..7ced7fad96
--- /dev/null
+++ b/extensions/cocostudio/armature/utils/CCTweenFunction.js
@@ -0,0 +1,501 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * TweenType
+ * @type Object
+ */
+ccs.TweenType = {
+ CUSTOM_EASING: -1,
+ LINEAR: 0,
+
+ SINE_EASEIN: 1,
+ SINE_EASEOUT: 2,
+ SINE_EASEINOUT: 3,
+
+ QUAD_EASEIN: 4,
+ QUAD_EASEOUT: 5,
+ QUAD_EASEINOUT: 6,
+
+ CUBIC_EASEIN: 7,
+ CUBIC_EASEOUT: 8,
+ CUBIC_EASEINOUT: 9,
+
+ QUART_EASEIN: 10,
+ QUART_EASEOUT: 11,
+ QUART_EASEINOUT: 12,
+
+ QUINT_EASEIN: 13,
+ QUINT_EASEOUT: 14,
+ QUINT_EASEINOUT: 15,
+
+ EXPO_EASEIN: 16,
+ EXPO_EASEOUT: 17,
+ EXPO_EASEINOUT: 18,
+
+ CIRC_EASEIN: 19,
+ CIRC_EASEOUT: 20,
+ CIRC_EASEINOUT: 21,
+
+ ELASTIC_EASEIN: 22,
+ ELASTIC_EASEOUT: 23,
+ ELASTIC_EASEINOUT: 24,
+
+ BACK_EASEIN: 25,
+ BACK_EASEOUT: 26,
+ BACK_EASEINOUT: 27,
+
+ BOUNCE_EASEIN: 28,
+ BOUNCE_EASEOUT: 29,
+ BOUNCE_EASEINOUT: 30,
+
+ TWEEN_EASING_MAX: 10000
+};
+
+ccs.TweenFunction = ccs.TweenFunction || ccs.Class.extend({});
+
+ccs.DOUBLE_PI = ccs.M_PI_X_2 = Math.PI * 2;
+ccs.HALF_PI = ccs.M_PI_2 = Math.PI / 2;
+ccs.M_PI = Math.PI;
+
+ccs.TweenFunction.tweenTo = function (time, type, easingParam) {
+ var delta = 0;
+
+ switch (type) {
+ case ccs.TweenType.CUSTOM_EASING:
+ delta = this.customEase(time, easingParam);
+ break;
+ case ccs.TweenType.LINEAR:
+ delta = this.linear(time);
+ break;
+ case ccs.TweenType.SINE_EASEIN:
+ delta = this.sineEaseIn(time);
+ break;
+ case ccs.TweenType.SINE_EASEOUT:
+ delta = this.sineEaseOut(time);
+ break;
+ case ccs.TweenType.SINE_EASEINOUT:
+ delta = this.sineEaseInOut(time);
+ break;
+
+ case ccs.TweenType.QUAD_EASEIN:
+ delta = this.quadEaseIn(time);
+ break;
+ case ccs.TweenType.QUAD_EASEOUT:
+ delta = this.quadEaseOut(time);
+ break;
+ case ccs.TweenType.QUAD_EASEINOUT:
+ delta = this.quadEaseInOut(time);
+ break;
+
+ case ccs.TweenType.CUBIC_EASEIN:
+ delta = this.cubicEaseIn(time);
+ break;
+ case ccs.TweenType.CUBIC_EASEOUT:
+ delta = this.cubicEaseOut(time);
+ break;
+ case ccs.TweenType.CUBIC_EASEINOUT:
+ delta = this.cubicEaseInOut(time);
+ break;
+
+ case ccs.TweenType.QUART_EASEIN:
+ delta = this.quartEaseIn(time);
+ break;
+ case ccs.TweenType.QUART_EASEOUT:
+ delta = this.quartEaseOut(time);
+ break;
+ case ccs.TweenType.QUART_EASEINOUT:
+ delta = this.quartEaseInOut(time);
+ break;
+
+ case ccs.TweenType.QUINT_EASEIN:
+ delta = this.quintEaseIn(time);
+ break;
+ case ccs.TweenType.QUINT_EASEOUT:
+ delta = this.quintEaseOut(time);
+ break;
+ case ccs.TweenType.QUINT_EASEINOUT:
+ delta = this.quintEaseInOut(time);
+ break;
+
+ case ccs.TweenType.EXPO_EASEIN:
+ delta = this.expoEaseIn(time);
+ break;
+ case ccs.TweenType.EXPO_EASEOUT:
+ delta = this.expoEaseOut(time);
+ break;
+ case ccs.TweenType.EXPO_EASEINOUT:
+ delta = this.expoEaseInOut(time);
+ break;
+
+ case ccs.TweenType.CIRC_EASEIN:
+ delta = this.circEaseIn(time);
+ break;
+ case ccs.TweenType.CIRC_EASEOUT:
+ delta = this.circEaseOut(time);
+ break;
+ case ccs.TweenType.CIRC_EASEINOUT:
+ delta = this.circEaseInOut(time);
+ break;
+
+ case ccs.TweenType.ELASTIC_EASEIN:
+ var period = 0.3;
+ if(null != easingParam && easingParam.length > 0){
+ period = easingParam[0];
+ }
+ delta = this.elasticEaseIn(time, period);
+ break;
+ case ccs.TweenType.ELASTIC_EASEOUT:
+ var period = 0.3;
+ if(null != easingParam && easingParam.length > 0){
+ period = easingParam[0];
+ }
+ delta = this.elasticEaseOut(time, period);
+ break;
+ case ccs.TweenType.ELASTIC_EASEINOUT:
+ var period = 0.3;
+ if(null != easingParam && easingParam.length > 0){
+ period = easingParam[0];
+ }
+ delta = this.elasticEaseInOut(time, period);
+ break;
+
+ case ccs.TweenType.BACK_EASEIN:
+ delta = this.backEaseIn(time);
+ break;
+ case ccs.TweenType.BACK_EASEOUT:
+ delta = this.backEaseOut(time);
+ break;
+ case ccs.TweenType.BACK_EASEINOUT:
+ delta = this.backEaseInOut(time);
+ break;
+
+ case ccs.TweenType.BOUNCE_EASEIN:
+ delta = this.bounceEaseIn(time);
+ break;
+ case ccs.TweenType.BOUNCE_EASEOUT:
+ delta = this.bounceEaseOut(time);
+ break;
+ case ccs.TweenType.BOUNCE_EASEINOUT:
+ delta = this.bounceEaseInOut(time);
+ break;
+
+ default:
+ delta = this.sineEaseInOut(time);
+ break;
+ }
+
+ return delta;
+};
+
+
+// Linear
+ccs.TweenFunction.linear = function (time) {
+ return time;
+};
+
+
+// Sine Ease
+ccs.TweenFunction.sineEaseIn = function (time) {
+ return -1 * Math.cos(time * ccs.HALF_PI) + 1;
+};
+ccs.TweenFunction.sineEaseOut = function (time) {
+ return Math.sin(time * ccs.HALF_PI);
+};
+ccs.TweenFunction.sineEaseInOut = function (time) {
+ return -0.5 * (Math.cos(ccs.M_PI * time) - 1);
+};
+
+
+// Quad Ease
+ccs.TweenFunction.quadEaseIn = function (time) {
+ return time * time;
+};
+ccs.TweenFunction.quadEaseOut = function (time) {
+ return -1 * time * (time - 2);
+};
+ccs.TweenFunction.quadEaseInOut = function (time) {
+ time = time * 2;
+ if (time < 1)
+ return 0.5 * time * time;
+ --time;
+ return -0.5 * (time * (time - 2) - 1);
+};
+
+
+// Cubic Ease
+ccs.TweenFunction.cubicEaseIn = function (time) {
+ return time * time * time;
+};
+ccs.TweenFunction.cubicEaseOut = function (time) {
+ time -= 1;
+ return (time * time * time + 1);
+};
+ccs.TweenFunction.cubicEaseInOut = function (time) {
+ time = time * 2;
+ if (time < 1)
+ return 0.5 * time * time * time;
+ time -= 2;
+ return 0.5 * (time * time * time + 2);
+};
+
+
+// Quart Ease
+ccs.TweenFunction.quartEaseIn = function (time) {
+ return time * time * time * time;
+};
+ccs.TweenFunction.quartEaseOut = function (time) {
+ time -= 1;
+ return -(time * time * time * time - 1);
+};
+ccs.TweenFunction.quartEaseInOut = function (time) {
+ time = time * 2;
+ if (time < 1)
+ return 0.5 * time * time * time * time;
+ time -= 2;
+ return -0.5 * (time * time * time * time - 2);
+};
+
+
+// Quint Ease
+ccs.TweenFunction.quintEaseIn = function (time) {
+ return time * time * time * time * time;
+};
+ccs.TweenFunction.quintEaseOut = function (time) {
+ time -= 1;
+ return (time * time * time * time * time + 1);
+};
+ccs.TweenFunction.quintEaseInOut = function (time) {
+ time = time * 2;
+ if (time < 1)
+ return 0.5 * time * time * time * time * time;
+ time -= 2;
+ return 0.5 * (time * time * time * time * time + 2);
+};
+
+
+// Expo Ease
+ccs.TweenFunction.expoEaseIn = function (time) {
+ return time === 0 ? 0 : Math.pow(2, 10 * (time - 1)) - 0.001;
+};
+ccs.TweenFunction.expoEaseOut = function (time) {
+ return time === 1 ? 1 : (-Math.pow(2, -10 * time) + 1);
+};
+ccs.TweenFunction.expoEaseInOut = function (time) {
+ time /= 0.5;
+ if (time < 1) {
+ time = 0.5 * Math.pow(2, 10 * (time - 1));
+ }
+ else {
+ time = 0.5 * (-Math.pow(2, -10 * (time - 1)) + 2);
+ }
+
+ return time;
+};
+
+
+// Circ Ease
+ccs.TweenFunction.circEaseIn = function (time) {
+ return -1 * (Math.sqrt(1 - time * time) - 1);
+};
+ccs.TweenFunction.circEaseOut = function (time) {
+ time = time - 1;
+ return Math.sqrt(1 - time * time);
+};
+ccs.TweenFunction.circEaseInOut = function (time) {
+ time = time * 2;
+ if (time < 1)
+ return -0.5 * (Math.sqrt(1 - time * time) - 1);
+ time -= 2;
+ return 0.5 * (Math.sqrt(1 - time * time) + 1);
+};
+
+
+// Elastic Ease
+ccs.TweenFunction.elasticEaseIn = function (time, easingParam) {
+ var period = 0.3;
+
+ if (easingParam.length > 0) {
+ period = easingParam[0];
+ }
+
+ var newT = 0;
+ if (time === 0 || time === 1) {
+ newT = time;
+ }
+ else {
+ var s = period / 4;
+ time = time - 1;
+ newT = -Math.pow(2, 10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period);
+ }
+
+ return newT;
+};
+ccs.TweenFunction.elasticEaseOut = function (time, easingParam) {
+ var period = 0.3;
+
+ if (easingParam.length > 0) {
+ period = easingParam[0];
+ }
+
+ var newT = 0;
+ if (time === 0 || time === 1) {
+ newT = time;
+ }
+ else {
+ var s = period / 4;
+ newT = Math.pow(2, -10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period) + 1;
+ }
+
+ return newT;
+};
+ccs.TweenFunction.elasticEaseInOut = function (time, easingParam) {
+ var period = 0.3;
+
+ if (easingParam.length > 0) {
+ period = easingParam[0];
+ }
+
+ var newT = 0;
+ if (time === 0 || time === 1) {
+ newT = time;
+ }
+ else {
+ time = time * 2;
+ if (!period) {
+ period = 0.3 * 1.5;
+ }
+
+ var s = period / 4;
+
+ time = time - 1;
+ if (time < 0) {
+ newT = -0.5 * Math.pow(2, 10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period);
+ } else {
+ newT = Math.pow(2, -10 * time) * Math.sin((time - s) * ccs.DOUBLE_PI / period) * 0.5 + 1;
+ }
+ }
+ return newT;
+};
+
+
+// Back Ease
+ccs.TweenFunction.backEaseIn = function (time) {
+ var overshoot = 1.70158;
+ return time * time * ((overshoot + 1) * time - overshoot);
+};
+ccs.TweenFunction.backEaseOut = function (time) {
+ var overshoot = 1.70158;
+
+ time = time - 1;
+ return time * time * ((overshoot + 1) * time + overshoot) + 1;
+};
+ccs.TweenFunction.backEaseInOut = function (time) {
+ var overshoot = 1.70158 * 1.525;
+
+ time = time * 2;
+ if (time < 1) {
+ return (time * time * ((overshoot + 1) * time - overshoot)) / 2;
+ }
+ else {
+ time = time - 2;
+ return (time * time * ((overshoot + 1) * time + overshoot)) / 2 + 1;
+ }
+};
+
+
+// Bounce Ease
+ccs.bounceTime = function (time) {
+ if (time < 1 / 2.75) {
+ return 7.5625 * time * time;
+ } else if (time < 2 / 2.75) {
+ time -= 1.5 / 2.75;
+ return 7.5625 * time * time + 0.75;
+ } else if (time < 2.5 / 2.75) {
+ time -= 2.25 / 2.75;
+ return 7.5625 * time * time + 0.9375;
+ }
+
+ time -= 2.625 / 2.75;
+ return 7.5625 * time * time + 0.984375;
+};
+ccs.TweenFunction.bounceEaseIn = function (time) {
+ return 1 - ccs.bounceTime(1 - time);
+};
+
+ccs.TweenFunction.bounceEaseOut = function (time) {
+ return ccs.bounceTime(time);
+};
+
+ccs.TweenFunction.bounceEaseInOut = function (time) {
+ var newT = 0;
+ if (time < 0.5) {
+ time = time * 2;
+ newT = (1 - ccs.bounceTime(1 - time)) * 0.5;
+ } else {
+ newT = ccs.bounceTime(time * 2 - 1) * 0.5 + 0.5;
+ }
+
+ return newT;
+};
+
+
+// Custom Ease
+ccs.TweenFunction.customEase = function (time, easingParam) {
+ if (easingParam.length > 0) {
+ var tt = 1 - time;
+ return easingParam[1] * tt * tt * tt + 3 * easingParam[3] * time * tt * tt + 3 * easingParam[5] * time * time * tt + easingParam[7] * time * time * time;
+ }
+ return time;
+};
+
+ccs.TweenFunction.easeIn = function(time, rate){
+ return Math.pow(time, rate);
+};
+
+ccs.TweenFunction.easeOut = function(time, rate){
+ return Math.pow(time, 1 / rate);
+};
+
+ccs.TweenFunction.easeInOut = function(time, rate){
+ time *= 2;
+ if(time < 1){
+ return 0.5 * Math.pow(time, rate);
+ }else{
+ return 1 - 0.5 * Math.pow(2 - time, rate);
+ }
+};
+
+ccs.TweenFunction.quadraticIn = function(time){
+ return Math.pow(time, 2);
+};
+
+ccs.TweenFunction.quadraticOut = function(time){
+ return -time * (time - 2);
+};
+
+ccs.TweenFunction.bezieratFunction = function(a, b, c, d, t){
+ return (Math.pow(1-t,3) * a + 3*t*(Math.pow(1-t,2))*b + 3*Math.pow(t,2)*(1-t)*c + Math.pow(t,3)*d );
+};
\ No newline at end of file
diff --git a/extensions/CocoStudio/Armature/utils/CCUtilMath.js b/extensions/cocostudio/armature/utils/CCUtilMath.js
similarity index 79%
rename from extensions/CocoStudio/Armature/utils/CCUtilMath.js
rename to extensions/cocostudio/armature/utils/CCUtilMath.js
index 2bdb2b71fe..082ec35b12 100644
--- a/extensions/CocoStudio/Armature/utils/CCUtilMath.js
+++ b/extensions/cocostudio/armature/utils/CCUtilMath.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -23,7 +24,7 @@
****************************************************************************/
var ENABLE_PHYSICS_DETECT = false;
-cc.fmodf = function (x, y) {
+ccs.fmodf = function (x, y) {
while (x > y) {
x -= y;
}
@@ -35,19 +36,19 @@ var CC_SAFE_RELEASE = function (obj) {
}
};
-cc.isSpriteContainPoint = function (sprite, point, outPoint) {
- var p = cc.p(0, 0);
+ccs.isSpriteContainPoint = function (sprite, point, outPoint) {
+ var p = sprite.convertToNodeSpace(point);
if (outPoint) {
- p = sprite.convertToNodeSpace(point);
+ outPoint.x = p.x;
+ outPoint.y = p.y;
}
var s = sprite.getContentSize();
- var r = cc.rect(0, 0, s.width, s.height);
- return cc.rectContainsPoint(r, p);
+ return cc.rectContainsPoint(cc.rect(0, 0, s.width, s.height), p);
};
-cc.SPRITE_CONTAIN_POINT = cc.isSpriteContainPoint;
-cc.SPRITE_CONTAIN_POINT_WITH_RETURN = cc.isSpriteContainPoint;
+ccs.SPRITE_CONTAIN_POINT = ccs.isSpriteContainPoint;
+ccs.SPRITE_CONTAIN_POINT_WITH_RETURN = ccs.isSpriteContainPoint;
-cc.extBezierTo = function (t, point1, point2, point3, point4) {
+ccs.extBezierTo = function (t, point1, point2, point3, point4) {
var p = cc.p(0, 0);
if (point3 && !point4) {
p.x = Math.pow((1 - t), 2) * point1.x + 2 * t * (1 - t) * point2.x + Math.pow(t, 2) * point3.x;
@@ -60,7 +61,7 @@ cc.extBezierTo = function (t, point1, point2, point3, point4) {
return p;
};
-cc.extCircleTo = function (t, center, radius, fromRadian, radianDif) {
+ccs.extCircleTo = function (t, center, radius, fromRadian, radianDif) {
var p = cc.p(0, 0);
p.x = center.x + radius * Math.cos(fromRadian + radianDif * t);
p.y = center.y + radius * Math.sin(fromRadian + radianDif * t);
diff --git a/extensions/CocoStudio/Components/CCComAttribute.js b/extensions/cocostudio/components/CCComAttribute.js
similarity index 65%
rename from extensions/CocoStudio/Components/CCComAttribute.js
rename to extensions/cocostudio/components/CCComAttribute.js
index 52cd57c7a3..0575b9334d 100644
--- a/extensions/CocoStudio/Components/CCComAttribute.js
+++ b/extensions/cocostudio/components/CCComAttribute.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -23,27 +24,36 @@
****************************************************************************/
/**
- * Base class for cc.ComAttribute
+ * The attribute component for Cocostudio.
* @class
- * @extends cc.Component
+ * @extends ccs.Component
*/
-cc.ComAttribute = cc.Component.extend({
- _attributes: null,
+ccs.ComAttribute = ccs.Component.extend(/** @lends ccs.ComAttribute# */{
_jsonDict: null,
+ _filePath: "",
+
+ /**
+ * Construction of ccs.ComAttribute
+ */
ctor: function () {
cc.Component.prototype.ctor.call(this);
- this._attributes = {};
this._jsonDict = {};
- this._name = "ComAttribute";
+ this._filePath = "";
+ this._name = "CCComAttribute";
+ ccs.ComAttribute.prototype.init.call(this);
},
+
+ /**
+ * Initializes a ccs.ComAttribute
+ * @returns {boolean}
+ */
init: function () {
- this._attributes = {};
this._jsonDict = {};
return true;
},
/**
- * Set int attribute
+ * Sets int attribute
* @param {String} key
* @param {number} value
*/
@@ -52,11 +62,11 @@ cc.ComAttribute = cc.Component.extend({
cc.log("Argument must be non-nil");
return;
}
- this._attributes[key] = value;
+ this._jsonDict[key] = value;
},
/**
- * Set double attribute
+ * Sets double attribute
* @param {String} key
* @param {number} value
*/
@@ -65,11 +75,11 @@ cc.ComAttribute = cc.Component.extend({
cc.log("Argument must be non-nil");
return;
}
- this._attributes[key] = value;
+ this._jsonDict[key] = value;
},
/**
- * Set float attribute
+ * Sets float attribute
* @param {String} key
* @param {number} value
*/
@@ -78,11 +88,11 @@ cc.ComAttribute = cc.Component.extend({
cc.log("Argument must be non-nil");
return;
}
- this._attributes[key] = value;
+ this._jsonDict[key] = value;
},
/**
- * Set boolean attribute
+ * Sets boolean attribute
* @param {String} key
* @param {Boolean} value
*/
@@ -91,24 +101,24 @@ cc.ComAttribute = cc.Component.extend({
cc.log("Argument must be non-nil");
return;
}
- this._attributes[key] = value;
+ this._jsonDict[key] = value;
},
/**
- * Set string attribute
+ * Sets string attribute
* @param {String} key
* @param {Boolean} value
*/
- setCString: function (key, value) {
+ setString: function (key, value) {
if (!key) {
cc.log("Argument must be non-nil");
return;
}
- this._attributes[key] = value;
+ this._jsonDict[key] = value;
},
/**
- * Set object attribute
+ * Sets object attribute
* @param {String} key
* @param {Object} value
*/
@@ -117,89 +127,84 @@ cc.ComAttribute = cc.Component.extend({
cc.log("Argument must be non-nil");
return;
}
- this._attributes[key] = value;
+ this._jsonDict[key] = value;
},
/**
- * Get int value from attribute
+ * Returns int value from attribute
* @param {String} key
* @returns {Number}
*/
getInt: function (key) {
- var ret = this._attributes[key];
+ var ret = this._jsonDict[key];
return parseInt(ret || 0);
},
/**
- * Get double value from attribute
+ * Returns double value from attribute
* @param {String} key
* @returns {Number}
*/
getDouble: function (key) {
- var ret = this._attributes[key];
+ var ret = this._jsonDict[key];
return parseFloat(ret || 0.0);
},
/**
- * Get float value from attribute
+ * Returns float value from attribute
* @param {String} key
* @returns {Number}
*/
getFloat: function (key) {
- var ret = this._attributes[key];
+ var ret = this._jsonDict[key];
return parseFloat(ret || 0.0);
},
/**
- * Get boolean value from attribute
+ * Returns boolean value from attribute
* @param {String} key
* @returns {Boolean}
*/
getBool: function (key) {
- var ret = this._attributes[key];
+ var ret = this._jsonDict[key];
return Boolean(ret || false);
},
/**
- * Get string value from attribute
+ * Returns string value from attribute
* @param {String} key
* @returns {String}
*/
- getCString: function (key) {
- var ret = this._attributes[key];
+ getString: function (key) {
+ var ret = this._jsonDict[key];
return ret || "";
},
/**
- * Get object value from attribute
+ * Returns object value from attribute
* @param {String} key
* @returns {Object}
*/
getObject: function (key) {
- return this._attributes[key];
- },
-
- /**
- * Getter of jsonDict
- * @returns {Object}
- */
- getDict: function () {
- return this._jsonDict;
+ return this._jsonDict[key];
},
/**
- * setter of jsonDict
- * @returns {Object}
+ * Parses json file.
+ * @param filename
*/
- setDict: function (dict) {
- this._jsonDict = dict;
+ parse:function(filename){
+ this._jsonDict = cc.loader.getRes(filename);
}
});
-
-cc.ComAttribute.create = function () {
- var com = new cc.ComAttribute();
- if (com && com.init()) {
- return com;
- }
- return null;
+/**
+ * allocates and initializes a ComAttribute.
+ * @deprecated since v3.0, please use new construction instead.
+ * @return {ccs.ComAttribute}
+ * @example
+ * // example
+ * var com = ccs.ComAttribute.create();
+ */
+ccs.ComAttribute.create = function () {
+ return new ccs.ComAttribute();
};
\ No newline at end of file
diff --git a/extensions/cocostudio/components/CCComAudio.js b/extensions/cocostudio/components/CCComAudio.js
new file mode 100644
index 0000000000..0b15af0b9a
--- /dev/null
+++ b/extensions/cocostudio/components/CCComAudio.js
@@ -0,0 +1,285 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The audio component for Cocostudio.
+ * @class
+ * @extends ccs.Component
+ */
+ccs.ComAudio = ccs.Component.extend(/** @lends ccs.ComAudio# */{
+ _filePath: "",
+ _loop: false,
+
+ /**
+ * Construction of ccs.ComAudio
+ */
+ ctor: function () {
+ cc.Component.prototype.ctor.call(this);
+ this._name = "Audio";
+ ccs.ComAudio.prototype.init.call(this);
+ },
+
+ /**
+ * Initializes a ccs.ComAudio.
+ * @returns {boolean}
+ */
+ init: function () {
+ return true;
+ },
+
+ /**
+ * The callback calls when a audio component enter stage.
+ * @override
+ */
+ onExit: function () {
+ this.stopBackgroundMusic(true);
+ this.stopAllEffects();
+ },
+
+ /**
+ * Stops all audios.
+ */
+ end: function () {
+ cc.audioEngine.end();
+ },
+
+ /**
+ * Preload background music resource
+ * @param {String} pszFilePath
+ */
+ preloadBackgroundMusic: function (pszFilePath) {
+ cc.loader.load(pszFilePath);
+ },
+
+ /**
+ * Play background music
+ * @param {String} [pszFilePath]
+ * @param {Boolean} [loop]
+ */
+ playBackgroundMusic: function (pszFilePath, loop) {
+ if(pszFilePath){
+ cc.audioEngine.playMusic(pszFilePath, loop);
+ }else{
+ cc.audioEngine.playMusic(this._filePath, this._loop);
+ }
+ },
+
+ /**
+ * Stop background music
+ * @param {String} releaseData
+ */
+ stopBackgroundMusic: function (releaseData) {
+ cc.audioEngine.stopMusic(releaseData);
+ },
+
+ /**
+ * Pause background music
+ */
+ pauseBackgroundMusic: function () {
+ cc.audioEngine.pauseMusic();
+ },
+
+ /**
+ * Resume background music
+ */
+ resumeBackgroundMusic: function () {
+ cc.audioEngine.resumeMusic();
+ },
+
+ /**
+ * Rewind background music
+ */
+ rewindBackgroundMusic: function () {
+ cc.audioEngine.rewindMusic();
+ },
+
+ /**
+ * Indicates whether any background music can be played or not.
+ * @returns {boolean}
+ */
+ willPlayBackgroundMusic: function () {
+ return cc.audioEngine.willPlayMusic();
+ },
+
+ /**
+ * Whether the music is playing.
+ * @returns {Boolean}
+ */
+ isBackgroundMusicPlaying: function () {
+ return cc.audioEngine.isMusicPlaying();
+ },
+
+ /**
+ * The volume of the music max value is 1.0,the min value is 0.0 .
+ * @returns {Number}
+ */
+ getBackgroundMusicVolume: function () {
+ return cc.audioEngine.getMusicVolume();
+ },
+
+ /**
+ * Set the volume of music.
+ * @param {Number} volume must be in 0.0~1.0 .
+ */
+ setBackgroundMusicVolume: function (volume) {
+ cc.audioEngine.setMusicVolume(volume);
+ },
+
+ /**
+ * The volume of the effects max value is 1.0,the min value is 0.0 .
+ * @returns {Number}
+ */
+ getEffectsVolume: function () {
+ return cc.audioEngine.getEffectsVolume();
+ },
+
+ /**
+ * Set the volume of sound effects.
+ * @param {Number} volume
+ */
+ setEffectsVolume: function (volume) {
+ cc.audioEngine.setEffectsVolume(volume);
+ },
+
+ /**
+ * Play sound effect.
+ * @param {String} [pszFilePath]
+ * @param {Boolean} [loop]
+ * @returns {Boolean}
+ */
+ playEffect: function (pszFilePath, loop) {
+ if (pszFilePath)
+ return cc.audioEngine.playEffect(pszFilePath, loop);
+ else
+ return cc.audioEngine.playEffect(this._filePath, this._loop);
+ },
+
+ /**
+ * Pause playing sound effect.
+ * @param {Number} soundId
+ */
+ pauseEffect: function (soundId) {
+ cc.audioEngine.pauseEffect(soundId);
+ },
+
+ /**
+ * Pause all effects
+ */
+ pauseAllEffects: function () {
+ cc.audioEngine.pauseAllEffects();
+ },
+
+ /**
+ * Resume effect
+ * @param {Number} soundId
+ */
+ resumeEffect: function (soundId) {
+ cc.audioEngine.resumeEffect(soundId);
+ },
+
+ /**
+ * Resume all effects
+ */
+ resumeAllEffects: function () {
+ cc.audioEngine.resumeAllEffects();
+ },
+
+ /**
+ * Stop effect
+ * @param {Number} soundId
+ */
+ stopEffect: function (soundId) {
+ cc.audioEngine.stopEffect(soundId);
+ },
+
+ /**
+ * stop all effects
+ */
+ stopAllEffects: function () {
+ cc.audioEngine.stopAllEffects();
+ },
+
+ /**
+ * Preload effect
+ * @param {String} pszFilePath
+ */
+ preloadEffect: function (pszFilePath) {
+ cc.loader.getRes(pszFilePath);
+ this.setFile(pszFilePath);
+ this.setLoop(false);
+ },
+
+ /**
+ * Unload effect
+ * @param {String} pszFilePath
+ */
+ unloadEffect: function (pszFilePath) {
+ cc.audioEngine.unloadEffect(pszFilePath);
+ },
+
+ /**
+ * File path setter
+ * @param {String} pszFilePath
+ */
+ setFile: function (pszFilePath) {
+ this._filePath = pszFilePath;
+ },
+
+ /**
+ * Sets audio component whether plays loop
+ * @param {Boolean} loop
+ */
+ setLoop: function (loop) {
+ this._loop = loop;
+ },
+
+ /**
+ * Returns the file path of audio component.
+ * @returns {string}
+ */
+ getFile: function () {
+ return this._filePath;
+ },
+
+ /**
+ * Returns audio component whether plays loop
+ * @returns {boolean}
+ */
+ isLoop: function () {
+ return this._loop;
+ }
+});
+
+/**
+ * allocates and initializes a ComAudio.
+ * @deprecated since v3.0, please use new construction instead.
+ * @return {ccs.ComAudio}
+ * @example
+ * // example
+ * var com = ccs.ComAudio.create();
+ */
+ccs.ComAudio.create = function () {
+ return new ccs.ComAudio();
+};
\ No newline at end of file
diff --git a/extensions/cocostudio/components/CCComController.js b/extensions/cocostudio/components/CCComController.js
new file mode 100644
index 0000000000..cdd85eeb94
--- /dev/null
+++ b/extensions/cocostudio/components/CCComController.js
@@ -0,0 +1,76 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The controller component for Cocostudio.
+ * @class
+ * @extends ccs.Component
+ */
+ccs.ComController = ccs.Component.extend(/** @lends ccs.ComController# */{
+ /**
+ * Construction of ccs.ComController.
+ */
+ ctor: function () {
+ cc.Component.prototype.ctor.call(this);
+ this._name = "ComController";
+ ccs.ComController.prototype.init.call(this);
+ },
+
+ /**
+ * The callback calls when controller component enter stage.
+ * @override
+ */
+ onEnter: function () {
+ if (this._owner !== null)
+ this._owner.scheduleUpdate();
+ },
+
+ /**
+ * Returns controller component whether is enabled
+ * @returns {Boolean}
+ */
+ isEnabled: function () {
+ return this._enabled;
+ },
+
+ /**
+ * Sets controller component whether is enabled
+ * @param {Boolean} bool
+ */
+ setEnabled: function (bool) {
+ this._enabled = bool;
+ }
+});
+/**
+ * Allocates and initializes a ComController.
+ * @deprecated since v3.0, please use new construction instead.
+ * @return {ccs.ComController}
+ * @example
+ * // example
+ * var com = ccs.ComController.create();
+ */
+ccs.ComController.create = function () {
+ return new ccs.ComController();
+};
\ No newline at end of file
diff --git a/extensions/cocostudio/components/CCComRender.js b/extensions/cocostudio/components/CCComRender.js
new file mode 100644
index 0000000000..960e096a11
--- /dev/null
+++ b/extensions/cocostudio/components/CCComRender.js
@@ -0,0 +1,91 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The render component for Cocostudio.
+ * @class
+ * @extends ccs.Component
+ */
+ccs.ComRender = ccs.Component.extend(/** @lends ccs.ComRender# */{
+ _render: null,
+ /**
+ * Construction of ccs.ComRender
+ * @param {cc.Node} node
+ * @param {String} comName
+ */
+ ctor: function (node, comName) {
+ cc.Component.prototype.ctor.call(this);
+ this._render = node;
+ this._name = comName;
+ this.isRenderer = true;
+ ccs.ComRender.prototype.init.call(this);
+ },
+
+ /**
+ * The callback calls when a render component enter stage.
+ */
+ onEnter: function () {
+ if (this._owner)
+ this._owner.addChild(this._render);
+ },
+
+ /**
+ * The callback calls when a render component exit stage.
+ */
+ onExit: function () {
+ if (this._owner) {
+ this._owner.removeChild(this._render, true);
+ this._render = null;
+ }
+ },
+
+ /**
+ * Returns a render node
+ * @returns {cc.Node}
+ */
+ getNode: function () {
+ return this._render;
+ },
+
+ /**
+ * Sets a render node to component.
+ * @param {cc.Node} node
+ */
+ setNode: function (node) {
+ this._render = node;
+ }
+});
+
+/**
+ * allocates and initializes a ComRender.
+ * @deprecated since v3.0, please use new construction instead.
+ * @return {ccs.ComRender}
+ * @example
+ * // example
+ * var com = ccs.ComRender.create();
+ */
+ccs.ComRender.create = function (node, comName) {
+ return new ccs.ComRender(node, comName);
+};
diff --git a/cocos2d/support/component/CCComponent.js b/extensions/cocostudio/components/CCComponent.js
similarity index 60%
rename from cocos2d/support/component/CCComponent.js
rename to extensions/cocostudio/components/CCComponent.js
index a0d3102cc5..5084a9744a 100644
--- a/cocos2d/support/component/CCComponent.js
+++ b/extensions/cocostudio/components/CCComponent.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2013 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,62 +23,113 @@
THE SOFTWARE.
****************************************************************************/
-cc.Component = cc.Class.extend({
+/**
+ * The base class of component in CocoStudio
+ * @class
+ * @extends cc.Class
+ */
+cc.Component = cc.Class.extend(/** @lends cc.Component# */{
_owner: null,
- _name: null,
- _enabled:null,
+ _name: "",
+ _enabled: true,
+ /**
+ * Construction of cc.Component
+ */
ctor:function(){
this._owner = null;
this._name = "";
this._enabled = true;
},
+ /**
+ * Initializes a cc.Component.
+ * @returns {boolean}
+ */
init:function(){
return true;
},
+ /**
+ * The callback when a component enter stage.
+ */
onEnter:function(){
-
},
+ /**
+ * The callback when a component exit stage.
+ */
onExit:function(){
-
},
+ /**
+ * The callback per every frame if it schedules update.
+ * @param delta
+ */
update:function(delta){
-
},
+ /**
+ * Serialize a component object.
+ * @param reader
+ */
serialize:function( reader){
-
},
+ /**
+ * Returns component whether is enabled.
+ * @returns {boolean}
+ */
isEnabled:function(){
return this._enabled;
},
+ /**
+ * Sets component whether is enabled.
+ * @param enable
+ */
setEnabled:function(enable){
this._enabled = enable;
},
+ /**
+ * Returns the name of cc.Component.
+ * @returns {string}
+ */
getName:function(){
return this._name;
} ,
+ /**
+ * Sets the name to cc.Component.
+ * @param {String} name
+ */
setName:function(name){
this._name = name;
} ,
+ /**
+ * Sets the owner to cc.Component.
+ * @param owner
+ */
setOwner:function(owner){
this._owner = owner;
},
+ /**
+ * Returns the owner of cc.Component.
+ * @returns {*}
+ */
getOwner:function(){
return this._owner;
}
});
+/**
+ * Allocates and initializes a component.
+ * @deprecated since v3.0, please use new construction instead.
+ * @return {cc.Component}
+ */
cc.Component.create = function(){
return new cc.Component();
};
diff --git a/cocos2d/support/component/CCComponentContainer.js b/extensions/cocostudio/components/CCComponentContainer.js
similarity index 58%
rename from cocos2d/support/component/CCComponentContainer.js
rename to extensions/cocostudio/components/CCComponentContainer.js
index bc344c84c3..0b9b461969 100644
--- a/cocos2d/support/component/CCComponentContainer.js
+++ b/extensions/cocostudio/components/CCComponentContainer.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2013 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,31 +23,59 @@
THE SOFTWARE.
****************************************************************************/
-cc.ComponentContainer = cc.Class.extend({
+/**
+ * The component container for Cocostudio, it has some components.
+ * @class
+ * @extends cc.Class
+ */
+cc.ComponentContainer = cc.Class.extend(/** @lends cc.ComponentContainer# */{
_components:null,
_owner:null,
+ /**
+ * Construction of cc.ComponentContainer
+ * @param node
+ */
ctor:function(node){
this._components = null;
this._owner = node;
},
+ /**
+ * Gets component by name.
+ * @param name
+ * @returns {*}
+ */
getComponent:function(name){
- cc.Assert(name != null, "Argument must be non-nil");
+ if(!name)
+ throw new Error("cc.ComponentContainer.getComponent(): name should be non-null");
name = name.trim();
+ if(!this._components){
+ this._components = {};
+ }
return this._components[name];
},
+ /**
+ * Adds a component to container
+ * @param {cc.Component} component
+ * @returns {boolean}
+ */
add:function(component){
- cc.Assert(component != null, "Argument must be non-nil");
- cc.Assert(component.getOwner() == null, "Component already added. It can't be added again");
+ if(!component)
+ throw new Error("cc.ComponentContainer.add(): component should be non-null");
+ if(component.getOwner()){
+ cc.log("cc.ComponentContainer.add(): Component already added. It can't be added again");
+ return false;
+ }
+
if(this._components == null){
this._components = {};
this._owner.scheduleUpdate();
}
var oldComponent = this._components[component.getName()];
if(oldComponent){
- cc.Assert(oldComponent == null, "Component already added. It can't be added again");
+ cc.log("cc.ComponentContainer.add(): Component already added. It can't be added again");
return false;
}
component.setOwner(this._owner);
@@ -55,25 +84,39 @@ cc.ComponentContainer = cc.Class.extend({
return true;
},
+ /**
+ * Removes component from container by name or component object.
+ * @param {String|cc.Component} name component name or component object.
+ * @returns {boolean}
+ */
remove:function(name){
- cc.Assert(name != null, "Argument must be non-nil");
+ if(!name)
+ throw new Error("cc.ComponentContainer.remove(): name should be non-null");
if(!this._components)
return false;
- var locComponents = this._components;
- name = name.trim();
- var component = locComponents[name];
- if(component)
+ if(name instanceof cc.Component)
+ return this._removeByComponent(name);
+ else {
+ name = name.trim();
+ return this._removeByComponent(this._components[name]);
+ }
+ },
+
+ _removeByComponent:function(component){
+ if(!component)
return false;
component.onExit();
component.setOwner(null);
- delete locComponents[name];
+ delete this._components[component.getName()];
return true;
},
+ /**
+ * Removes all components of container.
+ */
removeAll:function(){
if(!this._components)
return;
-
var locComponents = this._components;
for(var selKey in locComponents){
var selComponent = locComponents[selKey];
@@ -89,24 +132,27 @@ cc.ComponentContainer = cc.Class.extend({
this._components = {};
},
+ /**
+ * Visit callback by director. it calls every frame.
+ * @param {Number} delta
+ */
visit:function(delta){
if(!this._components)
return;
var locComponents = this._components;
- for(var selKey in locComponents){
+ for(var selKey in locComponents)
locComponents[selKey].update(delta);
- }
},
- isEmpty:function(){
- if(!this._components)
+ /**
+ * Returns the container whether is empty.
+ * @returns {boolean}
+ */
+ isEmpty: function () {
+ if (!this._components)
return true;
-
- for(var selkey in this._components){
- return false;
- }
- return true;
+ return this._components.length === 0;
}
});
diff --git a/extensions/cocostudio/loader/load.js b/extensions/cocostudio/loader/load.js
new file mode 100644
index 0000000000..bf75cce354
--- /dev/null
+++ b/extensions/cocostudio/loader/load.js
@@ -0,0 +1,280 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+ccs._load = (function () {
+
+ /**
+ * load file
+ * @param {String} file
+ * @param {String} [type=] - ccui|node|action
+ * @param {String} [path=] - Resource search path
+ * @returns {*}
+ */
+ var load = function (file, type, path) {
+
+ var json = cc.loader.getRes(file);
+
+ if (!json)
+ return cc.log("%s does not exist", file);
+ var ext = extname(file).toLocaleLowerCase();
+ if (ext !== "json" && ext !== "exportjson")
+ return cc.log("%s load error, must be json file", file);
+
+ var parse;
+ if (!type) {
+ if (json["widgetTree"])
+ parse = parser["ccui"];
+ else if (json["nodeTree"])
+ parse = parser["timeline"];
+ else if (json["Content"] && json["Content"]["Content"])
+ parse = parser["timeline"];
+ else if (json["gameobjects"])
+ parse = parser["scene"];
+ } else {
+ parse = parser[type];
+ }
+
+ if (!parse) {
+ cc.log("Can't find the parser : %s", file);
+ return new cc.Node();
+ }
+ var version = json["version"] || json["Version"];
+ if (!version && json["armature_data"]) {
+ cc.warn("%s is armature. please use:", file);
+ cc.warn(" ccs.armatureDataManager.addArmatureFileInfoAsync(%s);", file);
+ cc.warn(" var armature = new ccs.Armature('name');");
+ return new cc.Node();
+ }
+ var currentParser = getParser(parse, version);
+ if (!currentParser) {
+ cc.log("Can't find the parser : %s", file);
+ return new cc.Node();
+ }
+
+ return currentParser.parse(file, json, path) || null;
+ };
+
+ var parser = {
+ "ccui": {},
+ "timeline": {},
+ "action": {},
+ "scene": {}
+ };
+
+ load.registerParser = function (name, version, target) {
+ if (!name || !version || !target)
+ return cc.log("register parser error");
+ if (!parser[name])
+ parser[name] = {};
+ parser[name][version] = target;
+ };
+
+ load.getParser = function (name, version) {
+ if (name && version)
+ return parser[name] ? parser[name][version] : undefined;
+ if (name)
+ return parser[name];
+ return parser;
+ };
+
+ //Gets the file extension
+ var extname = function (fileName) {
+ var arr = fileName.match(extnameReg);
+ return ( arr && arr[1] ) ? arr[1] : null;
+ };
+ var extnameReg = /\.([^\.]+)$/;
+
+
+ var parserReg = /([^\.](\.\*)?)*$/;
+ var getParser = function (parser, version) {
+ if (parser[version])
+ return parser[version];
+ else if (version === "*")
+ return null;
+ else
+ return getParser(parser, version.replace(parserReg, "*"));
+ };
+
+ return load;
+
+})();
+
+ccs._parser = cc.Class.extend({
+
+ ctor: function () {
+ this.parsers = {};
+ },
+
+ _dirnameReg: /\S*\//,
+ _dirname: function (path) {
+ var arr = path.match(this._dirnameReg);
+ return (arr && arr[0]) ? arr[0] : "";
+ },
+
+ getClass: function (json) {
+ return json["classname"];
+ },
+
+ getNodeJson: function (json) {
+ return json["widgetTree"];
+ },
+
+ parse: function (file, json, resourcePath) {
+ resourcePath = resourcePath || this._dirname(file);
+ this.pretreatment(json, resourcePath);
+ var node = this.parseNode(this.getNodeJson(json), resourcePath, file);
+ node && this.deferred(json, resourcePath, node, file);
+ return node;
+ },
+
+ pretreatment: function (json, resourcePath, file) {
+ },
+
+ deferred: function (json, resourcePath, node, file) {
+ },
+
+ parseNode: function (json, resourcePath) {
+ var parser = this.parsers[this.getClass(json)];
+ var widget = null;
+ if (parser)
+ widget = parser.call(this, json, resourcePath);
+ else
+ cc.log("Can't find the parser : %s", this.getClass(json));
+
+ return widget;
+ },
+
+ registerParser: function (widget, parse) {
+ this.parsers[widget] = parse;
+ }
+});
+
+/**
+ * Analysis of studio JSON file
+ * The incoming file name, parse out the corresponding object
+ * Temporary support file list:
+ * ui 1.*
+ * node 1.* - 2.*
+ * action 1.* - 2.*
+ * scene 0.* - 1.*
+ * @param {String} file
+ * @param {String} [path=] Resource path
+ * @returns {{node: cc.Node, action: cc.Action}}
+ */
+ccs.load = function (file, path) {
+ var object = {
+ node: null,
+ action: null
+ };
+
+ object.node = ccs._load(file, null, path);
+ object.action = ccs._load(file, "action", path);
+ if (object.action && object.action.tag === -1 && object.node)
+ object.action.tag = object.node.tag;
+ return object;
+};
+ccs.load.validate = {};
+
+ccs.load.preload = true;
+
+/**
+ * Analysis of studio JSON file and layout ui widgets by visible size.
+ * The incoming file name, parse out the corresponding object
+ * Temporary support file list:
+ * ui 1.*
+ * node 1.* - 2.*
+ * action 1.* - 2.*
+ * scene 0.* - 1.*
+ * @param {String} file
+ * @param {String} [path=] Resource path
+ * @returns {{node: cc.Node, action: cc.Action}}
+ */
+ccs.loadWithVisibleSize = function (file, path) {
+ var object = ccs.load(file, path);
+ var size = cc.director.getVisibleSize();
+ if (object.node && size) {
+ object.node.setContentSize(size.width, size.height);
+ ccui.helper.doLayout(object.node);
+ }
+ return object;
+};
+
+//Forward compatible interface
+
+ccs.actionTimelineCache = {
+
+
+ //@deprecated This function will be deprecated sooner or later please use ccs.load
+ /**
+ * Create Timeline Action
+ * @param file
+ * @returns {*}
+ */
+ createAction: function (file) {
+ return ccs._load(file, "action");
+ }
+};
+
+ccs.csLoader = {
+
+ //@deprecated This function will be deprecated sooner or later please use ccs.load
+ /**
+ * Create Timeline Node
+ * @param file
+ * @returns {*}
+ */
+ createNode: function (file) {
+ return ccs._load(file);
+ }
+};
+
+cc.loader.register(["json"], {
+ load: function (realUrl, url, res, cb) {
+ cc.loader.loadJson(realUrl, function (error, data) {
+ var path = cc.path;
+ if (data && data["Content"] && data["Content"]["Content"]["UsedResources"]) {
+ var UsedResources = data["Content"]["Content"]["UsedResources"],
+ dirname = path.dirname(url),
+ list = [],
+ tmpUrl, normalUrl;
+ for (var i = 0; i < UsedResources.length; i++) {
+ if (!ccs.load.preload && /\.(png|jpg$)/.test(UsedResources[i]))
+ continue;
+ tmpUrl = path.join(dirname, UsedResources[i]);
+ normalUrl = path._normalize(tmpUrl);
+ if (!ccs.load.validate[normalUrl]) {
+ ccs.load.validate[normalUrl] = true;
+ list.push(normalUrl);
+ }
+ }
+ cc.loader.load(list, function () {
+ cb(error, data);
+ });
+ } else {
+ cb(error, data);
+ }
+
+ });
+ }
+});
diff --git a/extensions/cocostudio/loader/parsers/action-1.x.js b/extensions/cocostudio/loader/parsers/action-1.x.js
new file mode 100644
index 0000000000..f3b6ff17d8
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/action-1.x.js
@@ -0,0 +1,233 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function(load, baseParser){
+
+ var Parser = baseParser.extend({
+
+ getNodeJson: function(json){
+ return json["action"];
+ },
+
+ parseNode: function(json, resourcePath, file){
+ if(!json)
+ return null;
+
+ var self = this,
+ action = new ccs.ActionTimeline();
+
+ action.setDuration(json["duration"]);
+ action.setTimeSpeed(json["speed"] || 1);
+ //The process of analysis
+ var timelines = json["timelines"];
+ timelines.forEach(function(timeline){
+ var parser = self.parsers[timeline["frameType"]];
+ var frame;
+ if(parser)
+ frame = parser.call(self, timeline, resourcePath);
+ else
+ cc.log("parser does not exist : %s", timeline["frameType"]);
+ if(frame)
+ action.addTimeline(frame);
+
+ if(timeline["frameType"] === "ColorFrame"){
+ action.addTimeline(
+ self.parsers["AlphaFrame"].call(self, timeline, resourcePath)
+ );
+ }
+ });
+
+ return action;
+ }
+
+ });
+
+ var parser = new Parser();
+
+ var frameList = [
+ {
+ name: "PositionFrame",
+ handle: function(options){
+ var frame = new ccs.PositionFrame();
+ var x = options["x"];
+ var y = options["y"];
+ frame.setPosition(cc.p(x,y));
+ return frame;
+ }
+ },
+ {
+ name: "VisibleFrame",
+ handle: function(options){
+ var frame = new ccs.VisibleFrame();
+ var visible = options["value"];
+ frame.setVisible(visible);
+ return frame;
+ }
+ },
+ {
+ name: "ScaleFrame",
+ handle: function(options){
+ var frame = new ccs.ScaleFrame();
+ var scalex = options["x"];
+ var scaley = options["y"];
+ frame.setScaleX(scalex);
+ frame.setScaleY(scaley);
+ return frame;
+ }
+ },
+ {
+ name: "RotationFrame",
+ handle: function(options){
+ var frame = new ccs.RotationFrame();
+ var rotation = options["rotation"];
+ frame.setRotation(rotation);
+ return frame;
+ }
+ },
+ {
+ name: "SkewFrame",
+ handle: function(options){
+ var frame = new ccs.SkewFrame();
+ var skewx = options["x"];
+ var skewy = options["y"];
+ frame.setSkewX(skewx);
+ frame.setSkewY(skewy);
+ return frame;
+ }
+ },
+ {
+ name: "RotationSkewFrame",
+ handle: function(options){
+ var frame = new ccs.RotationSkewFrame();
+ var skewx = options["x"];
+ var skewy = options["y"];
+ frame.setSkewX(skewx);
+ frame.setSkewY(skewy);
+ return frame;
+ }
+ },
+ {
+ name: "AnchorFrame",
+ handle: function(options){
+ var frame = new ccs.AnchorPointFrame();
+ var anchorx = options["x"];
+ var anchory = options["y"];
+ frame.setAnchorPoint(cc.p(anchorx, anchory));
+ return frame;
+ }
+ },
+ {
+ name: "InnerActionFrame",
+ handle: function(options){
+ var frame = new ccs.InnerActionFrame();
+ var type = options["innerActionType"];
+ var startFrame = options["startFrame"];
+ frame.setInnerActionType(type);
+ frame.setStartFrameIndex(startFrame);
+ return frame;
+ }
+ },
+ {
+ name: "ColorFrame",
+ handle: function(options){
+ var frame = new ccs.ColorFrame();
+ var red = options["red"];
+ var green = options["green"];
+ var blue = options["blue"];
+ frame.setColor(cc.color(red, green, blue));
+ var alphaFrame = new ccs.AlphaFrame();
+ var alpha = options["alpha"];
+ alphaFrame.setAlpha(alpha);
+ return frame;
+ }
+ },
+ {
+ name: "AlphaFrame",
+ handle: function(options){
+ var frame = new ccs.AlphaFrame();
+ var alpha = options["alpha"];
+ frame.setAlpha(alpha);
+ return frame;
+ }
+ },
+ {
+ name: "TextureFrame",
+ handle: function(options){
+ var frame = new ccs.TextureFrame();
+ var texture = options["value"];
+ if(texture != null) {
+ var path = texture;
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
+ if(spriteFrame == null){
+ var jsonPath = ccs.csLoader.getJsonPath();
+ path = jsonPath + texture;
+ }
+ frame.setTextureName(path);
+ }
+ return frame;
+ }
+ },
+ {
+ name: "EventFrame",
+ handle: function(options){
+ var frame = new ccs.EventFrame();
+ var evnt = options["value"];
+ if(evnt != null)
+ frame.setEvent(evnt);
+ return frame;
+ }
+ },
+ {
+ name: "ZOrderFrame",
+ handle: function(options){
+ var frame = new ccs.ZOrderFrame();
+ var zorder = options["value"];
+ frame.setZOrder(zorder);
+ return frame;
+ }
+ }
+ ];
+
+ frameList.forEach(function(item){
+ parser.registerParser(item.name, function(options, resourcePath){
+ var timeline = new ccs.Timeline();
+ timeline.setActionTag(options["actionTag"]);
+
+ var frames = options["frames"];
+ if(frames && frames.length){
+ frames.forEach(function(frameData){
+ var frame = item.handle(frameData);
+ frame.setFrameIndex(frameData["frameIndex"]);
+ frame.setTween(frameData["tween"]);
+ timeline.addFrame(frame);
+ });
+ }
+ return timeline;
+ });
+ });
+
+ load.registerParser("action", "0.*", parser);
+ load.registerParser("action", "1.*", parser);
+
+})(ccs._load, ccs._parser);
diff --git a/extensions/cocostudio/loader/parsers/action-2.x.js b/extensions/cocostudio/loader/parsers/action-2.x.js
new file mode 100644
index 0000000000..febdad197b
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/action-2.x.js
@@ -0,0 +1,310 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function(load, baseParser){
+
+ var Parser = baseParser.extend({
+
+ getNodeJson: function(json){
+ return json["Content"]["Content"]["Animation"];
+ },
+
+ parseNode: function(json, resourcePath, file){
+ if(!json)
+ return null;
+
+ var self = this,
+ action = new ccs.ActionTimeline();
+
+ action.setDuration(json["Duration"]);
+ action.setTimeSpeed(json["Speed"] || 1);
+
+ //The process of analysis
+ var timelines = json["Timelines"];
+ timelines.forEach(function(timeline){
+ var parser = self.parsers[timeline["Property"]];
+ var frame;
+ if(parser)
+ frame = parser.call(self, timeline, resourcePath);
+ else
+ cc.log("parser does not exist : %s", timeline["Property"]);
+ if(frame)
+ action.addTimeline(frame);
+ });
+
+ return action;
+ },
+
+ deferred: function(json, resourcePath, action, file){
+ var animationlist = json["Content"]["Content"]["AnimationList"];
+ var length = animationlist ? animationlist.length : 0;
+ for (var i = 0; i < length; i++){
+ var animationdata = animationlist[i];
+ var info = { name: null, startIndex: null, endIndex: null };
+ info.name = animationdata["Name"];
+ info.startIndex = animationdata["StartIndex"];
+ info.endIndex = animationdata["EndIndex"];
+ action.addAnimationInfo(info);
+ }
+ }
+
+ });
+ var parser = new Parser();
+
+ var frameList = [
+ {
+ name: "Position",
+ handle: function(options){
+ var frame = new ccs.PositionFrame();
+ var x = options["X"];
+ var y = options["Y"];
+ frame.setPosition(cc.p(x,y));
+ return frame;
+ }
+ },
+ {
+ name: "VisibleForFrame",
+ handle: function(options){
+ var frame = new ccs.VisibleFrame();
+ var visible = options["Value"];
+ frame.setVisible(visible);
+ return frame;
+ }
+ },
+ {
+ name: "Scale",
+ handle: function(options){
+ var frame = new ccs.ScaleFrame();
+ var scalex = options["X"];
+ var scaley = options["Y"];
+ frame.setScaleX(scalex);
+ frame.setScaleY(scaley);
+ return frame;
+ }
+ },
+ {
+ name: "Rotation",
+ handle: function(options){
+ var frame = new ccs.RotationFrame();
+ var rotation = options["Rotation"] || options["Value"] || 0;
+ frame.setRotation(rotation);
+ return frame;
+ }
+ },
+ {
+ name: "Skew",
+ handle: function(options){
+ var frame = new ccs.SkewFrame();
+ var skewx = options["X"];
+ var skewy = options["Y"];
+ frame.setSkewX(skewx);
+ frame.setSkewY(skewy);
+ return frame;
+ }
+ },
+ {
+ name: "RotationSkew",
+ handle: function(options){
+ var frame = new ccs.RotationSkewFrame();
+ var skewx = options["X"];
+ var skewy = options["Y"];
+ frame.setSkewX(skewx);
+ frame.setSkewY(skewy);
+ return frame;
+ }
+ },
+ {
+ name: "Anchor",
+ handle: function(options){
+ var frame = new ccs.AnchorPointFrame();
+ var anchorx = options["X"];
+ var anchory = options["Y"];
+ frame.setAnchorPoint(cc.p(anchorx, anchory));
+ return frame;
+ }
+ },{
+ name: "AnchorPoint",
+ handle: function(options){
+ var frame = new ccs.AnchorPointFrame();
+ var anchorx = options["X"];
+ var anchory = options["Y"];
+ frame.setAnchorPoint(cc.p(anchorx, anchory));
+ return frame;
+ }
+ },{
+ name: "InnerAction",
+ handle: function(options){
+ var frame = new ccs.InnerActionFrame();
+ var type = options["InnerActionType"];
+ var startFrame = options["StartFrame"];
+ frame.setInnerActionType(type);
+ frame.setStartFrameIndex(startFrame);
+ return frame;
+ }
+ },
+ {
+ name: "CColor",
+ handle: function(options){
+ var frame = new ccs.ColorFrame();
+ var color = options["Color"];
+ if(!color) color = {};
+ color["R"] = color["R"] === undefined ? 255 : color["R"];
+ color["G"] = color["G"] === undefined ? 255 : color["G"];
+ color["B"] = color["B"] === undefined ? 255 : color["B"];
+ frame.setColor(cc.color(color["R"], color["G"], color["B"]));
+ return frame;
+ }
+ },
+ {
+ name: "Alpha",
+ handle: function(options){
+ var frame = new ccs.AlphaFrame();
+ var alpha = options["Value"];
+ frame.setAlpha(alpha);
+ return frame;
+ }
+ },
+ {
+ name: "FileData",
+ handle: function(options, resourcePath){
+ var frame, texture, plist, path, spriteFrame;
+ frame = new ccs.TextureFrame();
+ texture = options["TextureFile"];
+ if(texture != null) {
+ plist = texture["Plist"];
+ path = texture["Path"];
+ spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
+ if(!spriteFrame && plist){
+ if(cc.loader.getRes(resourcePath + plist)){
+ cc.spriteFrameCache.addSpriteFrames(resourcePath + plist);
+ spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
+ }else{
+ cc.log("%s need to be preloaded", resourcePath + plist);
+ }
+ }
+ if(spriteFrame == null){
+ path = resourcePath + path;
+ }
+ frame.setTextureName(path);
+ }
+ return frame;
+ }
+ },
+ {
+ name: "FrameEvent",
+ handle: function(options){
+ var frame = new ccs.EventFrame();
+ var evnt = options["Value"];
+ if(evnt != null)
+ frame.setEvent(evnt);
+ return frame;
+ }
+ },
+ {
+ name: "ZOrder",
+ handle: function(options){
+ var frame = new ccs.ZOrderFrame();
+ var zorder = options["Value"];
+ frame.setZOrder(zorder);
+ return frame;
+ }
+ },
+ {
+ name: "ActionValue",
+ handle: function (options) {
+
+ var frame = new ccs.InnerActionFrame();
+ var innerActionType = options["InnerActionType"];
+
+ var currentAnimationFrame = options["CurrentAniamtionName"];
+
+ var singleFrameIndex = options["SingleFrameIndex"];
+
+ var frameIndex = options["FrameIndex"];
+ if(frameIndex !== undefined)
+ frame.setFrameIndex(frameIndex);
+
+ frame.setInnerActionType(ccs.InnerActionType[innerActionType]);
+ frame.setSingleFrameIndex(singleFrameIndex);
+
+ frame.setEnterWithName(true);
+ if (currentAnimationFrame)
+ frame.setAnimationName(currentAnimationFrame);
+
+ return frame;
+ }
+ },
+ {
+ name: "BlendFunc",
+ handle: function(options){
+ var frame = new ccs.BlendFuncFrame();
+ var blendFunc = options["BlendFunc"];
+ if(blendFunc && blendFunc["Src"] !== undefined && blendFunc["Dst"] !== undefined)
+ frame.setBlendFunc(new cc.BlendFunc(blendFunc["Src"], blendFunc["Dst"]));
+ return frame;
+ }
+ }
+ ];
+
+ var loadEasingDataWithFlatBuffers = function(frame, options){
+ var type = options["Type"];
+ frame.setTweenType(type);
+ var points = options["Points"];
+ var result = [];
+ if(points){
+ points.forEach(function(p){
+ result.push(p["X"]);
+ result.push(p["Y"]);
+ });
+ frame.setEasingParams(result);
+ }
+ };
+
+ frameList.forEach(function(item){
+ parser.registerParser(item.name, function(options, resourcePath){
+ var timeline = new ccs.Timeline();
+ timeline.setActionTag(options["ActionTag"]);
+
+ var frames = options["Frames"];
+ if(frames && frames.length){
+ frames.forEach(function(frameData){
+ var frame = item.handle(frameData, resourcePath);
+ frame.setFrameIndex(frameData["FrameIndex"]);
+ var tween = frameData["Tween"] != null ? frameData["Tween"] : true;
+ frame.setTween(tween);
+ //https://github.com/cocos2d/cocos2d-x/pull/11388/files
+ var easingData = frameData["EasingData"];
+ if(easingData)
+ loadEasingDataWithFlatBuffers(frame, easingData);
+ timeline.addFrame(frame);
+ });
+ }
+ return timeline;
+ });
+ });
+
+ load.registerParser("action", "2.*", parser);
+ load.registerParser("action", "*", parser);
+
+})(ccs._load, ccs._parser);
diff --git a/extensions/cocostudio/loader/parsers/compatible.js b/extensions/cocostudio/loader/parsers/compatible.js
new file mode 100644
index 0000000000..9a73bdbfc4
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/compatible.js
@@ -0,0 +1,253 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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 file is for compatibility compatibility with older versions of GUIReader and SceneReader
+ todo: deprecated all
+ */
+
+(function () {
+
+ ccs.uiReader = {
+
+ _fileDesignSizes: {},
+
+ //@deprecated This function will be deprecated sooner or later please use ccs.load
+ /**
+ * Create CCUI Node
+ * @param file
+ * @returns {*}
+ */
+ widgetFromJsonFile: function (file) {
+ var json = cc.loader.getRes(file);
+ if (json)
+ this._fileDesignSizes[file] = cc.size(json["designWidth"] || 0, json["designHeight"] || 0);
+
+ var version = json["Version"] || json["version"];
+ var versionNum = ccs.uiReader.getVersionInteger(version);
+ if (!version || versionNum >= 1700) {
+ cc.warn("Not supported file types, Please try use the ccs.load");
+ return null;
+ }
+ return ccs._load(file, "ccui");
+ },
+
+ //@deprecated This function will be deprecated sooner or later please use parser.registerParser
+ /**
+ * Register a custom Widget reader
+ * @param classType
+ * @param ins
+ * @param object
+ * @param callback
+ * @deprecated This function will be deprecated sooner or later please use parser.registerParser
+ */
+ registerTypeAndCallBack: function (classType, ins, object, callback) {
+ var parser = ccs._load.getParser("ccui")["*"];
+ var func = callback.bind(object);
+ parser.registerParser(classType, function (options, resourcePath) {
+ var widget = new ins();
+ var uiOptions = options["options"];
+ object.setPropsFromJsonDictionary && object.setPropsFromJsonDictionary(widget, uiOptions);
+ this.generalAttributes(widget, uiOptions);
+ var customProperty = uiOptions["customProperty"];
+ if (customProperty)
+ customProperty = JSON.parse(customProperty);
+ else
+ customProperty = {};
+ func(classType, widget, customProperty);
+ this.colorAttributes(widget, uiOptions);
+ this.anchorPointAttributes(widget, uiOptions);
+ this.parseChild.call(this, widget, options, resourcePath);
+ return widget;
+ });
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Gets the version number by version string.
+ * @param {String} version version string.
+ * @returns {Number}
+ */
+ getVersionInteger: function (version) {
+ if (!version || typeof version !== "string") return 0;
+ var arr = version.split(".");
+ if (arr.length !== 4)
+ return 0;
+ var num = 0;
+ arr.forEach(function (n, i) {
+ num += n * Math.pow(10, 3 - i);
+ });
+ return num;
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * stores the designSize of UI file.
+ * @param {String} fileName
+ * @param {cc.Size} size
+ */
+ storeFileDesignSize: function (fileName, size) {
+ this._fileDesignSizes[fileName] = size;
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Gets the design size by filename.
+ * @param {String} fileName
+ * @returns {cc.Size}
+ */
+ getFileDesignSize: function (fileName) {
+ return this._fileDesignSizes[fileName];
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Returns the file path
+ * @returns {string}
+ */
+ getFilePath: function () {
+ return this._filePath;
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ setFilePath: function (path) {
+ this._filePath = path;
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Returns the parsed object map. (analytic function)
+ * @returns {Object}
+ */
+ getParseObjectMap: function () {
+ return ccs._load.getParser("ccui")["*"]["parsers"];
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Returns the parsed callback map. (analytic function)
+ * @returns {*}
+ */
+ getParseCallBackMap: function () {
+ return ccs._load.getParser("ccui")["*"]["parsers"];
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ clear: function () {
+ }
+ };
+
+ var parser = ccs._load.getParser("ccui")["*"];
+ ccs.imageViewReader = {setPropsFromJsonDictionary: parser.ImageViewAttributes};
+ ccs.buttonReader = {setPropsFromJsonDictionary: parser.ButtonAttributes};
+ ccs.checkBoxReader = {setPropsFromJsonDictionary: parser.CheckBoxAttributes};
+ ccs.labelAtlasReader = {setPropsFromJsonDictionary: parser.TextAtlasAttributes};
+ ccs.labelBMFontReader = {setPropsFromJsonDictionary: parser.TextBMFontAttributes};
+ ccs.labelReader = {setPropsFromJsonDictionary: parser.TextAttributes};
+ ccs.layoutReader = {setPropsFromJsonDictionary: parser.LayoutAttributes};
+ ccs.listViewReader = {setPropsFromJsonDictionary: parser.ListViewAttributes};
+ ccs.loadingBarReader = {setPropsFromJsonDictionary: parser.LoadingBarAttributes};
+ ccs.pageViewReader = {setPropsFromJsonDictionary: parser.PageViewAttributes};
+ ccs.scrollViewReader = {setPropsFromJsonDictionary: parser.ScrollViewAttributes};
+ ccs.sliderReader = {setPropsFromJsonDictionary: parser.SliderAttributes};
+ ccs.textFieldReader = {setPropsFromJsonDictionary: parser.TextFieldAttributes};
+})();
+
+(function () {
+ ccs.sceneReader = {
+
+ _node: null,
+
+ //@deprecated This function will be deprecated sooner or later please use ccs.load
+ /**
+ * Create Scene Node
+ * @param file
+ * @returns {*}
+ */
+ createNodeWithSceneFile: function (file) {
+ var node = ccs._load(file, "scene");
+ this._node = node;
+ return node;
+ },
+
+ /**
+ * Get a node by tag.
+ * @param {Number} tag
+ * @returns {cc.Node|null}
+ */
+ getNodeByTag: function (tag) {
+ if (this._node == null)
+ return null;
+ if (this._node.getTag() === tag)
+ return this._node;
+ return this._nodeByTag(this._node, tag);
+ },
+
+ _nodeByTag: function (parent, tag) {
+ if (parent == null)
+ return null;
+ var retNode = null;
+ var children = parent.getChildren();
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if (child && child.getTag() === tag) {
+ retNode = child;
+ break;
+ } else {
+ retNode = this._nodeByTag(child, tag);
+ if (retNode)
+ break;
+ }
+ }
+ return retNode;
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Returns the version of ccs.SceneReader.
+ * @returns {string}
+ */
+ version: function () {
+ return "*";
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Sets the listener to reader.
+ * Cannot use
+ */
+ setTarget: function () {
+ },
+
+ //@deprecated This function will be deprecated sooner or later
+ /**
+ * Clear all triggers and stops all sounds.
+ */
+ clear: function () {
+ ccs.triggerManager.removeAll();
+ cc.audioEngine.end();
+ }
+ };
+})();
diff --git a/extensions/cocostudio/loader/parsers/scene-1.x.js b/extensions/cocostudio/loader/parsers/scene-1.x.js
new file mode 100644
index 0000000000..8982f26bfc
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/scene-1.x.js
@@ -0,0 +1,264 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function (load, baseParser) {
+
+ var Parser = baseParser.extend({
+
+ getNodeJson: function (json) {
+ return json;
+ },
+
+ parseNode: function (json, resourcePath) {
+ var parser = this.parsers[this.getClass(json)];
+ var node = null;
+ if (parser)
+ node = parser.call(this, json, resourcePath);
+ else
+ cc.log("Can't find the parser : %s", this.getClass(json));
+
+ return node;
+ },
+
+ deferred: function (json, resourcePath, node, file) {
+ ccs.triggerManager.parse(json["Triggers"] || []);
+ if (ccs.sceneReader)
+ ccs.sceneReader._node = node;
+ },
+
+ setPropertyFromJsonDict: function (node, json) {
+ var x = (cc.isUndefined(json["x"])) ? 0 : json["x"];
+ var y = (cc.isUndefined(json["y"])) ? 0 : json["y"];
+ node.setPosition(x, y);
+
+ var bVisible = Boolean((cc.isUndefined(json["visible"])) ? 1 : json["visible"]);
+ node.setVisible(bVisible);
+
+ var nTag = (cc.isUndefined(json["objecttag"])) ? -1 : json["objecttag"];
+ node.setTag(nTag);
+
+ var nZorder = (cc.isUndefined(json["zorder"])) ? 0 : json["zorder"];
+ node.setLocalZOrder(nZorder);
+
+ var fScaleX = (cc.isUndefined(json["scalex"])) ? 1 : json["scalex"];
+ var fScaleY = (cc.isUndefined(json["scaley"])) ? 1 : json["scaley"];
+ node.setScaleX(fScaleX);
+ node.setScaleY(fScaleY);
+
+ var fRotationZ = (cc.isUndefined(json["rotation"])) ? 0 : json["rotation"];
+ node.setRotation(fRotationZ);
+
+ var sName = json["name"] || "";
+ node.setName(sName);
+ }
+
+ });
+
+ var parser = new Parser();
+
+ parser.parseChild = function (node, objects, resourcePath) {
+ for (var i = 0; i < objects.length; i++) {
+ var child,
+ options = objects[i];
+ if (options)
+ child = this.parseNode(options, resourcePath);
+ if (child)
+ node.addChild(child);
+ }
+ };
+
+ var componentsParser = {
+ "CCSprite": function (node, component, resourcePath) {
+ var child = new cc.Sprite();
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ if (type === 0)
+ child.setTexture(path);
+ else if (type === 1) {
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
+ child.setSpriteFrame(spriteFrame);
+ }
+ });
+ var render = new ccs.ComRender(child, "CCSprite");
+ node.addComponent(render);
+ return render;
+ },
+ "CCTMXTiledMap": function (node, component, resourcePath) {
+ var child = null;
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ if (type === 0)
+ child = new cc.TMXTiledMap(path);
+ });
+ var render = new ccs.ComRender(child, "CCTMXTiledMap");
+ node.addComponent(render);
+ return render;
+ },
+ "CCParticleSystemQuad": function (node, component, resourcePath) {
+ var child = null;
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ if (type === 0)
+ child = new cc.ParticleSystem(path);
+ else
+ cc.log("unknown resourcetype on CCParticleSystemQuad!");
+ child.setPosition(0, 0);
+ });
+ var render = new ccs.ComRender(child, "CCParticleSystemQuad");
+ node.addComponent(render);
+ return render;
+ },
+ "CCArmature": function (node, component, resourcePath) {
+ var child = null;
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ if (type === 0) {
+ var jsonDict = cc.loader.getRes(path);
+ if (!jsonDict) cc.log("Please load the resource [%s] first!", path);
+ var armature_data = jsonDict["armature_data"];
+ var subData = armature_data[0];
+ var name = subData["name"];
+ ccs.armatureDataManager.addArmatureFileInfo(path);
+ child = new ccs.Armature(name);
+ }
+ });
+ if (child) {
+ var render = new ccs.ComRender(child, "CCArmature");
+ node.addComponent(render);
+ var actionName = component["selectedactionname"];
+ if (actionName && child.getAnimation())
+ child.getAnimation().play(actionName);
+
+ return render;
+ }
+
+ },
+ "CCComAudio": function (node, component, resourcePath) {
+ var audio = null;
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ if (type === 0) {
+ audio = new ccs.ComAudio();
+ audio.preloadEffect(path);
+ var name = component["name"];
+ if (name)
+ audio.setName(name);
+ node.addComponent(audio);
+ }
+ });
+ },
+ "CCComAttribute": function (node, component, resourcePath) {
+ var attribute = null;
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ if (type === 0) {
+ attribute = new ccs.ComAttribute();
+ if (path !== "")
+ attribute.parse(path);
+ node.addComponent(attribute);
+ } else
+ cc.log("unknown resourcetype on CCComAttribute!");
+ });
+ return attribute;
+ },
+ "CCBackgroundAudio": function (node, component, resourcePath) {
+ var audio = null;
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ if (type === 0) {
+ audio = new ccs.ComAudio();
+ audio.preloadBackgroundMusic(path);
+ audio.setFile(path);
+ var bLoop = Boolean(component["loop"] || 0);
+ audio.setLoop(bLoop);
+ var name = component["name"];
+ if (name)
+ audio.setName(name);
+ node.addComponent(audio);
+ audio.playBackgroundMusic(path, bLoop);
+ }
+ });
+ },
+ "GUIComponent": function (node, component, resourcePath) {
+ var widget = null;
+ loadTexture(component["fileData"], resourcePath, function (path, type) {
+ widget = ccs._load(path, "ccui");
+ });
+ var render = new ccs.ComRender(widget, "GUIComponent");
+ node.addComponent(render);
+ return render;
+ },
+ "CCScene": function () {
+ }
+ };
+ var loadedPlist = {};
+ var loadTexture = function (json, resourcePath, cb) {
+ if (json != null) {
+ var path = json["path"];
+ var type = json["resourceType"];
+ var plist = json["plist"];
+ if (!path)
+ return;
+ if (plist) {
+ if (cc.loader.getRes(resourcePath + plist)) {
+ loadedPlist[resourcePath + plist] = true;
+ cc.spriteFrameCache.addSpriteFrames(resourcePath + plist);
+ } else {
+ if (!loadedPlist[resourcePath + plist])
+ cc.log("%s need to be preloaded", resourcePath + plist);
+ }
+ }
+ if (type !== 0)
+ cb(path, type);
+ else
+ cb(resourcePath + path, type);
+ }
+ };
+
+ parser.parseComponents = function (node, json, resourcePath) {
+ if (!node || !json)
+ return;
+ json.forEach(function (component) {
+ var parser = componentsParser[component["classname"]];
+ var render = null;
+ if (parser)
+ render = parser(node, component, resourcePath);
+ else
+ cc.log("Can't find the component parser : %s", component["classname"]);
+ var name = component["name"];
+ if (render && name) {
+ render.setName(name);
+ }
+ });
+ };
+
+ parser.registerParser("CCNode", function (options, resourcePath) {
+ var node = new cc.Node();
+ this.setPropertyFromJsonDict(node, options);
+ this.parseChild.call(this, node, options["gameobjects"], resourcePath);
+ this.parseComponents(node, options["components"], resourcePath);
+ var size = options["CanvasSize"];
+ if (size)
+ node.setContentSize(cc.size(size["_width"], size["_height"]));
+
+ return node;
+ });
+
+ load.registerParser("scene", "*", parser);
+
+
+})(ccs._load, ccs._parser);
diff --git a/extensions/cocostudio/loader/parsers/timelineParser-1.x.js b/extensions/cocostudio/loader/parsers/timelineParser-1.x.js
new file mode 100644
index 0000000000..1e9d907805
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/timelineParser-1.x.js
@@ -0,0 +1,291 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function (load, baseParser) {
+
+ var loadedPlist = {};
+
+ var Parser = baseParser.extend({
+
+ getNodeJson: function (json) {
+ return json["nodeTree"];
+ },
+
+ addSpriteFrame: function (plists, pngs, resourcePath) {
+ if (!plists || !pngs || plists.length !== pngs.length)
+ return;
+ for (var i = 0; i < plists.length; i++) {
+ var plist = resourcePath + plists[i];
+ if (!cc.loader.getRes(plist) && !loadedPlist[plist])
+ cc.log("%s need to be preloaded", plist);
+ else
+ loadedPlist[plist] = true;
+ cc.spriteFrameCache.addSpriteFrames(
+ plist,
+ resourcePath + pngs[i]
+ );
+ }
+ },
+
+ pretreatment: function (json, resourcePath, file) {
+ this.addSpriteFrame(json["textures"], json["texturesPng"], resourcePath);
+ }
+
+ });
+ var parser = new Parser();
+
+ parser.generalAttributes = function (node, options) {
+ var width = options["width"] != null ? options["width"] : 0;
+ var height = options["height"] != null ? options["height"] : 0;
+ var x = options["x"] != null ? options["x"] : 0;
+ var y = options["y"] != null ? options["y"] : 0;
+ var scalex = options["scaleX"] != null ? options["scaleX"] : 1;
+ var scaley = options["scaleY"] != null ? options["scaleY"] : 1;
+ var rotation = options["rotation"] != null ? options["rotation"] : 0;
+ var rotationSkewX = options["rotationSkewX"] != null ? options["rotationSkewX"] : 0;
+ var rotationSkewY = options["rotationSkewY"] != null ? options["rotationSkewY"] : 0;
+ var skewx = options["skewX"] != null ? options["skewX"] : 0;
+ var skewy = options["skewY"] != null ? options["skewY"] : 0;
+ var anchorx = options["anchorPointX"] != null ? options["anchorPointX"] : 0.5;
+ var anchory = options["anchorPointY"] != null ? options["anchorPointY"] : 0.5;
+ var alpha = options["opacity"] != null ? options["opacity"] : 255;
+ var red = options["colorR"] != null ? options["colorR"] : 255;
+ var green = options["colorG"] != null ? options["colorG"] : 255;
+ var blue = options["colorB"] != null ? options["colorB"] : 255;
+ var zorder = options["colorR"] != null ? options["colorR"] : 0;
+ var tag = options["tag"] != null ? options["tag"] : 0;
+ var actionTag = options["actionTag"] != null ? options["actionTag"] : 0;
+ var visible = options["visible"] != null ? options["visible"] : true;
+
+ if (x != 0 || y != 0)
+ node.setPosition(cc.p(x, y));
+ if (scalex != 1)
+ node.setScaleX(scalex);
+ if (scaley != 1)
+ node.setScaleY(scaley);
+ if (rotation != 0)
+ node.setRotation(rotation);
+ if (rotationSkewX != 0)
+ node.setRotationX(rotationSkewX);
+ if (rotationSkewY != 0)
+ node.setRotationY(rotationSkewY);
+ if (skewx != 0)
+ node.setSkewX(skewx);
+ if (skewy != 0)
+ node.setSkewY(skewy);
+ if (anchorx != 0.5 || anchory != 0.5)
+ node.setAnchorPoint(cc.p(anchorx, anchory));
+ if (width != 0 || height != 0)
+ node.setContentSize(cc.size(width, height));
+ if (zorder != 0)
+ node.setLocalZOrder(zorder);
+ if (visible != true)
+ node.setVisible(visible);
+
+ if (alpha != 255) {
+ node.setOpacity(alpha);
+ }
+ if (red != 255 || green != 255 || blue != 255) {
+ node.setColor(cc.color(red, green, blue));
+ }
+
+
+ node.setTag(tag);
+ node.setUserObject(new ccs.ActionTimelineData(actionTag));
+ };
+
+ parser.parseComponent = function (node, options) {
+ if (!options) return;
+ for (var i = 0; i < options.length; ++i) {
+ var dic = options[i];
+ var component = this.loadComponent(dic);
+ if (component) {
+ node.addComponent(component);
+ }
+ }
+ };
+
+ parser.parseChild = function (parse, widget, options, resourcePath) {
+ var children = options["children"];
+ for (var i = 0; i < children.length; i++) {
+ var child = this.parseNode(children[i], resourcePath);
+ if (child) {
+ if (widget instanceof ccui.PageView) {
+ if (child instanceof ccui.Layout)
+ widget.addPage(child);
+ } else {
+ if (widget instanceof ccui.ListView) {
+ if (child instanceof ccui.Widget)
+ widget.pushBackCustomItem(child);
+ } else {
+ if (!(widget instanceof ccui.Layout) && child instanceof ccui.Widget) {
+ if (child.getPositionType() === ccui.Widget.POSITION_PERCENT) {
+ var position = child.getPositionPercent();
+ var anchor = widget.getAnchorPoint();
+ child.setPositionPercent(cc.p(position.x + anchor.x, position.y + anchor.y));
+ }
+ //To make up for the studio positioning error problem
+ var AnchorPointIn = widget.getAnchorPointInPoints();
+ child.setPosition(cc.p(child.getPositionX() + AnchorPointIn.x, child.getPositionY() + AnchorPointIn.y));
+ }
+ widget.addChild(child);
+ }
+ }
+ }
+ }
+ };
+
+ parser.initNode = function (options) {
+ var node = new cc.Node();
+ this.generalAttributes(node, options);
+ return node;
+ };
+ parser.initSubGraph = function (options) {
+ var filePath = options["fileName"];
+
+ var node;
+ if (filePath && "" !== filePath) {
+ node = this.createNode(filePath);
+ } else {
+ node = new ccs.Node();
+ }
+ this.generalAttributes(node, options);
+ return node;
+ };
+ parser.initSprite = function (options, resourcePath) {
+ var path = options["fileName"];
+ var sprite;
+ if (path != null) {
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
+ if (!spriteFrame) {
+ path = resourcePath + path;
+ sprite = new ccs.Sprite(path);
+ } else {
+ sprite = ccs.Sprite.createWithSpriteFrame(spriteFrame);
+ }
+
+ if (!sprite) {
+ sprite = new cc.Sprite();
+ cc.log("filePath is empty. Create a sprite with no texture");
+ }
+ } else {
+ sprite = new ccs.Sprite();
+ }
+ this.generalAttributes(sprite, options);
+ var flipX = options["flipX"];
+ var flipY = options["flipY"];
+
+ if (flipX != false)
+ sprite.setFlippedX(flipX);
+ if (flipY != false)
+ sprite.setFlippedY(flipY);
+ return sprite;
+ };
+ parser.initParticle = function (options, resourcePath) {
+ var filePath = options["plistFile"];
+ var num = options["tmxFile"];
+ var particle = new cc.ParticleSystemQuad(filePath);
+ particle.setTotalParticles(num);
+ this.generalAttributes(particle, options);
+ return particle;
+ };
+ parser.initTMXTiledMap = function (options, resourcePath) {
+ var tmxFile = options["tmxFile"];
+ var tmxString = options["tmxString"];
+ //todo check path and resourcePath
+ var path = options["resourcePath"];
+
+ var tmx = null;
+ if (tmxFile && "" !== tmxFile) {
+ tmx = new cc.TMXTiledMap(tmxFile);
+ } else if (tmxString && "" !== tmxString && path && "" !== path) {
+ tmx = new cc.TMXTiledMap(tmxString, path);
+ }
+ return tmx;
+ };
+ var uiParser = load.getParser("ccui")["*"];
+ parser.initWidget = function (options, resourcePath) {
+ var type = options["classname"];
+
+ var parser = uiParser.parsers[type];
+ if (!parser)
+ return cc.log("%s parser is not found", type);
+
+ var node = parser.call(uiParser, options, resourcePath);
+ if (node) {
+ var rotationSkewX = options["rotationSkewX"];
+ var rotationSkewY = options["rotationSkewY"];
+ var skewx = options["skewX"];
+ var skewy = options["skewY"];
+ if (rotationSkewX != 0)
+ node.setRotationX(rotationSkewX);
+ if (rotationSkewY != 0)
+ node.setRotationY(rotationSkewY);
+ if (skewx != 0)
+ node.setSkewX(skewx);
+ if (skewy != 0)
+ node.setSkewY(skewy);
+
+ var actionTag = options["actionTag"];
+ node.setUserObject(new ccs.ActionTimelineData(actionTag));
+ }
+ return node;
+ };
+
+ var register = [
+ {name: "Node", handle: parser.initNode},
+ {name: "SubGraph", handle: parser.initSubGraph},
+ {name: "Sprite", handle: parser.initSprite},
+ {name: "Particle", handle: parser.initParticle},
+ {name: "TMXTiledMap", handle: parser.initTMXTiledMap},
+
+ {name: "Widget", handle: parser.initWidget},
+ {name: "Panel", handle: parser.initWidget},
+ {name: "Button", handle: parser.initWidget},
+ {name: "CheckBox", handle: parser.initWidget},
+ {name: "ImageView", handle: parser.initWidget},
+ {name: "LabelAtlas", handle: parser.initWidget},
+ {name: "LabelBMFont", handle: parser.initWidget},
+ {name: "Label", handle: parser.initWidget},
+ {name: "ListView", handle: parser.initWidget},
+ {name: "LoadingBar", handle: parser.initWidget},
+ {name: "PageView", handle: parser.initWidget},
+ {name: "ScrollView", handle: parser.initWidget},
+ {name: "Slider", handle: parser.initWidget},
+ {name: "TextField", handle: parser.initWidget}
+ ];
+
+ register.forEach(function (item) {
+ parser.registerParser(item.name, function (options, parse, resourcePath) {
+ var node = item.handle.call(this, options["options"]);
+ this.parseComponent(node, options["components"]);
+ this.parseChild(parse, node, options, resourcePath);
+ return node;
+ });
+ });
+
+ load.registerParser("timeline", "0.*", parser);
+ load.registerParser("timeline", "1.*", parser);
+
+})(ccs._load, ccs._parser);
diff --git a/extensions/cocostudio/loader/parsers/timelineParser-2.x.js b/extensions/cocostudio/loader/parsers/timelineParser-2.x.js
new file mode 100644
index 0000000000..c823ce8737
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/timelineParser-2.x.js
@@ -0,0 +1,1409 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function (load, baseParser) {
+
+ var DEBUG = false;
+
+ var Parser = baseParser.extend({
+
+ parse: function (file, json, path) {
+ var resourcePath;
+ if (path !== undefined)
+ resourcePath = path;
+ else
+ resourcePath = this._dirname(file);
+ this.pretreatment(json, resourcePath, file);
+ var node = this.parseNode(this.getNodeJson(json), resourcePath);
+ this.deferred(json, resourcePath, node, file);
+ return node;
+ },
+
+ getNodeJson: function (json) {
+ var content = json["Content"];
+ if (content["ObjectData"])
+ return content["ObjectData"];
+
+ return content["Content"]["ObjectData"];
+ },
+
+ getClass: function (json) {
+ return json["ctype"];
+ }
+
+ });
+ var parser = new Parser();
+
+
+ var getParam = function (value, dValue) {
+ if (value === undefined)
+ return dValue;
+ else
+ return value;
+ };
+
+ //////////
+ // NODE //
+ //////////
+
+ parser.generalAttributes = function (node, json) {
+ if (json["Name"] != null)
+ node.setName(json["Name"]);
+
+ var position = json["Position"];
+ if (position != null && (position["X"] != null || position["Y"] != null))
+ node.setPosition(cc.p(position["X"] || 0, position["Y"] || 0));
+
+ var scale = json["Scale"];
+ if (scale != null) {
+ if (scale["ScaleX"] != null)
+ node.setScaleX(scale["ScaleX"]);
+ if (scale["ScaleY"] != null)
+ node.setScaleY(scale["ScaleY"]);
+ }
+
+ var rotationSkewX = json["RotationSkewX"];
+ if (rotationSkewX != null)
+ node.setRotationX(rotationSkewX);
+
+ var rotationSkewY = json["RotationSkewY"];
+ if (json["RotationSkewY"] != null)
+ node.setRotationY(rotationSkewY);
+
+
+ var anchor = json["AnchorPoint"];
+ if (anchor != null) {
+ if (anchor["ScaleX"] == null)
+ anchor["ScaleX"] = 0;
+ if (anchor["ScaleY"] == null)
+ anchor["ScaleY"] = 0;
+ if (anchor["ScaleX"] != 0.5 || anchor["ScaleY"] != 0.5)
+ node.setAnchorPoint(cc.p(anchor["ScaleX"], anchor["ScaleY"]));
+ }
+
+ if (json["ZOrder"] != null)
+ node.setLocalZOrder(json["ZOrder"]);
+
+ var visible = getParam(json["VisibleForFrame"], true);
+ node.setVisible(visible);
+
+ var size = json["Size"];
+ if (size)
+ setContentSize(node, size);
+
+ if (json["Alpha"] != null)
+ node.setOpacity(json["Alpha"]);
+
+ node.setTag(json["Tag"] || 0);
+
+ var actionTag = json["ActionTag"] || 0;
+ var extensionData = new ccs.ComExtensionData();
+ var customProperty = json["UserData"];
+ if (customProperty !== undefined)
+ extensionData.setCustomProperty(customProperty);
+ extensionData.setActionTag(actionTag);
+ if (node.getComponent("ComExtensionData"))
+ node.removeComponent("ComExtensionData");
+ node.addComponent(extensionData);
+
+ node.setCascadeColorEnabled(true);
+ node.setCascadeOpacityEnabled(true);
+
+ setLayoutComponent(node, json);
+ };
+
+ parser.parseChild = function (node, children, resourcePath) {
+ if (!node || !children) return;
+ for (var i = 0; i < children.length; i++) {
+ var child = this.parseNode(children[i], resourcePath);
+ if (child) {
+ if (node instanceof ccui.PageView) {
+ if (child instanceof ccui.Layout)
+ node.addPage(child);
+ } else {
+ if (node instanceof ccui.ListView) {
+ if (child instanceof ccui.Widget)
+ node.pushBackCustomItem(child);
+ } else {
+ if (!(node instanceof ccui.Layout) && child instanceof ccui.Widget) {
+ if (child.getPositionType() === ccui.Widget.POSITION_PERCENT) {
+ var position = child.getPositionPercent();
+ var anchor = node.getAnchorPoint();
+ child.setPositionPercent(cc.p(position.x + anchor.x, position.y + anchor.y));
+ }
+ }
+ node.addChild(child);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * SingleNode
+ * @param json
+ * @returns {cc.Node}
+ */
+ parser.initSingleNode = function (json) {
+ var node = new cc.Node();
+
+ this.generalAttributes(node, json);
+ var color = json["CColor"];
+ if (color != null)
+ node.setColor(getColor(color));
+
+ return node;
+ };
+
+ /**
+ * Sprite
+ * @param json
+ * @param resourcePath
+ * @returns {cc.Sprite}
+ */
+ parser.initSprite = function (json, resourcePath) {
+ var node = new cc.Sprite();
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ if (type === 0)
+ node.setTexture(path);
+ else if (type === 1) {
+ var spriteFrame = cc.spriteFrameCache.getSpriteFrame(path);
+ if (spriteFrame)
+ node.setSpriteFrame(spriteFrame);
+ }
+ });
+
+ var blendData = json["BlendFunc"];
+ if (json["BlendFunc"]) {
+ var blendFunc = cc.BlendFunc.ALPHA_PREMULTIPLIED;
+ if (blendData["Src"] !== undefined)
+ blendFunc.src = blendData["Src"];
+ if (blendData["Dst"] !== undefined)
+ blendFunc.dst = blendData["Dst"];
+ node.setBlendFunc(blendFunc);
+ }
+
+ if (json["FlipX"])
+ node.setFlippedX(true);
+ if (json["FlipY"])
+ node.setFlippedY(true);
+
+ this.generalAttributes(node, json);
+ var color = json["CColor"];
+ if (color != null)
+ node.setColor(getColor(color));
+
+ return node;
+ };
+
+ /**
+ * Particle
+ * @param json
+ * @param resourcePath
+ * @returns {*}
+ */
+ parser.initParticle = function (json, resourcePath) {
+ var node,
+ self = this;
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ if (!cc.loader.getRes(path))
+ cc.log("%s need to be preloaded", path);
+ node = new cc.ParticleSystem(path);
+ self.generalAttributes(node, json);
+ node.setPositionType(cc.ParticleSystem.TYPE_GROUPED);
+ !cc.sys.isNative && node.setDrawMode(cc.ParticleSystem.TEXTURE_MODE);
+
+ var blendData = json["BlendFunc"];
+ if (json["BlendFunc"]) {
+ var blendFunc = cc.BlendFunc.ALPHA_PREMULTIPLIED;
+ if (blendData["Src"] !== undefined)
+ blendFunc.src = blendData["Src"];
+ if (blendData["Dst"] !== undefined)
+ blendFunc.dst = blendData["Dst"];
+ node.setBlendFunc(blendFunc);
+ }
+ });
+ return node;
+ };
+
+
+ ////////////
+ // WIDGET //
+ ////////////
+
+ parser.widgetAttributes = function (widget, json, enableContent) {
+ widget.setCascadeColorEnabled(true);
+ widget.setCascadeOpacityEnabled(true);
+
+ widget.setUnifySizeEnabled(false);
+ //widget.setLayoutComponentEnabled(true);
+ widget.ignoreContentAdaptWithSize(false);
+ !enableContent && setContentSize(widget, json["Size"]);
+
+ var name = json["Name"];
+ if (name)
+ widget.setName(name);
+
+ var actionTag = json["ActionTag"] || 0;
+ widget.setActionTag(actionTag);
+ var extensionData = new ccs.ComExtensionData();
+ var customProperty = json["UserData"];
+ if (customProperty !== undefined)
+ extensionData.setCustomProperty(customProperty);
+ extensionData.setActionTag(actionTag);
+ if (widget.getComponent("ComExtensionData"))
+ widget.removeComponent("ComExtensionData");
+ widget.addComponent(extensionData);
+
+ var rotationSkewX = json["RotationSkewX"];
+ if (rotationSkewX)
+ widget.setRotationX(rotationSkewX);
+
+ var rotationSkewY = json["RotationSkewY"];
+ if (rotationSkewY)
+ widget.setRotationY(rotationSkewY);
+
+ //var rotation = json["Rotation"];
+
+ var flipX = json["FlipX"];
+ if (flipX)
+ widget.setFlippedX(true);
+
+ var flipY = json["FlipY"];
+ if (flipY)
+ widget.setFlippedY(true);
+
+ var zOrder = json["zOrder"];
+ if (zOrder != null)
+ widget.setLocalZOrder(zOrder);
+
+ //var visible = json["Visible"];
+
+ var visible = getParam(json["VisibleForFrame"], true);
+ widget.setVisible(visible);
+
+ var alpha = json["Alpha"];
+ if (alpha != null)
+ widget.setOpacity(alpha);
+
+ widget.setTag(json["Tag"] || 0);
+
+ var touchEnabled = json["TouchEnable"] || false;
+ widget.setTouchEnabled(touchEnabled);
+
+ // -- var frameEvent = json["FrameEvent"];
+
+ var callBackType = json["CallBackType"];
+ if (callBackType != null)
+ widget.setCallbackType(callBackType);
+
+ var callBackName = json["CallBackName"];
+ if (callBackName)
+ widget.setCallbackName(callBackName);
+
+ var position = json["Position"];
+ if (position != null)
+ widget.setPosition(position["X"] || 0, position["Y"] || 0);
+
+ var scale = json["Scale"];
+ if (scale != null) {
+ var scaleX = getParam(scale["ScaleX"], 1);
+ var scaleY = getParam(scale["ScaleY"], 1);
+ widget.setScaleX(scaleX);
+ widget.setScaleY(scaleY);
+ }
+
+ var anchorPoint = json["AnchorPoint"];
+ if (anchorPoint != null)
+ widget.setAnchorPoint(anchorPoint["ScaleX"] || 0, anchorPoint["ScaleY"] || 0);
+
+ var color = json["CColor"];
+ if (color != null)
+ widget.setColor(getColor(color));
+
+ setLayoutComponent(widget, json);
+ bindCallback(widget, json);
+ };
+
+ var bindCallback = function (widget, json) {
+ var callBackType = json["CallBackType"];
+ var callBackName = json["CallBackName"];
+ var callBack = function (e) {
+ if (typeof widget[callBackName] === "function")
+ widget[callBackName](e);
+ };
+ if (callBackType === "Click") {
+ widget.addClickEventListener(callBack);
+ } else if (callBackType === "Touch") {
+ widget.addTouchEventListener(callBack);
+ } else if (callBackType === "Event") {
+ widget.addCCSEventListener(callBack);
+ }
+ };
+
+ var setLayoutComponent = function (widget, json) {
+
+ var layoutComponent = ccui.LayoutComponent.bindLayoutComponent(widget);
+ if (!layoutComponent)
+ return;
+
+ var positionXPercentEnabled = json["PositionPercentXEnable"] || json["PositionPercentXEnabled"] || false;
+ var positionYPercentEnabled = json["PositionPercentYEnable"] || json["PositionPercentYEnabled"] || false;
+ var positionXPercent = 0,
+ positionYPercent = 0,
+ PrePosition = json["PrePosition"];
+ if (PrePosition != null) {
+ positionXPercent = PrePosition["X"] || 0;
+ positionYPercent = PrePosition["Y"] || 0;
+ }
+ var sizeXPercentEnable = json["PercentWidthEnable"] || json["PercentWidthEnabled"] || false;
+ var sizeYPercentEnable = json["PercentHeightEnable"] || json["PercentHeightEnabled"] || false;
+ var sizeXPercent = 0,
+ sizeYPercent = 0,
+ PreSize = json["PreSize"];
+ if (PrePosition != null) {
+ sizeXPercent = PreSize["X"] || 0;
+ sizeYPercent = PreSize["Y"] || 0;
+ }
+ var stretchHorizontalEnabled = json["StretchWidthEnable"] || false;
+ var stretchVerticalEnabled = json["StretchHeightEnable"] || false;
+ var horizontalEdge = json["HorizontalEdge"];// = ccui.LayoutComponent.horizontalEdge.LEFT;
+ var verticalEdge = json["VerticalEdge"]; // = ccui.LayoutComponent.verticalEdge.TOP;
+ var leftMargin = json["LeftMargin"] || 0;
+ var rightMargin = json["RightMargin"] || 0;
+ var topMargin = json["TopMargin"] || 0;
+ var bottomMargin = json["BottomMargin"] || 0;
+
+ layoutComponent.setPositionPercentXEnabled(positionXPercentEnabled);
+ layoutComponent.setPositionPercentYEnabled(positionYPercentEnabled);
+ layoutComponent.setPositionPercentX(positionXPercent);
+ layoutComponent.setPositionPercentY(positionYPercent);
+ layoutComponent.setPercentWidthEnabled(sizeXPercentEnable);
+ layoutComponent.setPercentHeightEnabled(sizeYPercentEnable);
+ layoutComponent.setPercentWidth(sizeXPercent);
+ layoutComponent.setPercentHeight(sizeYPercent);
+ layoutComponent.setPercentWidthEnabled(sizeXPercentEnable || sizeYPercentEnable);
+ layoutComponent.setStretchWidthEnabled(stretchHorizontalEnabled);
+ layoutComponent.setStretchHeightEnabled(stretchVerticalEnabled);
+
+ var horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.NONE;
+ if (horizontalEdge === "LeftEdge") {
+ horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.LEFT;
+ } else if (horizontalEdge === "RightEdge") {
+ horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.RIGHT;
+ } else if (horizontalEdge === "BothEdge") {
+ horizontalEdgeType = ccui.LayoutComponent.horizontalEdge.CENTER;
+ }
+ layoutComponent.setHorizontalEdge(horizontalEdgeType);
+
+ var verticalEdgeType = ccui.LayoutComponent.verticalEdge.NONE;
+ if (verticalEdge === "TopEdge") {
+ verticalEdgeType = ccui.LayoutComponent.verticalEdge.TOP;
+ } else if (verticalEdge === "BottomEdge") {
+ verticalEdgeType = ccui.LayoutComponent.verticalEdge.BOTTOM;
+ } else if (verticalEdge === "BothEdge") {
+ verticalEdgeType = ccui.LayoutComponent.verticalEdge.CENTER;
+ }
+ layoutComponent.setVerticalEdge(verticalEdgeType);
+
+ layoutComponent.setTopMargin(topMargin);
+ layoutComponent.setBottomMargin(bottomMargin);
+ layoutComponent.setLeftMargin(leftMargin);
+ layoutComponent.setRightMargin(rightMargin);
+
+ layoutComponent.setVerticalEdge(verticalEdgeType);
+
+ layoutComponent.setTopMargin(topMargin);
+ layoutComponent.setBottomMargin(bottomMargin);
+ layoutComponent.setLeftMargin(leftMargin);
+ layoutComponent.setRightMargin(rightMargin);
+ };
+
+ var setLayoutBackground = function (layout, single, first, end) {
+ if (layout.getBackGroundColorType() === 2) {
+ first = first || {};
+ end = end || {};
+ layout.setBackGroundColor(getColor(first), getColor(end));
+ } else {
+ single = single || {};
+ layout.setBackGroundColor(getColor(single));
+ }
+ };
+
+ var setLayoutBackgroundVector = function (widget, vector) {
+ var x = vector["ScaleX"] || 0;
+ var y = vector["ScaleY"] || 0;
+ widget.setBackGroundColorVector(cc.p(x, y));
+ };
+
+ /**
+ * Layout
+ * @param json
+ * @param resourcePath
+ * @returns {ccui.Layout}
+ */
+ parser.initPanel = function (json, resourcePath) {
+ var widget = new ccui.Layout();
+
+ this.widgetAttributes(widget, json);
+
+ var clipEnabled = json["ClipAble"] || false;
+ if (clipEnabled != null)
+ widget.setClippingEnabled(clipEnabled);
+
+ var colorType = getParam(json["ComboBoxIndex"], 0);
+ widget.setBackGroundColorType(colorType);
+
+ var bgColorOpacity = getParam(json["BackColorAlpha"], 255);
+ if (bgColorOpacity != null)
+ widget.setBackGroundColorOpacity(bgColorOpacity);
+
+ var backGroundScale9Enabled = json["Scale9Enable"];
+ if (backGroundScale9Enabled != null)
+ widget.setBackGroundImageScale9Enabled(backGroundScale9Enabled);
+
+ var opacity = getParam(json["Alpha"], 255);
+ widget.setOpacity(opacity);
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ widget.setBackGroundImage(path, type);
+ });
+
+ if (backGroundScale9Enabled) {
+ var scale9OriginX = json["Scale9OriginX"] || 0;
+ var scale9OriginY = json["Scale9OriginY"] || 0;
+
+ var scale9Width = json["Scale9Width"] || 0;
+ var scale9Height = json["Scale9Height"] || 0;
+
+ widget.setBackGroundImageCapInsets(cc.rect(
+ scale9OriginX, scale9OriginY, scale9Width, scale9Height
+ ));
+
+ setContentSize(widget, json["Size"]);
+ } else {
+ if (!widget.isIgnoreContentAdaptWithSize()) {
+ setContentSize(widget, json["Size"]);
+ }
+
+ }
+
+ setLayoutBackground(widget, json["SingleColor"], json["FirstColor"], json["EndColor"]);
+ setLayoutBackgroundVector(widget, json["ColorVector"]);
+
+ return widget;
+ };
+
+ /**
+ * Text
+ * @param json
+ * @param resourcePath
+ */
+ parser.initText = function (json, resourcePath) {
+
+ var widget = new ccui.Text();
+
+ var touchScaleEnabled = json["TouchScaleChangeAble"];
+ if (touchScaleEnabled != null)
+ widget.setTouchScaleChangeEnabled(touchScaleEnabled);
+
+ var text = json["LabelText"];
+ if (text != null)
+ widget.setString(text);
+
+ var fontSize = json["FontSize"];
+ if (fontSize != null)
+ widget.setFontSize(fontSize);
+
+ var fontName = json["FontName"];
+ if (fontName != null)
+ widget.setFontName(fontName);
+
+ var areaWidth = json["AreaWidth"];
+ var areaHeight = json["areaHeight"];
+ if (areaWidth && areaHeight)
+ widget.setTextAreaSize(cc.size(areaWidth, areaHeight));
+
+ var h_alignment = json["HorizontalAlignmentType"] || "HT_Left";
+ switch (h_alignment) {
+ case "HT_Right":
+ h_alignment = 2;
+ break;
+ case "HT_Center":
+ h_alignment = 1;
+ break;
+ case "HT_Left":
+ default:
+ h_alignment = 0;
+ }
+ widget.setTextHorizontalAlignment(h_alignment);
+
+ var v_alignment = json["VerticalAlignmentType"] || "VT_Top";
+ switch (v_alignment) {
+ case "VT_Bottom":
+ v_alignment = 2;
+ break;
+ case "VT_Center":
+ v_alignment = 1;
+ break;
+ case "VT_Top":
+ default:
+ v_alignment = 0;
+ }
+ widget.setTextVerticalAlignment(v_alignment);
+
+ var fontResource = json["FontResource"];
+ if (fontResource != null) {
+ var path = fontResource["Path"];
+ //resoutceType = fontResource["Type"];
+ if (path != null) {
+ if (cc.sys.isNative) {
+ fontName = cc.path.join(cc.loader.resPath, resourcePath, path);
+ } else {
+ fontName = path.match(/([^\/]+)\.(\S+)/);
+ fontName = fontName ? fontName[1] : "";
+ }
+ widget.setFontName(fontName);
+ }
+ }
+
+ if (json["OutlineEnabled"] && json["OutlineColor"] && widget.enableOutline)
+ widget.enableOutline(getColor(json["OutlineColor"]), getParam(json["OutlineSize"], 1));
+
+ if (json["ShadowEnabled"] && json["ShadowColor"] && widget.enableShadow)
+ widget.enableShadow(
+ getColor(json["ShadowColor"]),
+ cc.size(getParam(json["ShadowOffsetX"], 2), getParam(json["ShadowOffsetY"], -2)),
+ json["ShadowBlurRadius"] || 0
+ );
+
+ var isCustomSize = json["IsCustomSize"];
+ if (isCustomSize != null)
+ widget.ignoreContentAdaptWithSize(!isCustomSize);
+
+ widget.setUnifySizeEnabled(false);
+
+ var color = json["CColor"];
+ json["CColor"] = null;
+ widget.setTextColor(getColor(color));
+ this.widgetAttributes(widget, json, widget.isIgnoreContentAdaptWithSize());
+ json["CColor"] = color;
+ return widget;
+
+ };
+
+ /**
+ * Button
+ * @param json
+ * @param resourcePath
+ */
+ parser.initButton = function (json, resourcePath) {
+
+ var widget = new ccui.Button();
+
+ loadTexture(json["NormalFileData"], resourcePath, function (path, type) {
+ widget.loadTextureNormal(path, type);
+ });
+ loadTexture(json["PressedFileData"], resourcePath, function (path, type) {
+ widget.loadTexturePressed(path, type);
+ });
+ loadTexture(json["DisabledFileData"], resourcePath, function (path, type) {
+ widget.loadTextureDisabled(path, type);
+ });
+
+ var scale9Enabled = getParam(json["Scale9Enable"], false);
+ if (scale9Enabled) {
+ widget.setScale9Enabled(scale9Enabled);
+ }
+
+ var text = json["ButtonText"];
+ if (text != null)
+ widget.setTitleText(text);
+
+ var fontSize = json["FontSize"];
+ if (fontSize != null)
+ widget.setTitleFontSize(fontSize);
+
+ var fontName = json["FontName"];
+ if (fontName != null)
+ widget.setTitleFontName(fontName);
+
+ var textColor = json["TextColor"];
+ if (textColor != null)
+ widget.setTitleColor(getColor(textColor));
+
+ var displaystate = getParam(json["DisplayState"], true);
+ widget.setBright(displaystate);
+ widget.setEnabled(displaystate);
+
+ var fontResource = json["FontResource"];
+ if (fontResource != null) {
+ var path = fontResource["Path"];
+ //resoutceType = fontResource["Type"];
+ if (path != null) {
+ if (cc.sys.isNative) {
+ fontName = cc.path.join(cc.loader.resPath, resourcePath, path);
+ } else {
+ fontName = path.match(/([^\/]+)\.(\S+)/);
+ fontName = fontName ? fontName[1] : "";
+ }
+ widget.setTitleFontName(fontName);
+ }
+ }
+
+ var label = widget.getTitleRenderer();
+ if (label && json["ShadowEnabled"] && json["ShadowColor"] && label.enableShadow) {
+ label.enableShadow(
+ getColor(json["ShadowColor"]),
+ cc.size(getParam(json["ShadowOffsetX"], 2), getParam(json["ShadowOffsetY"], -2)),
+ json["ShadowBlurRadius"] || 0
+ );
+ }
+ if (label && json["OutlineEnabled"] && json["OutlineColor"] && label.enableStroke)
+ label.enableStroke(getColor(json["OutlineColor"]), getParam(json["OutlineSize"], 1));
+
+ this.widgetAttributes(widget, json);
+
+ if (scale9Enabled) {
+ widget.setUnifySizeEnabled(false);
+ widget.ignoreContentAdaptWithSize(false);
+ var capInsets = cc.rect(
+ json["Scale9OriginX"] || 0,
+ json["Scale9OriginY"] || 0,
+ json["Scale9Width"] || 0,
+ json["Scale9Height"] || 0
+ );
+ widget.setCapInsets(capInsets);
+
+ }
+
+ setContentSize(widget, json["Size"]);
+
+ return widget;
+
+ };
+
+ /**
+ * CheckBox
+ * @param json
+ * @param resourcePath
+ */
+ parser.initCheckBox = function (json, resourcePath) {
+
+ var widget = new ccui.CheckBox();
+
+ this.widgetAttributes(widget, json);
+
+ var dataList = [
+ {name: "NormalBackFileData", handle: widget.loadTextureBackGround},
+ {name: "PressedBackFileData", handle: widget.loadTextureBackGroundSelected},
+ {name: "NodeNormalFileData", handle: widget.loadTextureFrontCross},
+ {name: "DisableBackFileData", handle: widget.loadTextureBackGroundDisabled},
+ {name: "NodeDisableFileData", handle: widget.loadTextureFrontCrossDisabled}
+ ];
+
+ dataList.forEach(function (item) {
+ loadTexture(json[item.name], resourcePath, function (path, type) {
+ item.handle.call(widget, path, type);
+ });
+ });
+
+ var selectedState = getParam(json["CheckedState"], false);
+ widget.setSelected(selectedState);
+
+ var displaystate = getParam(json["DisplayState"], true);
+ widget.setBright(displaystate);
+ widget.setEnabled(displaystate);
+
+ return widget;
+ };
+
+ /**
+ * ScrollView
+ * @param json
+ * @param resourcePath
+ */
+ parser.initScrollView = function (json, resourcePath) {
+ var widget = new ccui.ScrollView();
+
+ this.widgetAttributes(widget, json);
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ widget.setBackGroundImage(path, type);
+ });
+
+ var clipEnabled = json["ClipAble"] || false;
+ widget.setClippingEnabled(clipEnabled);
+
+ var colorType = getParam(json["ComboBoxIndex"], 0);
+ widget.setBackGroundColorType(colorType);
+
+ var bgColorOpacity = json["BackColorAlpha"];
+ if (bgColorOpacity != null)
+ widget.setBackGroundColorOpacity(bgColorOpacity);
+
+ var backGroundScale9Enabled = json["Scale9Enable"];
+ if (backGroundScale9Enabled) {
+ widget.setBackGroundImageScale9Enabled(true);
+
+
+ var scale9OriginX = json["Scale9OriginX"] || 0;
+ var scale9OriginY = json["Scale9OriginY"] || 0;
+ var scale9Width = json["Scale9Width"] || 0;
+ var scale9Height = json["Scale9Height"] || 0;
+ widget.setBackGroundImageCapInsets(cc.rect(
+ scale9OriginX, scale9OriginY, scale9Width, scale9Height
+ ));
+ setContentSize(widget, json["Size"]);
+ } else if (!widget.isIgnoreContentAdaptWithSize()) {
+ setContentSize(widget, json["Size"]);
+ }
+
+ setLayoutBackground(widget, json["SingleColor"], json["FirstColor"], json["EndColor"]);
+ setLayoutBackgroundVector(widget, json["ColorVector"]);
+
+ var innerNodeSize = json["InnerNodeSize"];
+ var innerSize = cc.size(
+ innerNodeSize["Width"] || 0,
+ innerNodeSize["Height"] || 0
+ );
+ widget.setInnerContainerSize(innerSize);
+
+ var direction = 0;
+ if (json["ScrollDirectionType"] === "Vertical") direction = 1;
+ if (json["ScrollDirectionType"] === "Horizontal") direction = 2;
+ if (json["ScrollDirectionType"] === "Vertical_Horizontal") direction = 3;
+ widget.setDirection(direction);
+
+ var bounceEnabled = getParam(json["IsBounceEnabled"], false);
+ widget.setBounceEnabled(bounceEnabled);
+
+ return widget;
+ };
+
+ /**
+ * ImageView
+ * @param json
+ * @param resourcePath
+ */
+ parser.initImageView = function (json, resourcePath) {
+
+ var widget = new ccui.ImageView();
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ widget.loadTexture(path, type);
+ });
+ loadTexture(json["ImageFileData"], resourcePath, function (path, type) {
+ widget.loadTexture(path, type);
+ });
+
+ var scale9Enabled = json["Scale9Enable"];
+ if (scale9Enabled) {
+ widget.setScale9Enabled(true);
+ widget.setUnifySizeEnabled(false);
+ widget.ignoreContentAdaptWithSize(false);
+
+ var scale9OriginX = json["Scale9OriginX"] || 0;
+ var scale9OriginY = json["Scale9OriginY"] || 0;
+ var scale9Width = json["Scale9Width"] || 0;
+ var scale9Height = json["Scale9Height"] || 0;
+ widget.setCapInsets(cc.rect(
+ scale9OriginX,
+ scale9OriginY,
+ scale9Width,
+ scale9Height
+ ));
+ } else
+ setContentSize(widget, json["Size"]);
+
+ this.widgetAttributes(widget, json);
+
+ return widget;
+ };
+
+ /**
+ * LoadingBar
+ * @param json
+ * @param resourcePath
+ * @returns {ccui.LoadingBar}
+ */
+ parser.initLoadingBar = function (json, resourcePath) {
+
+ var widget = new ccui.LoadingBar();
+
+ this.widgetAttributes(widget, json);
+
+ loadTexture(json["ImageFileData"], resourcePath, function (path, type) {
+ widget.loadTexture(path, type);
+ });
+
+ var direction = json["ProgressType"] === "Right_To_Left" ? 1 : 0;
+ widget.setDirection(direction);
+
+ var percent = getParam(json["ProgressInfo"], 80);
+ if (percent != null)
+ widget.setPercent(percent);
+
+ return widget;
+
+ };
+
+ /**
+ * Slider
+ * @param json
+ * @param resourcePath
+ */
+ parser.initSlider = function (json, resourcePath) {
+
+ var widget = new ccui.Slider();
+ var loader = cc.loader;
+
+ this.widgetAttributes(widget, json);
+
+ var textureList = [
+ {name: "BackGroundData", handle: widget.loadBarTexture},
+ {name: "BallNormalData", handle: widget.loadSlidBallTextureNormal},
+ {name: "BallPressedData", handle: widget.loadSlidBallTexturePressed},
+ {name: "BallDisabledData", handle: widget.loadSlidBallTextureDisabled},
+ {name: "ProgressBarData", handle: widget.loadProgressBarTexture}
+ ];
+ textureList.forEach(function (item) {
+ loadTexture(json[item.name], resourcePath, function (path, type) {
+ if (type === 0 && !loader.getRes(path))
+ cc.log("%s need to be preloaded", path);
+ item.handle.call(widget, path, type);
+ });
+ });
+
+ var percent = json["PercentInfo"] || 0;
+ widget.setPercent(percent);
+
+ var displaystate = getParam(json["DisplayState"], true);
+ widget.setBright(displaystate);
+ widget.setEnabled(displaystate);
+
+ return widget;
+ };
+
+ /**
+ * PageView
+ * @param json
+ * @param resourcePath
+ */
+ parser.initPageView = function (json, resourcePath) {
+
+ var widget = new ccui.PageView();
+
+ this.widgetAttributes(widget, json);
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ widget.setBackGroundImage(path, type);
+ });
+
+ var clipEnabled = json["ClipAble"] || false;
+ widget.setClippingEnabled(clipEnabled);
+
+ var backGroundScale9Enabled = json["Scale9Enable"];
+ if (backGroundScale9Enabled) {
+ widget.setBackGroundImageScale9Enabled(true);
+
+ var scale9OriginX = json["Scale9OriginX"] || 0;
+ var scale9OriginY = json["Scale9OriginY"] || 0;
+ var scale9Width = json["Scale9Width"] || 0;
+ var scale9Height = json["Scale9Height"] || 0;
+ widget.setBackGroundImageCapInsets(cc.rect(
+ scale9OriginX,
+ scale9OriginY,
+ scale9Width,
+ scale9Height
+ ));
+ }
+
+ var colorType = getParam(json["ComboBoxIndex"], 0);
+ widget.setBackGroundColorType(colorType);
+
+ setLayoutBackground(widget, json["SingleColor"], json["FirstColor"], json["EndColor"]);
+ setLayoutBackgroundVector(widget, json["ColorVector"]);
+
+ var bgColorOpacity = json["BackColorAlpha"];
+ if (bgColorOpacity != null)
+ widget.setBackGroundColorOpacity(bgColorOpacity);
+
+ setContentSize(widget, json["Size"]);
+
+ return widget;
+
+ };
+
+ /**
+ * ListView
+ * @param json
+ * @param resourcePath
+ * @returns {ccui.ListView}
+ */
+ parser.initListView = function (json, resourcePath) {
+
+ var widget = new ccui.ListView();
+
+ this.widgetAttributes(widget, json);
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ widget.setBackGroundImage(path, type);
+ });
+
+ var clipEnabled = json["ClipAble"] || false;
+ widget.setClippingEnabled(clipEnabled);
+
+ var colorType = getParam(json["ComboBoxIndex"], 0);
+ widget.setBackGroundColorType(colorType);
+
+ var bgColorOpacity = getParam(json["BackColorAlpha"], 255);
+ var backGroundScale9Enabled = json["Scale9Enable"];
+ if (backGroundScale9Enabled) {
+ widget.setBackGroundImageScale9Enabled(true);
+
+ var scale9OriginX = json["Scale9OriginX"] || 0;
+ var scale9OriginY = json["Scale9OriginY"] || 0;
+ var scale9Width = json["Scale9Width"] || 0;
+ var scale9Height = json["Scale9Height"] || 0;
+ widget.setBackGroundImageCapInsets(cc.rect(
+ scale9OriginX,
+ scale9OriginY,
+ scale9Width,
+ scale9Height
+ ));
+ }
+
+ var directionType = getParam(json["DirectionType"], ccui.ListView.DIR_HORIZONTAL);
+ var verticalType = getParam(json["VerticalType"], "Align_Left");
+ var horizontalType = getParam(json["HorizontalType"], "Align_Top");
+ if (!directionType) {
+ widget.setDirection(ccui.ScrollView.DIR_HORIZONTAL);
+ if (verticalType === "Align_Bottom")
+ widget.setGravity(ccui.ListView.GRAVITY_BOTTOM);
+ else if (verticalType === "Align_VerticalCenter")
+ widget.setGravity(ccui.ListView.GRAVITY_CENTER_VERTICAL);
+ else
+ widget.setGravity(ccui.ListView.GRAVITY_TOP);
+ } else if (directionType === "Vertical") {
+ widget.setDirection(ccui.ScrollView.DIR_VERTICAL);
+ if (horizontalType === "")
+ widget.setGravity(ccui.ListView.GRAVITY_LEFT);
+ else if (horizontalType === "Align_Right")
+ widget.setGravity(ccui.ListView.GRAVITY_RIGHT);
+ else if (horizontalType === "Align_HorizontalCenter")
+ widget.setGravity(ccui.ListView.GRAVITY_CENTER_HORIZONTAL);
+ }
+
+
+ var bounceEnabled = getParam(json["IsBounceEnabled"], false);
+ widget.setBounceEnabled(bounceEnabled);
+
+ var itemMargin = json["ItemMargin"] || 0;
+ widget.setItemsMargin(itemMargin);
+
+ var innerSize = json["InnerNodeSize"];
+ //Width
+ if (innerSize != null)
+ widget.setInnerContainerSize(cc.size(innerSize["Widget"] || 0, innerSize["Height"] || 0));
+
+ setLayoutBackground(widget, json["SingleColor"], json["FirstColor"], json["EndColor"]);
+ setLayoutBackgroundVector(widget, json["ColorVector"]);
+
+ if (bgColorOpacity != null)
+ widget.setBackGroundColorOpacity(bgColorOpacity);
+
+ setContentSize(widget, json["Size"]);
+
+ return widget;
+ };
+
+ /**
+ * TextAtlas
+ * @param json
+ * @param resourcePath
+ * @returns {ccui.TextAtlas}
+ */
+ parser.initTextAtlas = function (json, resourcePath) {
+
+ var widget = new ccui.TextAtlas();
+
+ var stringValue = json["LabelText"];
+ var itemWidth = json["CharWidth"];
+ var itemHeight = json["CharHeight"];
+
+ var startCharMap = json["StartChar"];
+
+ loadTexture(json["LabelAtlasFileImage_CNB"], resourcePath, function (path, type) {
+ if (!cc.loader.getRes(path))
+ cc.log("%s need to be preloaded", path);
+ if (type === 0) {
+ widget.setProperty(stringValue, path, itemWidth, itemHeight, startCharMap);
+ }
+ });
+ this.widgetAttributes(widget, json);
+
+ // the TextAtlas must be ignore ContentSize[Size] in the ccs file.
+ widget.ignoreContentAdaptWithSize(true);
+
+ return widget;
+ };
+
+ /**
+ * TextBMFont
+ * @param json
+ * @param resourcePath
+ * @returns {ccui.TextBMFont}
+ */
+ parser.initTextBMFont = function (json, resourcePath) {
+ var widget = new ccui.TextBMFont();
+ this.widgetAttributes(widget, json);
+
+ loadTexture(json["LabelBMFontFile_CNB"], resourcePath, function (path, type) {
+ if (!cc.loader.getRes(path))
+ cc.log("%s need to be pre loaded", path);
+ widget.setFntFile(path);
+ });
+
+ var text = json["LabelText"];
+ widget.setString(text);
+
+ widget.ignoreContentAdaptWithSize(true);
+ return widget;
+ };
+
+ /**
+ * TextField
+ * @param json
+ * @param resourcePath
+ * @returns {ccui.TextField}
+ */
+ parser.initTextField = function (json, resourcePath) {
+ var widget = new ccui.TextField();
+
+ var passwordEnabled = json["PasswordEnable"];
+ if (passwordEnabled) {
+ widget.setPasswordEnabled(true);
+ var passwordStyleText = json["PasswordStyleText"] || "*";
+ widget.setPasswordStyleText(passwordStyleText);
+ }
+
+ var placeHolder = json["PlaceHolderText"];
+ if (placeHolder != null)
+ widget.setPlaceHolder(placeHolder);
+
+ var fontSize = json["FontSize"];
+ if (fontSize != null)
+ widget.setFontSize(fontSize);
+
+ var fontName = json["FontName"];
+ if (fontName != null)
+ widget.setFontName(fontName);
+
+ var maxLengthEnabled = json["MaxLengthEnable"];
+ if (maxLengthEnabled) {
+ widget.setMaxLengthEnabled(true);
+ var maxLength = json["MaxLengthText"] || 0;
+ widget.setMaxLength(maxLength);
+ }
+
+ //var isCustomSize = json["IsCustomSize"];
+ this.widgetAttributes(widget, json);
+
+ var text = json["LabelText"];
+ if (text != null)
+ widget.setString(text);
+
+ var fontResource = json["FontResource"];
+ if (fontResource != null) {
+ var path = fontResource["Path"];
+ //resoutceType = fontResource["Type"];
+ if (path != null) {
+ if (cc.sys.isNative) {
+ fontName = cc.path.join(cc.loader.resPath, resourcePath, path);
+ } else {
+ fontName = path.match(/([^\/]+)\.(\S+)/);
+ fontName = fontName ? fontName[1] : "";
+ }
+ widget.setFontName(fontName);
+ }
+ }
+
+ widget.setUnifySizeEnabled(false);
+ widget.ignoreContentAdaptWithSize(false);
+
+ var color = json["CColor"];
+ if (color != null)
+ widget.setTextColor(getColor(color));
+
+ if (!widget.isIgnoreContentAdaptWithSize()) {
+ setContentSize(widget, json["Size"]);
+ if (cc.sys.isNative)
+ widget.getVirtualRenderer().setLineBreakWithoutSpace(true);
+ }
+
+
+ return widget;
+
+ };
+
+ /**
+ * SimpleAudio
+ * @param json
+ * @param resourcePath
+ */
+ parser.initSimpleAudio = function (json, resourcePath) {
+
+ var node = new ccs.ComAudio();
+ var loop = json["Loop"] || false;
+ //var volume = json["Volume"] || 0;
+ //cc.audioEngine.setMusicVolume(volume);
+ node.setLoop(loop);
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ node.setFile(path);
+ });
+
+ };
+
+ /**
+ * GameMap
+ * @param json
+ * @param resourcePath
+ * @returns {*}
+ */
+ parser.initGameMap = function (json, resourcePath) {
+
+ var node = null;
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ if (type === 0)
+ node = new cc.TMXTiledMap(path);
+
+ parser.generalAttributes(node, json);
+ });
+
+ return node;
+ };
+
+ /**
+ * ProjectNode
+ * @param json
+ * @param resourcePath
+ * @returns {*}
+ */
+ parser.initProjectNode = function (json, resourcePath) {
+ var projectFile = json["FileData"];
+ if (projectFile != null && projectFile["Path"]) {
+ var file = resourcePath + projectFile["Path"];
+ if (cc.loader.getRes(file)) {
+ var obj = ccs.load(file, resourcePath);
+ parser.generalAttributes(obj.node, json);
+ if (obj.action && obj.node) {
+ obj.action.tag = obj.node.tag;
+ var InnerActionSpeed = json["InnerActionSpeed"];
+ if (InnerActionSpeed !== undefined)
+ obj.action.setTimeSpeed(InnerActionSpeed);
+ obj.node.runAction(obj.action);
+ obj.action.gotoFrameAndPause(0);
+ }
+ return obj.node;
+ } else
+ cc.log("%s need to be preloaded", file);
+ }
+ };
+
+ var getFileName = function (name) {
+ if (!name) return "";
+ var arr = name.match(/([^\/]+)\.[^\/]+$/);
+ if (arr && arr[1])
+ return arr[1];
+ else
+ return "";
+ };
+
+ /**
+ * Armature
+ * @param json
+ * @param resourcePath
+ */
+ parser.initArmature = function (json, resourcePath) {
+
+ var node = new ccs.Armature();
+
+ var isLoop = json["IsLoop"];
+
+ var isAutoPlay = json["IsAutoPlay"];
+
+ var currentAnimationName = json["CurrentAnimationName"];
+
+ loadTexture(json["FileData"], resourcePath, function (path, type) {
+ var plists, pngs;
+ var armJson = cc.loader.getRes(path);
+ if (!armJson)
+ cc.log("%s need to be preloaded", path);
+ else {
+ plists = armJson["config_file_path"];
+ pngs = armJson["config_png_path"];
+ plists.forEach(function (plist, index) {
+ if (pngs[index])
+ cc.spriteFrameCache.addSpriteFrames(plist, pngs[index]);
+ });
+ }
+ ccs.armatureDataManager.addArmatureFileInfo(path);
+ node.init(getFileName(path));
+ if (isAutoPlay)
+ node.getAnimation().play(currentAnimationName, -1, isLoop);
+ else {
+ node.getAnimation().play(currentAnimationName);
+ node.getAnimation().gotoAndPause(0);
+ }
+
+ });
+
+ delete json["AnchorPoint"];
+ delete json["Size"];
+ parser.generalAttributes(node, json);
+
+ node.setColor(getColor(json["CColor"]));
+ return node;
+ };
+
+ parser.initBoneNode = function (json, resourcePath) {
+
+ var node = new ccs.BoneNode();
+
+ var length = json["Length"];
+ if (length !== undefined)
+ node.setDebugDrawLength(length);
+
+ var blendFunc = json["BlendFunc"];
+ if (blendFunc && blendFunc["Src"] !== undefined && blendFunc["Dst"] !== undefined)
+ node.setBlendFunc(new cc.BlendFunc(blendFunc["Src"], blendFunc["Dst"]));
+
+ parser.generalAttributes(node, json);
+ var color = json["CColor"];
+ if (color && (color["R"] !== undefined || color["G"] !== undefined || color["B"] !== undefined))
+ node.setColor(getColor(color));
+ return node;
+ };
+
+ parser.initSkeletonNode = function (json) {
+ var node = new ccs.SkeletonNode();
+ parser.generalAttributes(node, json);
+ var color = json["CColor"];
+ if (color && (color["R"] !== undefined || color["G"] !== undefined || color["B"] !== undefined))
+ node.setColor(getColor(color));
+ return node;
+ };
+
+ var loadedPlist = {};
+ var loadTexture = function (json, resourcePath, cb) {
+ if (json != null) {
+ var path = json["Path"];
+ var type;
+ if (json["Type"] === "Default" || json["Type"] === "Normal")
+ type = 0;
+ else
+ type = 1;
+ var plist = json["Plist"];
+ if (plist) {
+ if (cc.loader.getRes(resourcePath + plist)) {
+ loadedPlist[resourcePath + plist] = true;
+ cc.spriteFrameCache.addSpriteFrames(resourcePath + plist);
+ } else {
+ if (!loadedPlist[resourcePath + plist] && !cc.spriteFrameCache.getSpriteFrame(path))
+ cc.log("%s need to be preloaded", resourcePath + plist);
+ }
+ }
+ if (type !== 0) {
+ if (cc.spriteFrameCache.getSpriteFrame(path))
+ cb(path, type);
+ else
+ cc.log("failed to get spriteFrame: %s", path);
+ } else
+ cb(resourcePath + path, type);
+ }
+ };
+
+ var getColor = function (json) {
+ if (!json) return;
+ var r = json["R"] != null ? json["R"] : 255;
+ var g = json["G"] != null ? json["G"] : 255;
+ var b = json["B"] != null ? json["B"] : 255;
+ var a = json["A"] != null ? json["A"] : 255;
+ return cc.color(r, g, b, a);
+ };
+
+ var setContentSize = function (node, size) {
+ var x = size["X"] || 0;
+ var y = size["Y"] || 0;
+ if (size)
+ node.setContentSize(cc.size(x, y));
+ };
+
+ var register = [
+ {name: "SingleNodeObjectData", handle: parser.initSingleNode},
+ {name: "NodeObjectData", handle: parser.initSingleNode},
+ {name: "LayerObjectData", handle: parser.initSingleNode},
+ {name: "GameNodeObjectData", handle: parser.initSingleNode},
+ {name: "GameLayerObjectData", handle: parser.initSingleNode},
+ {name: "SpriteObjectData", handle: parser.initSprite},
+ {name: "ParticleObjectData", handle: parser.initParticle},
+ {name: "PanelObjectData", handle: parser.initPanel},
+ {name: "TextObjectData", handle: parser.initText},
+ {name: "ButtonObjectData", handle: parser.initButton},
+ {name: "CheckBoxObjectData", handle: parser.initCheckBox},
+ {name: "ScrollViewObjectData", handle: parser.initScrollView},
+ {name: "ImageViewObjectData", handle: parser.initImageView},
+ {name: "LoadingBarObjectData", handle: parser.initLoadingBar},
+ {name: "SliderObjectData", handle: parser.initSlider},
+ {name: "PageViewObjectData", handle: parser.initPageView},
+ {name: "ListViewObjectData", handle: parser.initListView},
+ {name: "TextAtlasObjectData", handle: parser.initTextAtlas},
+ {name: "TextBMFontObjectData", handle: parser.initTextBMFont},
+ {name: "TextFieldObjectData", handle: parser.initTextField},
+ {name: "SimpleAudioObjectData", handle: parser.initSimpleAudio},
+ {name: "GameMapObjectData", handle: parser.initGameMap},
+ {name: "ProjectNodeObjectData", handle: parser.initProjectNode},
+ {name: "ArmatureNodeObjectData", handle: parser.initArmature},
+ {name: "BoneNodeObjectData", handle: parser.initBoneNode},
+ {name: "SkeletonNodeObjectData", handle: parser.initSkeletonNode}
+ ];
+
+ register.forEach(function (item) {
+ parser.registerParser(item.name, function (options, resourcePath) {
+ var node = item.handle.call(this, options, resourcePath);
+ this.parseChild(node, options["Children"], resourcePath);
+ DEBUG && node && (node.__parserName = item.name);
+ return node;
+ });
+ });
+
+
+ load.registerParser("timeline", "2.*", parser);
+ load.registerParser("timeline", "*", parser);
+
+
+})(ccs._load, ccs._parser);
diff --git a/extensions/cocostudio/loader/parsers/uiParser-1.x.js b/extensions/cocostudio/loader/parsers/uiParser-1.x.js
new file mode 100644
index 0000000000..e6904df62d
--- /dev/null
+++ b/extensions/cocostudio/loader/parsers/uiParser-1.x.js
@@ -0,0 +1,710 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function (load, baseParser) {
+
+ var _stack = new Array(50);
+
+ var Parser = baseParser.extend({
+
+ addSpriteFrame: function (textures, resourcePath) {
+ if (!textures) return;
+ for (var i = 0; i < textures.length; i++) {
+ cc.spriteFrameCache.addSpriteFrames(resourcePath + textures[i]);
+ }
+ },
+
+ pretreatment: function (json, resourcePath) {
+ this.addSpriteFrame(json["textures"], resourcePath);
+ },
+
+ parseRecursive: function (json, resourcePath) {
+ var index = 1;
+ var rootNode = null;
+ var parser, curr, className, options, position, anchor, anchorPP,
+ node, parent, child, children;
+ _stack[0] = json;
+ while (index > 0) {
+ index--;
+ curr = _stack[index];
+ // Avoid memory leak
+ _stack[index] = null;
+ if (!curr) continue;
+
+ // Parse node
+ className = curr["classname"];
+ parser = this.parsers[className];
+ if (!parser) {
+ cc.log("Can't find the parser : %s", className);
+ continue;
+ }
+ node = new parser.object();
+ if (!node) continue;
+ if (!rootNode) {
+ rootNode = node;
+ }
+
+ // Parse attributes
+ options = curr["options"];
+ this.generalAttributes(node, options);
+ parser.handle(node, options, resourcePath);
+ this.colorAttributes(node, options);
+
+ parent = curr.parent;
+ curr.parent = null;
+ if (parent instanceof ccui.PageView) {
+ parent.addPage(node);
+ }
+ else if (parent instanceof ccui.ListView) {
+ parent.pushBackCustomItem(node);
+ }
+ else if (parent) {
+ if (!(parent instanceof ccui.Layout)) {
+ if (node.getPositionType() === ccui.Widget.POSITION_PERCENT) {
+ position = node._positionPercent;
+ anchor = parent._anchorPoint;
+ node._positionPercent.x = position.x + anchor.x;
+ node._positionPercent.y = position.y + anchor.y;
+ }
+ anchorPP = parent._renderCmd._anchorPointInPoints;
+ node._position.x += anchorPP.x;
+ node._position.y += anchorPP.y;
+ node.setNodeDirty();
+ }
+ parent.addChild(node);
+ }
+
+ children = curr["children"];
+ if (children && children.length > 0) {
+ for (var i = children.length - 1; i >= 0; i--) {
+ _stack[index] = children[i];
+ _stack[index].parent = node;
+ index++;
+ }
+ }
+ }
+ return rootNode;
+ },
+
+ parse: function (file, json, resourcePath) {
+ resourcePath = resourcePath || this._dirname(file);
+ this.pretreatment(json, resourcePath);
+
+ var node = this.parseRecursive(json["widgetTree"], resourcePath);
+
+ node && this.deferred(json, resourcePath, node, file);
+ return node;
+ },
+
+ deferred: function (json, resourcePath, node, file) {
+ if (node) {
+ ccs.actionManager.initWithDictionary(file, json["animation"], node);
+ node.setContentSize(json["designWidth"], json["designHeight"]);
+ }
+ }
+
+ });
+ var parser = new Parser();
+
+ parser.generalAttributes = function (widget, options) {
+ widget._ignoreSize = options["ignoreSize"] || true;
+ widget._sizeType = options["sizeType"] || 0;
+ widget._positionType = options["positionType"] || 0;
+
+ widget._sizePercent.x = options["sizePercentX"] || 0;
+ widget._sizePercent.y = options["sizePercentY"] || 0;
+ widget._positionPercent.x = options["positionPercentX"] || 0;
+ widget._positionPercent.y = options["positionPercentY"] || 0;
+
+ /* adapt screen */
+ var w = 0, h = 0;
+ var adaptScreen = options["adaptScreen"];
+ if (adaptScreen) {
+ var screenSize = cc.director.getWinSize();
+ w = screenSize.width;
+ h = screenSize.height;
+ } else {
+ w = options["width"] || 0;
+ h = options["height"] || 0;
+ }
+
+ var anchorPointX = options["anchorPointX"];
+ var anchorPointY = options["anchorPointY"];
+
+ widget._anchorPoint.x = isNaN(anchorPointX) ? 0.5 : anchorPointX;
+ widget._anchorPoint.y = isNaN(anchorPointY) ? 0.5 : anchorPointY;
+
+ widget.setContentSize(w, h);
+
+ widget.setTag(options["tag"]);
+ widget.setActionTag(options["actiontag"]);
+ widget.setTouchEnabled(options["touchAble"]);
+
+ widget._name = options["name"] || "default";
+
+ widget._position.x = options["x"] || 0;
+ widget._position.y = options["y"] || 0;
+ widget._scaleX = options["scaleX"] || 1;
+ widget._scaleY = options["scaleY"] || 1;
+ widget._rotationX = widget._rotationY = options["rotation"] || 0;
+
+ widget._visible = options["visible"] || false;
+ widget._localZOrder = options["ZOrder"] || 0;
+
+ var layout = options["layoutParameter"];
+ if (layout != null) {
+ var layoutParameterDic = options["layoutParameter"];
+ var paramType = isNaN(layoutParameterDic["type"]) ? 2 : layoutParameterDic["type"];
+ var parameter = null;
+
+ switch (paramType) {
+ case 0:
+ break;
+ case 1:
+ parameter = new ccui.LinearLayoutParameter();
+ parameter._linearGravity = layoutParameterDic["gravity"] || 0;
+ break;
+ case 2:
+ parameter = new ccui.RelativeLayoutParameter();
+ parameter._relativeLayoutName = layoutParameterDic["relativeName"];
+ parameter._relativeWidgetName = layoutParameterDic["relativeToName"];
+ parameter._relativeAlign = layoutParameterDic["align"] || 0;
+ break;
+ default:
+ break;
+ }
+ if (parameter != null) {
+ var margin = parameter._margin;
+ margin.left = layoutParameterDic["marginLeft"] || 0;
+ margin.top = layoutParameterDic["marginTop"] || 0;
+ margin.right = layoutParameterDic["marginRight"] || 0;
+ margin.bottom = layoutParameterDic["marginDown"] || 0;
+ widget.setLayoutParameter(parameter);
+ }
+ }
+ };
+
+ parser.colorAttributes = function (widget, options) {
+ var op = options["opacity"] !== null ? options["opacity"] : 255;
+ if (op != null)
+ widget.setOpacity(op);
+ var colorR = options["colorR"];
+ var colorG = options["colorG"];
+ var colorB = options["colorB"];
+ widget.setColor(cc.color((colorR == null) ? 255 : colorR, (colorG == null) ? 255 : colorG, (colorB == null) ? 255 : colorB));
+
+ widget.setFlippedX(options["flipX"]);
+ widget.setFlippedY(options["flipY"]);
+ };
+
+ var getPath = function (res, type, path, cb) {
+ if (path) {
+ if (type === 0)
+ cb(res + path, type);
+ else
+ cb(path, type);
+ }
+ };
+
+ /**
+ * Panel parser (UILayout)
+ */
+ parser.LayoutAttributes = function (widget, options, resourcePath) {
+ var w = 0, h = 0;
+ var adaptScreen = options["adaptScreen"];
+ if (adaptScreen) {
+ var screenSize = cc.director.getWinSize();
+ w = screenSize.width;
+ h = screenSize.height;
+ } else {
+ w = options["width"] || 0;
+ h = options["height"] || 0;
+ }
+ widget.setSize(cc.size(w, h));
+
+ widget.setClippingEnabled(options["clipAble"]);
+
+ var backGroundScale9Enable = options["backGroundScale9Enable"];
+ widget.setBackGroundImageScale9Enabled(backGroundScale9Enable);
+ var cr = options["bgColorR"] || 0;
+ var cg = options["bgColorG"] || 0;
+ var cb = options["bgColorB"] || 0;
+
+ var scr = isNaN(options["bgStartColorR"]) ? 255 : options["bgStartColorR"];
+ var scg = isNaN(options["bgStartColorG"]) ? 255 : options["bgStartColorG"];
+ var scb = isNaN(options["bgStartColorB"]) ? 255 : options["bgStartColorB"];
+
+ var ecr = isNaN(options["bgEndColorR"]) ? 255 : options["bgEndColorR"];
+ var ecg = isNaN(options["bgEndColorG"]) ? 255 : options["bgEndColorG"];
+ var ecb = isNaN(options["bgEndColorB"]) ? 255 : options["bgEndColorB"];
+
+ var bgcv1 = options["vectorX"] || 0;
+ var bgcv2 = options["vectorY"] || 0;
+ widget.setBackGroundColorVector(cc.p(bgcv1, bgcv2));
+
+ var co = options["bgColorOpacity"] || 0;
+
+ var colorType = options["colorType"] || 0;
+ widget.setBackGroundColorType(colorType/*ui.LayoutBackGroundColorType(colorType)*/);
+ widget.setBackGroundColor(cc.color(scr, scg, scb), cc.color(ecr, ecg, ecb));
+ widget.setBackGroundColor(cc.color(cr, cg, cb));
+ widget.setBackGroundColorOpacity(co);
+
+
+ var imageFileNameDic = options["backGroundImageData"];
+ if (imageFileNameDic) {
+ getPath(resourcePath, imageFileNameDic["resourceType"] || 0, imageFileNameDic["path"], function (path, type) {
+ widget.setBackGroundImage(path, type);
+ });
+ }
+
+ if (backGroundScale9Enable) {
+ var cx = options["capInsetsX"] || 0;
+ var cy = options["capInsetsY"] || 0;
+ var cw = isNaN(options["capInsetsWidth"]) ? 1 : options["capInsetsWidth"];
+ var ch = isNaN(options["capInsetsHeight"]) ? 1 : options["capInsetsHeight"];
+ widget.setBackGroundImageCapInsets(cc.rect(cx, cy, cw, ch));
+ }
+ if (options["layoutType"]) {
+ widget.setLayoutType(options["layoutType"]);
+ }
+ };
+ /**
+ * Button parser (UIButton)
+ */
+ parser.ButtonAttributes = function (widget, options, resourcePath) {
+ var button = widget;
+ var scale9Enable = options["scale9Enable"];
+ button.setScale9Enabled(scale9Enable);
+
+ var normalDic = options["normalData"];
+ getPath(resourcePath, normalDic["resourceType"] || 0, normalDic["path"], function (path, type) {
+ button.loadTextureNormal(path, type);
+ });
+ var pressedDic = options["pressedData"];
+ getPath(resourcePath, pressedDic["resourceType"] || 0, pressedDic["path"], function (path, type) {
+ button.loadTexturePressed(path, type);
+ });
+ var disabledDic = options["disabledData"];
+ getPath(resourcePath, disabledDic["resourceType"] || 0, disabledDic["path"], function (path, type) {
+ button.loadTextureDisabled(path, type);
+ });
+ if (scale9Enable) {
+ var cx = options["capInsetsX"] || 0;
+ var cy = options["capInsetsY"] || 0;
+ var cw = isNaN(options["capInsetsWidth"]) ? 1 : options["capInsetsWidth"];
+ var ch = isNaN(options["capInsetsHeight"]) ? 1 : options["capInsetsHeight"];
+
+ button.setCapInsets(cc.rect(cx, cy, cw, ch));
+ var sw = options["scale9Width"] || 0;
+ var sh = options["scale9Height"] || 0;
+ if (sw != null && sh != null)
+ button.setSize(cc.size(sw, sh));
+ }
+ var text = options["text"] || "";
+ if (text) {
+ button.setTitleText(text);
+
+ var cr = options["textColorR"];
+ var cg = options["textColorG"];
+ var cb = options["textColorB"];
+ var cri = (cr !== null) ? options["textColorR"] : 255;
+ var cgi = (cg !== null) ? options["textColorG"] : 255;
+ var cbi = (cb !== null) ? options["textColorB"] : 255;
+
+ button.setTitleColor(cc.color(cri, cgi, cbi));
+ var fs = options["fontSize"];
+ if (fs != null)
+ button.setTitleFontSize(options["fontSize"]);
+ var fn = options["fontName"];
+ if (fn)
+ button.setTitleFontName(options["fontName"]);
+ }
+ };
+ /**
+ * CheckBox parser (UICheckBox)
+ */
+ parser.CheckBoxAttributes = function (widget, options, resourcePath) {
+ //load background image
+ var backGroundDic = options["backGroundBoxData"];
+ getPath(resourcePath, backGroundDic["resourceType"] || 0, backGroundDic["path"], function (path, type) {
+ widget.loadTextureBackGround(path, type);
+ });
+
+ //load background selected image
+ var backGroundSelectedDic = options["backGroundBoxSelectedData"];
+ getPath(
+ resourcePath,
+ backGroundSelectedDic["resourceType"] || backGroundDic["resourceType"],
+ backGroundSelectedDic["path"] || backGroundDic["path"],
+ function (path, type) {
+ widget.loadTextureBackGroundSelected(path, type);
+ });
+
+ //load frontCross image
+ var frontCrossDic = options["frontCrossData"];
+ getPath(resourcePath, frontCrossDic["resourceType"] || 0, frontCrossDic["path"], function (path, type) {
+ widget.loadTextureFrontCross(path, type);
+ });
+
+ //load backGroundBoxDisabledData
+ var backGroundDisabledDic = options["backGroundBoxDisabledData"];
+ getPath(
+ resourcePath,
+ backGroundDisabledDic["resourceType"] || frontCrossDic["resourceType"],
+ backGroundDisabledDic["path"] || frontCrossDic["path"],
+ function (path, type) {
+ widget.loadTextureBackGroundDisabled(path, type);
+ });
+
+ ///load frontCrossDisabledData
+ var frontCrossDisabledDic = options["frontCrossDisabledData"];
+ getPath(resourcePath, frontCrossDisabledDic["resourceType"] || 0, frontCrossDisabledDic["path"], function (path, type) {
+ widget.loadTextureFrontCrossDisabled(path, type);
+ });
+
+ if (options["selectedState"])
+ widget.setSelected(options["selectedState"]);
+ };
+ /**
+ * ImageView parser (UIImageView)
+ */
+ parser.ImageViewAttributes = function (widget, options, resourcePath) {
+ var imageFileNameDic = options["fileNameData"]
+ getPath(resourcePath, imageFileNameDic["resourceType"] || 0, imageFileNameDic["path"], function (path, type) {
+ widget.loadTexture(path, type);
+ });
+
+ var scale9EnableExist = options["scale9Enable"];
+ var scale9Enable = false;
+ if (scale9EnableExist) {
+ scale9Enable = options["scale9Enable"];
+ }
+ widget.setScale9Enabled(scale9Enable);
+
+ if (scale9Enable) {
+ var sw = options["scale9Width"] || 0;
+ var sh = options["scale9Height"] || 0;
+ if (sw && sh) {
+ var swf = options["scale9Width"] || 0;
+ var shf = options["scale9Height"] || 0;
+ widget.setSize(cc.size(swf, shf));
+ }
+
+ var cx = options["capInsetsX"] || 0;
+ var cy = options["capInsetsY"] || 0;
+ var cw = isNaN(options["capInsetsWidth"]) ? 1 : options["capInsetsWidth"];
+ var ch = isNaN(options["capInsetsHeight"]) ? 1 : options["capInsetsHeight"];
+
+ widget.setCapInsets(cc.rect(cx, cy, cw, ch));
+
+ }
+ };
+ /**
+ * TextAtlas parser (UITextAtlas)
+ */
+ parser.TextAtlasAttributes = function (widget, options, resourcePath) {
+ var sv = options["stringValue"];
+ var cmf = options["charMapFileData"]; // || options["charMapFile"];
+ var iw = options["itemWidth"];
+ var ih = options["itemHeight"];
+ var scm = options["startCharMap"];
+ if (sv != null && cmf && iw != null && ih != null && scm != null) {
+ var cmftDic = options["charMapFileData"];
+ var cmfType = cmftDic["resourceType"] || 0;
+ switch (cmfType) {
+ case 0:
+ var tp_c = resourcePath;
+ var cmfPath = cmftDic["path"];
+ var cmf_tp = tp_c + cmfPath;
+ widget.setProperty(sv, cmf_tp, iw, ih, scm);
+ break;
+ case 1:
+ cc.log("Wrong res type of LabelAtlas!");
+ break;
+ default:
+ break;
+ }
+ }
+ };
+ /**
+ * TextBMFont parser (UITextBMFont)
+ */
+ parser.TextBMFontAttributes = function (widget, options, resourcePath) {
+ var cmftDic = options["fileNameData"];
+ var cmfType = cmftDic["resourceType"] || 0;
+ switch (cmfType) {
+ case 0:
+ var tp_c = resourcePath;
+ var cmfPath = cmftDic["path"];
+ var cmf_tp = tp_c + cmfPath;
+ widget.setFntFile(cmf_tp);
+ break;
+ case 1:
+ cc.log("Wrong res type of LabelAtlas!");
+ break;
+ default:
+ break;
+ }
+
+ var text = options["text"] || "";
+ widget.setString(text);
+ };
+ /**
+ * Text parser (UIText)
+ */
+ var regTTF = /\.ttf$/;
+ parser.TextAttributes = function (widget, options, resourcePath) {
+ var touchScaleChangeAble = options["touchScaleEnable"];
+ widget.setTouchScaleChangeEnabled(touchScaleChangeAble);
+ var text = options["text"] || "";
+ if(text) {
+ widget._setString(text);
+ }
+
+ var fs = options["fontSize"];
+ if (fs != null) {
+ widget._setFontSize(options["fontSize"]);
+ }
+ var fn = options["fontName"];
+ if (fn != null) {
+ if (cc.sys.isNative) {
+ if (regTTF.test(fn)) {
+ widget.setFontName(cc.path.join(cc.loader.resPath, resourcePath, fn));
+ } else {
+ widget.setFontName(fn);
+ }
+ } else {
+ widget._setFontName(fn.replace(regTTF, ''));
+ }
+ }
+ var aw = options["areaWidth"] || 0;
+ var ah = options["areaHeight"] || 0;
+ if (aw && ah) {
+ var size = cc.size(options["areaWidth"], options["areaHeight"]);
+ widget._setTextAreaSize(size);
+ }
+ var ha = options["hAlignment"] || 0;
+ if (ha != null) {
+ widget._setTextHorizontalAlignment(ha);
+ }
+ var va = options["vAlignment"] || 0;
+ if (va != null) {
+ widget._setTextVerticalAlignment(va);
+ }
+ widget._updateUITextContentSize();
+ };
+ /**
+ * ListView parser (UIListView)
+ */
+ parser.ListViewAttributes = function (widget, options, resoutcePath) {
+ parser.ScrollViewAttributes(widget, options, resoutcePath);
+ var direction = options["direction"] || 1;
+ widget.setDirection(direction);
+ var gravity = options["gravity"] || 0;
+ widget.setGravity(gravity);
+ var itemMargin = options["itemMargin"] || 0;
+ widget.setItemsMargin(itemMargin);
+ };
+ /**
+ * LoadingBar parser (UILoadingBar)
+ */
+ parser.LoadingBarAttributes = function (widget, options, resourcePath) {
+ var imageFileNameDic = options["textureData"];
+ getPath(resourcePath, imageFileNameDic["resourceType"] || 0, imageFileNameDic["path"], function (path, type) {
+ widget.loadTexture(path, type);
+ });
+
+ var scale9Enable = options["scale9Enable"];
+ widget.setScale9Enabled(scale9Enable);
+
+ if (scale9Enable) {
+ var cx = options["capInsetsX"] || 0;
+ var cy = options["capInsetsY"] || 0;
+ var cw = isNaN(options["capInsetsWidth"]) ? 1 : options["capInsetsWidth"];
+ var ch = isNaN(options["capInsetsHeight"]) ? 1 : options["capInsetsHeight"];
+
+ widget.setCapInsets(cc.rect(cx, cy, cw, ch));
+
+ var width = options["width"] || 0;
+ var height = options["height"] || 0;
+ widget.setSize(cc.size(width, height));
+ }
+
+ widget.setDirection(options["direction"] || 0);
+ widget.setPercent(options["percent"] || 0);
+ };
+ /**
+ * PageView parser (UIPageView)
+ */
+ parser.PageViewAttributes = parser.LayoutAttributes;
+ /**
+ * ScrollView parser (UIScrollView)
+ */
+ parser.ScrollViewAttributes = function (widget, options, resoutcePath) {
+ parser.LayoutAttributes(widget, options, resoutcePath);
+ var innerWidth = options["innerWidth"] != null ? options["innerWidth"] : 200;
+ var innerHeight = options["innerHeight"] != null ? options["innerHeight"] : 200;
+ widget.setInnerContainerSize(cc.size(innerWidth, innerHeight));
+
+ var direction = options["direction"] != null ? options["direction"] : 1;
+ widget.setDirection(direction);
+ widget.setBounceEnabled(options["bounceEnable"]);
+ };
+ /**
+ * Slider parser (UISlider)
+ */
+ parser.SliderAttributes = function (widget, options, resourcePath) {
+
+ var slider = widget;
+
+ var barTextureScale9Enable = options["scale9Enable"];
+ slider.setScale9Enabled(barTextureScale9Enable);
+ var bt = options["barFileName"];
+ var barLength = options["length"];
+
+ var imageFileNameDic = options["barFileNameData"];
+ var imageFileType = imageFileNameDic["resourceType"] || 0;
+ var imageFileName = imageFileNameDic["path"];
+
+ if (bt != null) {
+ if (barTextureScale9Enable) {
+ getPath(resourcePath, imageFileType, imageFileName, function (path, type) {
+ slider.loadBarTexture(path, type);
+ });
+ slider.setSize(cc.size(barLength, slider.getContentSize().height));
+ }
+ } else {
+ getPath(resourcePath, imageFileType, imageFileName, function (path, type) {
+ slider.loadBarTexture(path, type);
+ });
+ }
+
+ var normalDic = options["ballNormalData"];
+ getPath(resourcePath, normalDic["resourceType"] || 0, normalDic["path"], function (path, type) {
+ slider.loadSlidBallTextureNormal(path, type);
+ });
+
+ var pressedDic = options["ballPressedData"];
+ getPath(
+ resourcePath,
+ pressedDic["resourceType"] || normalDic["resourceType"],
+ pressedDic["path"] || normalDic["path"],
+ function (path, type) {
+ slider.loadSlidBallTexturePressed(path, type);
+ });
+
+ var disabledDic = options["ballDisabledData"];
+ getPath(resourcePath, disabledDic["resourceType"] || 0, disabledDic["path"], function (path, type) {
+ slider.loadSlidBallTextureDisabled(path, type);
+ });
+
+ var progressBarDic = options["progressBarData"];
+ getPath(resourcePath, progressBarDic["resourceType"] || 0, progressBarDic["path"], function (path, type) {
+ slider.loadProgressBarTexture(path, type);
+ });
+ };
+ /**
+ * TextField parser (UITextField)
+ */
+ parser.TextFieldAttributes = function (widget, options, resourcePath) {
+ var ph = options["placeHolder"] || "";
+ if (ph)
+ widget.setPlaceHolder(ph);
+ widget.setString(options["text"] || "");
+ var fs = options["fontSize"];
+ if (fs)
+ widget.setFontSize(fs);
+ var fn = options["fontName"];
+ if (fn != null) {
+ if (cc.sys.isNative) {
+ if (regTTF.test(fn)) {
+ widget.setFontName(cc.path.join(cc.loader.resPath, resourcePath, fn));
+ } else {
+ widget.setFontName(fn);
+ }
+ } else {
+ widget.setFontName(fn.replace(regTTF, ''));
+ }
+ }
+ var tsw = options["touchSizeWidth"] || 0;
+ var tsh = options["touchSizeHeight"] || 0;
+ if (tsw != null && tsh != null)
+ widget.setTouchSize(tsw, tsh);
+
+ var dw = options["width"] || 0;
+ var dh = options["height"] || 0;
+ if (dw > 0 || dh > 0) {
+ //textField.setSize(cc.size(dw, dh));
+ }
+ var maxLengthEnable = options["maxLengthEnable"];
+ widget.setMaxLengthEnabled(maxLengthEnable);
+
+ if (maxLengthEnable) {
+ var maxLength = options["maxLength"];
+ widget.setMaxLength(maxLength);
+ }
+ var passwordEnable = options["passwordEnable"];
+ widget.setPasswordEnabled(passwordEnable);
+ if (passwordEnable)
+ widget.setPasswordStyleText(options["passwordStyleText"]);
+
+ var aw = options["areaWidth"] || 0;
+ var ah = options["areaHeight"] || 0;
+ if (aw && ah) {
+ var size = cc.size(aw, ah);
+ widget.setTextAreaSize(size);
+ }
+ var ha = options["hAlignment"] || 0;
+ if (ha)
+ widget.setTextHorizontalAlignment(ha);
+ var va = options["vAlignment"] || 0;
+ if (va)
+ widget.setTextVerticalAlignment(va);
+
+ var r = isNaN(options["colorR"]) ? 255 : options["colorR"];
+ var g = isNaN(options["colorG"]) ? 255 : options["colorG"];
+ var b = isNaN(options["colorB"]) ? 255 : options["colorB"];
+ widget.setTextColor(cc.color(r, g, b));
+ };
+
+ parser.parsers = {
+ "Panel": {object: ccui.Layout, handle: parser.LayoutAttributes},
+ "Button": {object: ccui.Button, handle: parser.ButtonAttributes},
+ "CheckBox": {object: ccui.CheckBox, handle: parser.CheckBoxAttributes},
+ "ImageView": {object: ccui.ImageView, handle: parser.ImageViewAttributes},
+ "LabelAtlas": {object: ccui.TextAtlas, handle: parser.TextAtlasAttributes},
+ "LabelBMFont": {object: ccui.TextBMFont, handle: parser.TextBMFontAttributes},
+ "Label": {object: ccui.Text, handle: parser.TextAttributes},
+ "ListView": {object: ccui.ListView, handle: parser.ListViewAttributes},
+ "LoadingBar": {object: ccui.LoadingBar, handle: parser.LoadingBarAttributes},
+ "PageView": {object: ccui.PageView, handle: parser.PageViewAttributes},
+ "ScrollView": {object: ccui.ScrollView, handle: parser.ScrollViewAttributes},
+ "Slider": {object: ccui.Slider, handle: parser.SliderAttributes},
+ "TextField": {object: ccui.TextField, handle: parser.TextFieldAttributes}
+ };
+
+ load.registerParser("ccui", "*", parser);
+
+})(ccs._load, ccs._parser);
diff --git a/extensions/cocostudio/timeline/ActionTimeline.js b/extensions/cocostudio/timeline/ActionTimeline.js
new file mode 100644
index 0000000000..fd899ae120
--- /dev/null
+++ b/extensions/cocostudio/timeline/ActionTimeline.js
@@ -0,0 +1,537 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+
+/**
+ * ActionTimelineData
+ * @name ccs.ActionTimelineData
+ * @extend ccs.Class
+ * @class
+ *
+ */
+ccs.ActionTimelineData = ccs.Class.extend({
+
+ _actionTag: 0,
+
+ ctor: function (actionTag) {
+ this._init(actionTag);
+ },
+
+ _init: function (actionTag) {
+ this._actionTag = actionTag;
+ return true;
+ },
+
+ /**
+ * Set the action tag.
+ * @param {number} actionTag
+ */
+ setActionTag: function (actionTag) {
+ this._actionTag = actionTag;
+ },
+
+ /**
+ * Gets the action tag.
+ */
+ getActionTag: function () {
+ return this._actionTag;
+ }
+
+});
+
+ccs.AnimationInfo = function (name, start, end) {
+ this.name = name;
+ this.startIndex = start;
+ this.endIndex = end;
+};
+
+ccs.ComExtensionData = ccs.Component.extend({
+
+ _customProperty: null,
+ _timelineData: null,
+ _name: "ComExtensionData",
+
+ ctor: function(){
+ this._customProperty = "";
+ this._timelineData = new ccs.ActionTimelineData(0);
+ return true;
+ },
+
+ setActionTag: function(actionTag){
+ this._timelineData.setActionTag(actionTag);
+ },
+
+ getActionTag: function(){
+ return this._timelineData.getActionTag();
+ },
+
+ setCustomProperty: function(customProperty){
+ this._customProperty = customProperty;
+ },
+
+ getCustomProperty: function(){
+ return this._customProperty;
+ }
+
+});
+
+ccs.ComExtensionData.create = function(){
+ return new ccs.ComExtensionData();
+};
+
+/**
+ * Create new ActionTimelineData.
+ *
+ * @deprecated v3.0, please use new ccs.ActionTimelineData() instead.
+ *
+ * @name ccs.ActionTimelineData.create
+ * @function
+ * @param actionTag
+ * @returns {ccs.ActionTimelineData}
+ */
+ccs.ActionTimelineData.create = function (actionTag) {
+ return new ccs.ActionTimelineData(actionTag);
+};
+
+
+/**
+ * ActionTimeline
+ * @class
+ * @extend cc.Action
+ *
+ * @property gotoFrameAndPlay
+ * @property gotoFrameAndPause
+ */
+ccs.ActionTimeline = cc.Action.extend({
+
+ _timelineMap: null,
+ _timelineList: null,
+ _duration: 0,
+ _time: null,
+ _timeSpeed: 1,
+ _frameInternal: 1 / 60,
+ _playing: false,
+ _currentFrame: 0,
+ _startFrame: 0,
+ _endFrame: 0,
+ _loop: null,
+ _frameEventListener: null,
+ _animationInfos: null,
+ _lastFrameListener: null,
+
+ ctor: function () {
+ cc.Action.prototype.ctor.call(this);
+ this._timelineMap = {};
+ this._timelineList = [];
+ this._animationInfos = {};
+ this.init();
+ },
+
+ _gotoFrame: function (frameIndex) {
+ var size = this._timelineList.length;
+ for (var i = 0; i < size; i++) {
+ this._timelineList[i]._gotoFrame(frameIndex);
+ }
+ },
+
+ _stepToFrame: function (frameIndex) {
+ var size = this._timelineList.length;
+ for (var i = 0; i < size; i++) {
+ this._timelineList[i]._stepToFrame(frameIndex);
+ }
+ },
+
+ //emit frame event, call it when enter a frame
+ _emitFrameEvent: function (frame) {
+ if (this._frameEventListener) {
+ this._frameEventListener(frame);
+ }
+ },
+
+ init: function () {
+ return true;
+ },
+
+ /**
+ * Goto the specified frame index, and start playing from this index.
+ * @param startIndex The animation will play from this index.
+ * @param [endIndex=] The animation will end at this index.
+ * @param [currentFrameIndex=] set current frame index.
+ * @param [loop=] Whether or not the animation need loop.
+ */
+ gotoFrameAndPlay: function (startIndex, endIndex, currentFrameIndex, loop) {
+ //Consolidation parameters
+ var i = 0,
+ argLen = arguments.length;
+ var num = [],
+ bool;
+ for (i; i < argLen; i++) {
+ if (typeof arguments[i] === "boolean") {
+ bool = arguments[i];
+ } else {
+ num.push(arguments[i]);
+ }
+ }
+ startIndex = num[0];
+ endIndex = num[1] !== undefined ? num[1] : this._duration;
+ currentFrameIndex = num[2] || startIndex;
+ loop = bool != null ? bool : true;
+
+ this._startFrame = startIndex;
+ this._endFrame = endIndex;
+ this._currentFrame = currentFrameIndex;
+ this._loop = loop;
+ this._time = this._currentFrame * this._frameInternal;
+
+ this.resume();
+ this._gotoFrame(this._currentFrame);
+ },
+
+ /**
+ * Goto the specified frame index, and pause at this index.
+ * @param startIndex The animation will pause at this index.
+ */
+ gotoFrameAndPause: function (startIndex) {
+ this._startFrame = this._currentFrame = startIndex;
+ this._time = this._currentFrame * this._frameInternal;
+
+ this.pause();
+ this._gotoFrame(this._currentFrame);
+ },
+
+ /**
+ * Pause the animation.
+ */
+ pause: function () {
+ this._playing = false;
+ },
+
+ /**
+ * Resume the animation.
+ */
+ resume: function () {
+ this._playing = true;
+ },
+
+ /**
+ * Whether or not Action is playing.
+ */
+ isPlaying: function () {
+ return this._playing;
+ },
+
+ /**
+ * Set the animation speed, this will speed up or slow down the speed.
+ * @param {number} speed
+ */
+ setTimeSpeed: function (speed) {
+ this._timeSpeed = speed;
+ },
+
+ /**
+ * Get current animation speed.
+ * @returns {number}
+ */
+ getTimeSpeed: function () {
+ return this._timeSpeed;
+ },
+
+ /**
+ * duration of the whole action
+ * @param {number} duration
+ */
+ setDuration: function (duration) {
+ this._duration = duration;
+ },
+
+ /**
+ * Get current animation duration.
+ * @returns {number}
+ */
+ getDuration: function () {
+ return this._duration;
+ },
+
+ /**
+ * Start frame index of this action
+ * @returns {number}
+ */
+ getStartFrame: function () {
+ return this._startFrame;
+ },
+
+ /**
+ * End frame of this action.
+ * When action play to this frame, if action is not loop, then it will stop,
+ * or it will play from start frame again.
+ * @returns {number}
+ */
+ getEndFrame: function () {
+ return this._endFrame;
+ },
+
+ /**
+ * Set current frame index, this will cause action plays to this frame.
+ */
+ setCurrentFrame: function (frameIndex) {
+ if (frameIndex >= this._startFrame && frameIndex <= this._endFrame) {
+ this._currentFrame = frameIndex;
+ this._time = this._currentFrame * this._frameInternal;
+ } else {
+ cc.log("frame index is not between start frame and end frame");
+ }
+
+ },
+
+ /**
+ * Get current frame.
+ * @returns {number}
+ */
+ getCurrentFrame: function () {
+ return this._currentFrame;
+ },
+
+ /**
+ * add Timeline to ActionTimeline
+ * @param {ccs.Timeline} timeline
+ */
+ addTimeline: function (timeline) {
+ var tag = timeline.getActionTag();
+ if (!this._timelineMap[tag]) {
+ this._timelineMap[tag] = [];
+ }
+
+ if (this._timelineMap[tag].indexOf(timeline) === -1) {
+ this._timelineList.push(timeline);
+ this._timelineMap[tag].push(timeline);
+ timeline.setActionTimeline(this);
+ }
+
+ },
+
+ /**
+ * remove Timeline to ActionTimeline
+ * @param {ccs.Timeline} timeline
+ */
+ removeTimeline: function (timeline) {
+ var tag = timeline.getActionTag();
+ if (this._timelineMap[tag]) {
+ if (this._timelineMap[tag].some(function (item) {
+ if (item === timeline)
+ return true;
+ })) {
+ cc.arrayRemoveObject(this._timelineMap[tag], timeline);
+ cc.arrayRemoveObject(this._timelineList, timeline);
+ timeline.setActionTimeline(null);
+ }
+ }
+ },
+
+ /**
+ * Gets the timeline list
+ * @returns {array | null}
+ */
+ getTimelines: function () {
+ return this._timelineList;
+ },
+
+ /**
+ * Set the Frame event
+ * @param {function} listener
+ */
+ setFrameEventCallFunc: function (listener) {
+ this._frameEventListener = listener;
+ },
+
+ /**
+ * remove event
+ */
+ clearFrameEventCallFunc: function () {
+ this._frameEventListener = null;
+ },
+
+ /**
+ * Clone this timeline
+ * @returns {ccs.ActionTimeline}
+ */
+ clone: function () {
+ var newAction = new ccs.ActionTimeline();
+ newAction.setDuration(this._duration);
+ newAction.setTimeSpeed(this._timeSpeed);
+
+ for (var a in this._timelineMap) {
+ var timelines = this._timelineMap[a];
+ for (var b in timelines) {
+ var timeline = timelines[b];
+ var newTimeline = timeline.clone();
+ newAction.addTimeline(newTimeline);
+ }
+ }
+
+ return newAction;
+
+ },
+
+ /**
+ * Reverse is not defined;
+ * @returns {null}
+ */
+ reverse: function () {
+ return null;
+ },
+
+ /**
+ * Stepping of this time line.
+ * @param {number} delta
+ */
+ step: function (delta) {
+ if (!this._playing || this._timelineMap.length === 0 || this._duration === 0) {
+ return;
+ }
+
+ this._time += delta * this._timeSpeed;
+ var endoffset = this._time - this._endFrame * this._frameInternal;
+
+ if (endoffset < this._frameInternal) {
+ this._currentFrame = Math.floor(this._time / this._frameInternal);
+ this._stepToFrame(this._currentFrame);
+ if (endoffset >= 0 && this._lastFrameListener)
+ this._lastFrameListener();
+ } else {
+ this._playing = this._loop;
+ if (!this._playing) {
+ this._time = this._endFrame * this._frameInternal;
+ if (this._currentFrame != this._endFrame) {
+ this._currentFrame = this._endFrame;
+ this._stepToFrame(this._currentFrame);
+ if (this._lastFrameListener)
+ this._lastFrameListener();
+ }
+ } else
+ this.gotoFrameAndPlay(this._startFrame, this._endFrame, this._loop);
+ }
+
+ },
+
+ _foreachNodeDescendant: function (parent, callback) {
+ callback(parent);
+
+ var children = parent.getChildren();
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ this._foreachNodeDescendant(child, callback);
+ }
+ },
+
+ /**
+ * start with node.
+ * @param {cc.Node} target
+ */
+ startWithTarget: function(target){
+ cc.Action.prototype.startWithTarget.call(this, target);
+
+ var self = this;
+ var callback = function(child){
+ var data = child.getComponent("ComExtensionData");
+
+ if(data) {
+ var actionTag = data.getActionTag();
+ if(self._timelineMap[actionTag]) {
+ var timelines = self._timelineMap[actionTag];
+ for (var i=0; i _renderCmd._debug
+ if (this._squareVertices === null)
+ this._squareVertices = [
+ {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}
+ ];
+
+ this._rackColor = cc.color.WHITE;
+ this._blendFunc = BlendFunc.ALPHA_NON_PREMULTIPLIED;
+
+ this._childBones = [];
+ this._boneSkins = [];
+
+ this._rackLength = length === undefined ? 50 : length;
+ this._rackWidth = 20;
+ this._updateVertices();
+ //this._updateColor();
+ },
+
+ visit: function (parent) {
+ this._visit && this._visit(parent && parent._renderCmd);
+ },
+
+ addSkin: function (skin, display, hideOthers/*false*/) {
+ // skin, display
+ // skin, display, hideOthers
+ var boneSkins = this._boneSkins;
+ debug.assert(skin != null, "Argument must be non-nil");
+ if (hideOthers) {
+ for (var i = 0; i < boneSkins.length; i++) {
+ boneSkins[i].setVisible(false);
+ }
+ }
+ Node.prototype.addChild.call(this, skin);
+ this._boneSkins.push(skin);
+ skin.setVisible(display);
+ },
+
+ getChildBones: function () {
+ return this._childBones;
+ },
+
+ getSkins: function () {
+ return this._boneSkins;
+ },
+
+ displaySkin: function (skin, hideOthers) {
+ var boneSkins = this._boneSkins;
+ var boneSkin, i;
+ if (typeof skin === "string") {
+ for (i = 0; i < boneSkins.length; i++) {
+ boneSkin = boneSkins[i];
+ if (skin == boneSkin.getName()) {
+ boneSkin.setVisible(true);
+ } else if (hideOthers) {
+ boneSkin.setVisible(false);
+ }
+ }
+ } else {
+ for (i = 0; i < boneSkins.length; i++) {
+ boneSkin = boneSkins[i];
+ if (boneSkin == skin) {
+ boneSkin.setVisible(true);
+ } else if (hideOthers) {
+ boneSkin.setVisible(false);
+ }
+ }
+ }
+ },
+
+ getVisibleSkins: function () {
+ var displayingSkins = [];
+ var boneSkins = this._boneSkins;
+ for (var boneSkin, i = 0; i < boneSkins.length; i++) {
+ boneSkin = boneSkins[i];
+ if (boneSkin.isVisible()) {
+ displayingSkins.push(boneSkin);
+ }
+ }
+ return displayingSkins;
+ },
+
+ getRootSkeletonNode: function () {
+ return this._rootSkeleton;
+ },
+
+ getAllSubBones: function () {
+ var allBones = [];
+ var boneStack = []; // for avoid recursive
+ var childBones = this._childBones;
+ for (var i = 0; i < childBones.length; i++) {
+ boneStack.push(childBones[i]);
+ }
+
+ while (boneStack.length > 0) {
+ var top = boneStack.pop();
+ allBones.push(top);
+ var topChildren = top.getChildBones();
+ for (var j = 0; j < topChildren; j++) {
+ boneStack.push(topChildren[j]);
+ }
+ }
+ return allBones;
+ },
+
+ getAllSubSkins: function () {
+ var allBones = this.getAllSubBones();
+ var allSkins = [];
+ for (var i = 0; i < allBones.length; i++) {
+ var skins = allBones[i].getSkins();
+ for (var j = 0; j < skins.length; j++) {
+ allSkins.push(skins[i]);
+ }
+ }
+ return allSkins;
+ },
+
+ addChild: function (child, localZOrder, tag) {
+ //child, localZOrder, tag
+ //child, localZOrder, name
+ Node.prototype.addChild.call(this, child, localZOrder, tag);
+ this._addToChildrenListHelper(child);
+ },
+
+ removeChild: function (child, cleanup) {
+ if (this._children.indexOf(child) !== -1) {
+ Node.prototype.removeChild.call(this, child, cleanup);
+ this._removeFromChildrenListHelper(child);
+ }
+ },
+
+ setBlendFunc: function (blendFunc) {
+ var ob = this._blendFunc;
+ if (blendFunc && ob.src !== blendFunc.src && ob.dst !== blendFunc.dst) {
+ this._blendFunc = blendFunc;
+ var boneSkins = this._boneSkins;
+ for (var boneSkin, i = 0; i < boneSkins.length; i++) {
+ boneSkin = boneSkins[i];
+ boneSkin.setBlendFunc(blendFunc);
+ }
+ }
+ },
+
+ getBlendFunc: function () {
+ return this._blendFunc;
+ },
+
+ setDebugDrawLength: function (length) {
+ this._rackLength = length;
+ this._updateVertices();
+ },
+
+ getDebugDrawLength: function () {
+ return this._rackLength;
+ },
+
+ setDebugDrawWidth: function (width) {
+ this._rackWidth = width;
+ this._updateVertices();
+ },
+
+ getDebugDrawWidth: function () {
+ return this._rackWidth;
+ },
+
+ setDebugDrawEnabled: function (isDebugDraw) {
+ var renderCmd = this._renderCmd;
+ if (renderCmd._debug === isDebugDraw)
+ return;
+
+ renderCmd._debug = isDebugDraw;
+ cc.renderer.childrenOrderDirty = true;
+
+ if (this._visible && null != this._rootSkeleton) {
+ this._rootSkeleton._subBonesDirty = true;
+ this._rootSkeleton._subBonesOrderDirty = true;
+ }
+ },
+
+ isDebugDrawEnabled: function () {
+ return this._renderCmd._debug;
+ },
+
+ setDebugDrawColor: function (color) {
+ this._rackColor = color;
+ },
+
+ getDebugDrawColor: function () {
+ return this._rackColor;
+ },
+
+ getVisibleSkinsRect: function () {
+ var minx, miny, maxx, maxy = 0;
+ minx = miny = maxx = maxy;
+ var first = true;
+
+ var displayRect = type.rect(0, 0, 0, 0);
+ if (this._renderCmd._debug && this._rootSkeleton != null && this._rootSkeleton._renderCmd._debug) {
+ maxx = this._rackWidth;
+ maxy = this._rackLength;
+ first = false;
+ }
+
+ var boneSkins = this._boneSkins;
+ for (var skin, i = 0; i < boneSkins.length; i++) {
+ skin = boneSkins[i];
+ var r = skin.getBoundingBox();
+ if (!skin.isVisible() || (r.x === 0 && r.y === 0 && r.width === 0 && r.height === 0))
+ continue;
+
+ if (first) {
+ minx = cc.rectGetMinX(r);
+ miny = cc.rectGetMinY(r);
+ maxx = cc.rectGetMaxX(r);
+ maxy = cc.rectGetMaxY(r);
+
+ first = false;
+ } else {
+ minx = Math.min(cc.rectGetMinX(r), minx);
+ miny = Math.min(cc.rectGetMinY(r), miny);
+ maxx = Math.max(cc.rectGetMaxX(r), maxx);
+ maxy = Math.max(cc.rectGetMaxY(r), maxy);
+ }
+ displayRect.setRect(minx, miny, maxx - minx, maxy - miny);
+ }
+ return displayRect;
+ },
+
+ getBoundingBox: function () {
+ var boundingBox = this.getVisibleSkinsRect();
+ return cc.rectApplyAffineTransform(boundingBox, this.getNodeToParentAffineTransform());
+ },
+
+ batchBoneDrawToSkeleton: function (bone) {
+ },
+
+ setLocalZOrder: function (localZOrder) {
+ Node.prototype.setLocalZOrder.call(this, localZOrder);
+ if (this._rootSkeleton != null)
+ this._rootSkeleton._subBonesOrderDirty = true;
+ },
+
+ setName: function (name) {
+ var rootSkeleton = this._rootSkeleton;
+ var oldName = this.getName();
+ Node.prototype.setName.call(this, name);
+ if (rootSkeleton != null) {
+ var oIter = rootSkeleton._subBonesMap[oldName];
+ var nIter = rootSkeleton._subBonesMap[name];
+ if (oIter && !nIter) {
+ delete rootSkeleton._subBonesMap[oIter];
+ rootSkeleton._subBonesMap[name] = oIter;
+ }
+ }
+ },
+
+ setContentSize: function (contentSize) {
+ Node.prototype.setContentSize.call(this, contentSize);
+ this._updateVertices();
+ },
+
+ setAnchorPoint: function (anchorPoint) {
+ Node.prototype.setAnchorPoint.call(this, anchorPoint);
+ this._updateVertices();
+ },
+
+ setVisible: function (visible) {
+ if (this._visible == visible)
+ return;
+ Node.prototype.setVisible.call(this, visible);
+ if (this._rootSkeleton != null) {
+ this._rootSkeleton._subBonesDirty = true;
+ this._rootSkeleton._subBonesOrderDirty = true;
+ }
+ },
+
+ _addToChildrenListHelper: function (child) {
+ if (child instanceof BoneNode) {
+ this._addToBoneList(child);
+ } else {
+ //if (child instanceof SkinNode) {
+ this._addToSkinList(child);
+ //}
+ }
+ },
+
+ _removeFromChildrenListHelper: function (child) {
+ if (child instanceof BoneNode) {
+ this._removeFromBoneList(child);
+ } else {
+ if (child instanceof SkinNode)
+ this._removeFromSkinList(skin);
+ }
+ },
+
+ _removeFromBoneList: function (bone) {
+ if (
+ this._rootSkeleton != null &&
+ bone instanceof ccs.SkeletonNode &&
+ bone._rootSkeleton === this._rootSkeleton
+ ) {
+ bone._rootSkeleton = null;
+ var subBones = bone.getAllSubBones();
+ subBones.push(bone);
+ for (var subBone, i = 0; i < subBones.length; i++) {
+ subBone = subBones[i];
+ subBone._rootSkeleton = null;
+ delete this._rootSkeleton._subBonesMap[subBone.getName()];
+ this._rootSkeleton._subBonesDirty = true;
+ this._rootSkeleton._subBonesOrderDirty = true;
+ }
+ } else {
+ this._rootSkeleton._subBonesDirty = true;
+ this._rootSkeleton._subBonesOrderDirty = true;
+ }
+ cc.arrayRemoveObject(this._childBones, bone);
+ },
+
+ _setRootSkeleton: function (rootSkeleton) {
+ this._rootSkeleton = rootSkeleton;
+ var subBones = this.getAllSubBones();
+ for (var i = 0; i < subBones.length; i++) {
+ this._addToBoneList(subBones[i]);
+ }
+ },
+
+ _addToBoneList: function (bone) {
+ if (this._childBones.indexOf(bone) === -1)
+ this._childBones.push(bone);
+ if (this._rootSkeleton != null) {
+ var skeletonNode = bone;
+ if (!(skeletonNode instanceof SkinNode) && !bone._rootSkeleton) {// not nest skeleton
+ var subBones = bone.getAllSubBones();
+ subBones.push(bone);
+ for (var subBone, i = 0; i < subBones.length; i++) {
+ subBone = subBones[i];
+ subBone._setRootSkeleton(this._rootSkeleton);
+ var bonename = subBone.getName();
+ if (!this._rootSkeleton._subBonesMap[bonename]) {
+ this._rootSkeleton._subBonesMap[subBone.getName()] = subBone;
+ this._rootSkeleton._subBonesDirty = true;
+ this._rootSkeleton._subBonesOrderDirty = true;
+ } else {
+ cc.log("already has a bone named %s in skeleton %s", bonename, this._rootSkeleton.getName());
+ this._rootSkeleton._subBonesDirty = true;
+ this._rootSkeleton._subBonesOrderDirty = true;
+ }
+ }
+ }
+ }
+ },
+
+ _visitSkins: function () {
+ var cmd = this._renderCmd;
+ // quick return if not visible
+ if (!this._visible)
+ return;
+
+ var parentCmd = cmd.getParentRenderCmd();
+ if (parentCmd)
+ cmd._curLevel = parentCmd._curLevel + 1;
+
+ //visit for canvas
+ var i, children = this._boneSkins, child;
+ //var i, children = this._children, child;
+ cmd._syncStatus(parentCmd);
+ var len = children.length;
+ if (len > 0) {
+ this.sortAllChildren();
+ // draw children zOrder < 0
+ for (i = 0; i < len; i++) {
+ child = children[i];
+ if (child._localZOrder < 0)
+ child.visit(this);
+ else
+ break;
+ }
+ for (; i < len; i++)
+ children[i].visit(this);
+ }
+ cmd._dirtyFlag = 0;
+ },
+
+ _addToSkinList: function (skin) {
+ this._boneSkins.push(skin);
+ if (skin.getBlendFunc) {
+ var blendFunc = skin.getBlendFunc();
+ if (this._blendFunc.src !== blendFunc.src && this._blendFunc.dst !== blendFunc.dst)
+ skin.setBlendFunc(this._blendFunc);
+ }
+ },
+
+ _removeFromSkinList: function (skin) {
+ cc.arrayRemoveObject(this._boneSkins, skin);
+ },
+
+ sortAllChildren: function () {
+ this._sortArray(this._childBones);
+ this._sortArray(this._boneSkins);
+ Node.prototype.sortAllChildren.call(this);
+ },
+
+ _sortArray: function (array) {
+ if (!array)
+ return;
+ var len = array.length, i, j, tmp;
+ for (i = 1; i < len; i++) {
+ tmp = array[i];
+ j = i - 1;
+ while (j >= 0) {
+ if (tmp._localZOrder < array[j]._localZOrder) {
+ array[j + 1] = array[j];
+ } else if (tmp._localZOrder === array[j]._localZOrder && tmp.arrivalOrder < array[j].arrivalOrder) {
+ array[j + 1] = array[j];
+ } else {
+ break;
+ }
+ j--;
+ }
+ array[j + 1] = tmp;
+ }
+ },
+
+ _updateVertices: function () {
+ var squareVertices = this._squareVertices,
+ anchorPointInPoints = this._renderCmd._anchorPointInPoints;
+ if (this._rackLength != squareVertices[2].x - anchorPointInPoints.x ||
+ squareVertices[3].y != this._rackWidth / 2 - anchorPointInPoints.y) {
+
+ squareVertices[1].x = squareVertices[1].y = squareVertices[3].y = 0;
+ squareVertices[0].x = squareVertices[2].x = this._rackLength * .1;
+ squareVertices[2].y = this._rackWidth * .5;
+ squareVertices[0].y = -squareVertices[2].y;
+ squareVertices[3].x = this._rackLength;
+
+ for (var i = 0; i < squareVertices.length; i++) {
+ squareVertices[i].x += anchorPointInPoints.x;
+ squareVertices[i].y += anchorPointInPoints.y;
+ }
+
+ this._renderCmd.updateDebugPoint(squareVertices);
+ }
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new BoneNodeCanvasCmd(this);
+ else
+ return new BoneNodeWebGLCmd(this);
+ }
+ });
+
+ BoneNode.create = function (length, color) {
+ // null
+ // length
+ // length, color
+ return new ccui.BoneNode(length, color);
+ };
+
+ var BoneNodeCanvasCmd = (function () {
+
+ var BoneNodeCanvasCmd = function (node) {
+ this._rootCtor(node);
+ this._debug = false;
+ this._color = cc.color.WHITE;
+ this._drawNode = new cc.DrawNode();
+ };
+
+ var proto = BoneNodeCanvasCmd.prototype = Object.create(Node.CanvasRenderCmd.prototype);
+ proto.constructor = BoneNodeCanvasCmd;
+
+ proto.updateDebugPoint = function (points) {
+ this._drawNode.clear();
+ this._drawNode.drawPoly(points, this._color, 0, this._color);
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ var rootSkeleton = this._node._rootSkeleton;
+ this.originTransform(parentCmd, recursive);
+ if (rootSkeleton && rootSkeleton._renderCmd._debug) {
+ this._drawNode._renderCmd.transform(this);
+ }
+ };
+
+ return BoneNodeCanvasCmd;
+
+ })();
+
+ var BoneNodeWebGLCmd = (function () {
+
+ var BoneNodeWebGLCmd = function (node) {
+ this._rootCtor(node);
+ this._debug = false;
+ this._color = cc.color.WHITE;
+ this._drawNode = new cc.DrawNode();
+ };
+
+ var proto = BoneNodeWebGLCmd.prototype = Object.create(Node.WebGLRenderCmd.prototype);
+ proto.constructor = BoneNodeWebGLCmd;
+
+ proto.updateDebugPoint = function (points) {
+ this._drawNode.clear();
+ this._drawNode.drawPoly(points, this._color, 0, this._color);
+ };
+
+ proto.transform = function (parentCmd, recursive) {
+ var rootSkeleton = this._node._rootSkeleton;
+ this.originTransform(parentCmd, recursive);
+ if (rootSkeleton && rootSkeleton._renderCmd._debug) {
+ this._drawNode._renderCmd.transform(this);
+ }
+ };
+
+ return BoneNodeWebGLCmd;
+
+ })();
+
+ return BoneNode;
+
+})();
diff --git a/extensions/cocostudio/timeline/CCSkeletonNode.js b/extensions/cocostudio/timeline/CCSkeletonNode.js
new file mode 100644
index 0000000000..2bd075f51e
--- /dev/null
+++ b/extensions/cocostudio/timeline/CCSkeletonNode.js
@@ -0,0 +1,266 @@
+/****************************************************************************
+ Copyright (c) 2015-2016 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+//9980397
+
+/**
+ * SkeletonNode
+ * base class
+ * @class
+ */
+ccs.SkeletonNode = (function () {
+
+ var BoneNode = ccs.BoneNode;
+
+ var type = {
+ p: cc.p,
+ size: cc.size,
+ rect: cc.rect
+ };
+
+ var SkeletonNode = BoneNode.extend(/** @lends ccs.SkeletonNode# */{
+ _subBonesMap: null,
+
+ _squareVertices: null,
+ _squareColors: null,
+ _noMVPVertices: null,
+ _skinGroupMap: null,
+
+ _sortedAllBonesDirty: false,
+ _sortedAllBones: null,
+ _batchedBoneVetices: null,
+ _batchedBoneColors: null,
+ _batchedVeticesCount: null,
+ _batchBoneCommand: null,
+ _subOrderedAllBones: null,
+
+ ctor: function () {
+ this._squareVertices = [
+ {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0},
+ {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}, {x: 0, y: 0}
+ ];
+ this._rootSkeleton = this;
+ BoneNode.prototype.ctor.call(this);
+ this._subBonesMap = {};
+ this._subOrderedAllBones = [];
+
+ this._skinGroupMap = {};
+
+ this._rackLength = this._rackWidth = 20;
+ this._updateVertices();
+ },
+
+ getBoneNode: function (boneName) {
+ var item = this._subBonesMap[boneName];
+ if (item)
+ return item;
+ return null;
+ },
+
+ getAllSubBonesMap: function () {
+ return this._subBonesMap;
+ },
+
+ changeSkins: function (boneSkinNameMap) {
+ //boneSkinNameMap
+ //suitName
+ if (typeof boneSkinNameMap === "object") {
+ var boneSkin;
+ for (var name in boneSkinNameMap) {
+ boneSkin = boneSkinNameMap[name];
+ var bone = this.getBoneNode(name);
+ if (null !== bone)
+ bone.displaySkin(boneSkin, true);
+ }
+ } else {
+ var suit = this._suitMap[boneSkinNameMap/*suitName*/];
+ if (suit)
+ this.changeSkins(suit, true);
+ }
+ },
+
+ addSkinGroup: function (groupName, boneSkinNameMap) {
+ this._skinGroupMap[groupName] = boneSkinNameMap;
+ },
+
+ getBoundingBox: function () {
+ var minx, miny, maxx, maxy = 0;
+ minx = miny = maxx = maxy;
+ var boundingBox = this.getVisibleSkinsRect();
+ var first = true;
+ if (boundingBox.x !== 0 || boundingBox.y !== 0 || boundingBox.width !== 0 || boundingBox.height !== 0) {
+ minx = cc.rectGetMinX(boundingBox);
+ miny = cc.rectGetMinY(boundingBox);
+ maxx = cc.rectGetMaxX(boundingBox);
+ maxy = cc.rectGetMaxY(boundingBox);
+ first = false;
+ }
+ var allBones = this.getAllSubBones();
+ for (var bone, i = 0; i < allBones.length; i++) {
+ bone = allBones[i];
+ var r = cc.rectApplyAffineTransform(bone.getVisibleSkinsRect(), bone.getNodeToParentTransform(bone.getRootSkeletonNode()));
+ if (r.x === 0 && r.y === 0 && r.width === 0 && r.height === 0)
+ continue;
+
+ if (first) {
+ minx = cc.rectGetMinX(r);
+ miny = cc.rectGetMinY(r);
+ maxx = cc.rectGetMaxX(r);
+ maxy = cc.rectGetMaxY(r);
+
+ first = false;
+ } else {
+ minx = Math.min(cc.rectGetMinX(r), minx);
+ miny = Math.min(cc.rectGetMinY(r), miny);
+ maxx = Math.max(cc.rectGetMaxX(r), maxx);
+ maxy = Math.max(cc.rectGetMaxY(r), maxy);
+ }
+ }
+ boundingBox.x = minx;
+ boundingBox.y = miny;
+ boundingBox.width = maxx - minx;
+ boundingBox.height = maxy - miny;
+ return cc.rectApplyAffineTransform(boundingBox, this.getNodeToParentTransform());
+ },
+
+ _visit: function (parentCmd) {
+ var cmd = this._renderCmd;
+ parentCmd = parentCmd || cmd.getParentRenderCmd();
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+ cmd._syncStatus(parentCmd);
+
+ var i, node;
+ if (this._children.length !== 0) {
+ for (i = 0; i < this._children.length; i++) {
+ node = this._children[i];
+ node.visit(this);
+ }
+ }
+
+ this._checkSubBonesDirty();
+ var subOrderedAllBones = this._subOrderedAllBones,
+ subOrderedBone, subOrderedBoneCmd;
+ for (i = 0; i < subOrderedAllBones.length; i++) {
+ subOrderedBone = subOrderedAllBones[i];
+ subOrderedBone._visitSkins();
+ }
+
+ if (cmd._debug)
+ for (i = 0; i < subOrderedAllBones.length; i++) {
+ subOrderedBoneCmd = subOrderedAllBones[i]._renderCmd;
+ cc.renderer.pushRenderCommand(subOrderedBoneCmd._drawNode._renderCmd);
+ }
+ cmd._dirtyFlag = 0;
+ },
+
+ _checkSubBonesDirty: function () {
+ if (this._subBonesDirty) {
+ this._updateOrderedAllbones();
+ this._subBonesDirty = false;
+ }
+ if (this._subBonesOrderDirty) {
+ this._sortOrderedAllBones();
+ this._subBonesOrderDirty = false;
+ }
+ },
+
+ _updateOrderedAllbones: function () {
+ this._subOrderedAllBones.length = 0;
+ // update sub bones, get All Visible SubBones
+ // get all sub bones as visit with visible
+ var boneStack = [];
+ var childBones = this._childBones;
+ for (var bone, i = 0; i < childBones.length; i++) {
+ bone = childBones[i];
+ if (bone.isVisible())
+ boneStack.push(bone);
+ }
+ while (boneStack.length > 0) {
+ var top = boneStack.pop();
+ var topCmd = top._renderCmd;
+ topCmd._syncStatus(topCmd.getParentRenderCmd());
+ this._subOrderedAllBones.push(top);
+
+ var topChildren = top.getChildBones();
+
+ for (var childbone, i = 0; i < topChildren.length; i++) {
+ childbone = topChildren[i];
+ if (childbone.isVisible())
+ boneStack.push(childbone);
+ }
+ }
+ },
+
+ _sortOrderedAllBones: function () {
+ this._sortArray(this._subOrderedAllBones);
+ },
+
+ // protected
+ _updateVertices: function () {
+ var squareVertices = this._squareVertices,
+ anchorPointInPoints = this._renderCmd._anchorPointInPoints;
+ if (this._rackLength != squareVertices[6].x - anchorPointInPoints.x ||
+ this._rackWidth != squareVertices[3].y - anchorPointInPoints.y) {
+ var radiusl = this._rackLength * .5;
+ var radiusw = this._rackWidth * .5;
+ var radiusl_2 = radiusl * .25;
+ var radiusw_2 = radiusw * .25;
+ squareVertices[5].y = squareVertices[2].y = squareVertices[1].y = squareVertices[6].y
+ = squareVertices[0].x = squareVertices[4].x = squareVertices[7].x = squareVertices[3].x = .0;
+ squareVertices[5].x = -radiusl; squareVertices[0].y = -radiusw;
+ squareVertices[6].x = radiusl; squareVertices[3].y = radiusw;
+ squareVertices[1].x = radiusl_2; squareVertices[7].y = radiusw_2;
+ squareVertices[2].x = -radiusl_2; squareVertices[4].y = -radiusw_2;
+ for (var i = 0; i < squareVertices.length; i++) {
+ squareVertices[i].x += anchorPointInPoints.x;
+ squareVertices[i].y += anchorPointInPoints.y;
+ }
+ }
+ },
+
+ _updateAllDrawBones: function () {
+ this._subDrawBones = {}; //.clear()
+ for (var name in this._subBonesMap) {
+ var bone = this._subBonesMap[name];
+ if (bone.isVisible() && bone.isDebugDrawEnabled())
+ this._subDrawBones.push(bone);
+ }
+ this._sortArray(this._sortedAllBones);
+ this._subDrawBones = false;
+ }
+
+ });
+
+ SkeletonNode.create = function () {
+ return new SkeletonNode;
+ };
+
+ return SkeletonNode;
+
+})();
diff --git a/extensions/cocostudio/timeline/CCSkinNode.js b/extensions/cocostudio/timeline/CCSkinNode.js
new file mode 100644
index 0000000000..310af38c2c
--- /dev/null
+++ b/extensions/cocostudio/timeline/CCSkinNode.js
@@ -0,0 +1,14 @@
+ccs.SkinNode = (function () {
+
+ var Node = cc.Node;
+
+ var proto = {};
+
+ var SkinNode = Node.extend(proto);
+
+ SkinNode.create = function () {
+ };
+
+ return SkinNode;
+
+})();
diff --git a/extensions/cocostudio/timeline/Frame.js b/extensions/cocostudio/timeline/Frame.js
new file mode 100644
index 0000000000..b935fcee6b
--- /dev/null
+++ b/extensions/cocostudio/timeline/Frame.js
@@ -0,0 +1,1430 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * Timeline Frame.
+ * base class
+ * @class
+ */
+ccs.Frame = ccs.Class.extend({
+
+ _frameIndex: null,
+ _tween: null,
+ _timeline: null,
+ _node: null,
+ _tweenType: null,
+ _easingParam: null,
+ _enterWhenPassed: null,
+
+ ctor: function () {
+ this._frameIndex = 0;
+ this._tween = true;
+ this._timeline = null;
+ this._node = null;
+ this._enterWhenPassed = false;
+ this._easingParam = [];
+ },
+
+ _emitEvent: function () {
+ if (this._timeline) {
+ this._timeline.getActionTimeline()._emitFrameEvent(this);
+ }
+ },
+
+ _cloneProperty: function (frame) {
+ this._frameIndex = frame.getFrameIndex();
+ this._tween = frame.isTween();
+ this._tweenType = frame.getTweenType();
+ this.setEasingParams(frame.getEasingParams());
+ },
+
+ /**
+ * Set the frame index
+ * @param {number} frameIndex
+ */
+ setFrameIndex: function (frameIndex) {
+ this._frameIndex = frameIndex;
+ },
+
+ /**
+ * Get the frame index
+ * @returns {null}
+ */
+ getFrameIndex: function () {
+ return this._frameIndex;
+ },
+
+ /**
+ * Set timeline
+ * @param timeline
+ */
+ setTimeline: function (timeline) {
+ this._timeline = timeline;
+ },
+
+ /**
+ * Get timeline
+ * @param timeline
+ * @returns {ccs.timeline}
+ */
+ getTimeline: function (timeline) {
+ return this._timeline;
+ },
+
+ /**
+ * Set Node
+ * @param {cc.Node} node
+ */
+ setNode: function (node) {
+ this._node = node;
+ },
+
+ /**
+ * gets the Node
+ * @return node
+ */
+ getNode: function () {
+ return this._node;
+ },
+
+ /**
+ * set tween
+ * @param tween
+ */
+ setTween: function (tween) {
+ this._tween = tween;
+ },
+
+ /**
+ * Gets the tween
+ * @returns {boolean | null}
+ */
+ isTween: function () {
+ return this._tween;
+ },
+
+ /**
+ * the execution of the callback
+ * @override
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) { // = 0
+ },
+
+ /**
+ * Each frame logic
+ * @override
+ * @param {number} percent
+ */
+ apply: function (percent) {
+ if (!this._tween)
+ return;
+ if (this._tweenType !== ccs.FrameEaseType.TWEEN_EASING_MAX && this._tweenType !== ccs.FrameEaseType.LINEAR)
+ percent = this.tweenPercent(percent);
+ this._onApply(percent);
+ },
+
+ _onApply: function (percent) {
+
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @override
+ * @return {ccs.Frame}
+ */
+ clone: function () { // = 0
+ },
+
+ tweenPercent: function (percent) {
+ var func = ccs.Frame.tweenToMap[this._tweenType];
+ if (func)
+ return func(percent, this._easingParam);
+ else
+ return percent;
+ },
+
+ setEasingParams: function (easingParams) {
+ if (easingParams) {
+ this._easingParam.length = 0;
+ for (var i = 0; i < easingParams.length; i++)
+ this._easingParam[i] = easingParams[i];
+ }
+ },
+
+ getEasingParams: function () {
+ return this._easingParam;
+ },
+
+ setTweenType: function (tweenType) {
+ this._tweenType = tweenType;
+ },
+
+ getTweenType: function () {
+ return this._tweenType;
+ },
+
+ isEnterWhenPassed: function () {
+ return this._enterWhenPassed;
+ }
+});
+
+ccs.Frame.tweenToMap = {
+ "-1": function (time, easingParam) {
+ if (easingParam) {
+ var tt = 1 - time;
+ return easingParam[1] * tt * tt * tt + 3 * easingParam[3] * time * tt * tt + 3 * easingParam[5] * time * time * tt + easingParam[7] * time * time * time;
+ }
+ return time;
+ },
+ 1: cc._easeSineInObj.easing,//Sine_EaseIn
+ 2: cc._easeSineOutObj.easing,//Sine_EaseOut
+ 3: cc._easeSineInOutObj.easing,//Sine_EaseInOut
+
+ 4: cc._easeQuadraticActionIn.easing,//Quad_EaseIn
+ 5: cc._easeQuadraticActionOut.easing,//Quad_EaseOut
+ 6: cc._easeQuadraticActionInOut.easing,//Quad_EaseInOut
+
+ 7: cc._easeCubicActionIn.easing, //Cubic_EaseIn
+ 8: cc._easeCubicActionOut.easing,//Cubic_EaseOut
+ 9: cc._easeCubicActionInOut.easing,//Cubic_EaseInOut
+
+ 10: cc._easeCubicActionIn.easing,//Cubic_EaseIn
+ 11: cc._easeCubicActionOut.easing,//Cubic_EaseOut
+ 12: cc._easeCubicActionInOut.easing,//Cubic_EaseInOut
+
+ 13: cc._easeQuinticActionIn.easing,//Quint_EaseIn
+ 14: cc._easeQuinticActionOut.easing,//Quint_EaseOut
+ 15: cc._easeQuinticActionInOut.easing,//Quint_EaseInOut
+
+ 16: cc._easeExponentialInObj.easing,//Expo_EaseIn
+ 17: cc._easeExponentialOutObj.easing,//Expo_EaseOut
+ 18: cc._easeExponentialInOutObj.easing,//Expo_EaseInOut
+
+ 19: cc._easeCircleActionIn.easing,//Circ_EaseIn
+ 20: cc._easeCircleActionOut.easing,//Circ_EaseOut
+ 21: cc._easeCircleActionInOut.easing,//Circ_EaseInOut
+
+ 22: function (time, easingParam) {
+ var period = 0.3;
+ easingParam != null && ( period = easingParam[0] );
+ return cc.easeElasticIn(period).easing(time);
+ },//Elastic_EaesIn
+ 23: function (time, easingParam) {
+ var period = 0.3;
+ easingParam != null && ( period = easingParam[0] );
+ return cc.easeElasticOut(period).easing(time);
+ },//Elastic_EaesOut
+ 24: function (time, easingParam) {
+ var period = 0.3;
+ easingParam != null && ( period = easingParam[0] );
+ return cc.easeElasticInOut(period).easing(time);
+ },//Elastic_EaesInOut
+
+ 25: cc._easeBackInObj.easing, //Back_EaseIn
+ 26: cc._easeBackOutObj.easing, //Back_EaseOut
+ 27: cc._easeBackInOutObj.easing, //Back_EaseInOut
+
+ 28: cc._easeBounceInObj.easing, //Bounce_EaseIn
+ 29: cc._easeBounceOutObj.easing, //Bounce_EaseOut
+ 30: cc._easeBounceInOutObj.easing //Bounce_EaseInOut
+};
+
+/**
+ * Visible frame
+ * To control the display state
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.VisibleFrame = ccs.Frame.extend({
+
+ _visible: true,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._visible = true;
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (this._node)
+ this._node.setVisible(this._visible);
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.VisibleFrame}
+ */
+ clone: function () {
+ var frame = new ccs.VisibleFrame();
+ frame.setVisible(this._visible);
+
+ frame._cloneProperty(this);
+
+ return frame;
+ },
+
+ /**
+ * Set display state
+ * @param {Boolean} visible
+ */
+ setVisible: function (visible) {
+ this._visible = visible;
+ },
+
+ /**
+ * Get the display state
+ * @returns {Boolean}
+ */
+ isVisible: function () {
+ return this._visible;
+ }
+
+});
+
+/**
+ * Create the visible frame
+ *
+ * @deprecated v3.0, please use new ccs.VisibleFrame() instead.
+ * @returns {ccs.VisibleFrame}
+ */
+ccs.VisibleFrame.create = function () {
+ return new ccs.VisibleFrame();
+};
+
+/**
+ * Texture frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.TextureFrame = ccs.Frame.extend({
+
+ _sprite: null,
+ _textureName: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+
+ this._textureName = "";
+ },
+
+ /**
+ * Set the node element to draw texture
+ * @param {cc.Node} node
+ */
+ setNode: function (node) {
+ ccs.Frame.prototype.setNode.call(this, node);
+ this._sprite = node;
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (this._sprite) {
+ var spriteBlendFunc = this._sprite.getBlendFunc();
+ var spriteFrame = cc.spriteFrameCache._spriteFrames[this._textureName];
+ if (spriteFrame != null)
+ this._sprite.setSpriteFrame(spriteFrame);
+ else
+ this._sprite.setTexture(this._textureName);
+
+ if (this._sprite.getBlendFunc() !== spriteBlendFunc)
+ this._sprite.setBlendFunc(spriteBlendFunc);
+ }
+
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.TextureFrame}
+ */
+ clone: function () {
+ var frame = new ccs.TextureFrame();
+ frame.setTextureName(this._textureName);
+ frame._cloneProperty(this);
+ return frame;
+ },
+
+ /**
+ * Set the texture name
+ * @param {string} textureName
+ */
+ setTextureName: function (textureName) {
+ this._textureName = textureName;
+ },
+
+ /**
+ * Gets the Texture name
+ * @returns {null}
+ */
+ getTextureName: function () {
+ return this._textureName;
+ }
+
+});
+
+/**
+ * Create the Texture frame
+ *
+ * @deprecated v3.0, please use new ccs.TextureFrame() instead.
+ * @returns {ccs.TextureFrame}
+ */
+ccs.TextureFrame.create = function () {
+ return new ccs.TextureFrame();
+};
+
+/**
+ * Rotation Frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.RotationFrame = ccs.Frame.extend({
+
+ _rotation: null,
+ _betwennRotation: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._rotation = 0;
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (!this._node)
+ return;
+ this._node.setRotation(this._rotation);
+
+ if (this._tween) {
+ this._betwennRotation = nextFrame._rotation - this._rotation;
+ }
+ },
+
+ /**
+ * Each frame logic
+ * @param {number} percent
+ */
+ _onApply: function (percent) {
+ if (this._betwennRotation !== 0) {
+ var rotation = this._rotation + percent * this._betwennRotation;
+ this._node.setRotation(rotation);
+ }
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.RotationFrame}
+ */
+ clone: function () {
+ var frame = new ccs.RotationFrame();
+ frame.setRotation(this._rotation);
+
+ frame._cloneProperty(this);
+
+ return frame;
+ },
+
+ /**
+ * Set the rotation
+ * @param {Number} rotation
+ */
+ setRotation: function (rotation) {
+ this._rotation = rotation;
+ },
+
+ /**
+ * Gets the rotation
+ * @returns {Number}
+ */
+ getRotation: function () {
+ return this._rotation;
+ }
+
+});
+
+/**
+ * Create the Rotation frame
+ *
+ * @deprecated v3.0, please use new ccs.RotationFrame() instead.
+ * @returns {ccs.RotationFrame}
+ */
+ccs.RotationFrame.create = function () {
+ return new ccs.RotationFrame();
+};
+
+/**
+ * Skew frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.SkewFrame = ccs.Frame.extend({
+
+ _skewX: null,
+ _skewY: null,
+ _betweenSkewX: null,
+ _betweenSkewY: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._skewX = 0;
+ this._skewY = 0;
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (!this._node)
+ return;
+ this._node.setSkewX(this._skewX);
+ this._node.setSkewY(this._skewY);
+
+ if (this._tween) {
+ this._betweenSkewX = nextFrame._skewX - this._skewX;
+ this._betweenSkewY = nextFrame._skewY - this._skewY;
+ }
+
+ },
+
+ /**
+ * Each frame logic
+ * @param {number} percent
+ */
+ _onApply: function (percent) {
+ if (this._betweenSkewX !== 0 || this._betweenSkewY !== 0) {
+ var skewx = this._skewX + percent * this._betweenSkewX;
+ var skewy = this._skewY + percent * this._betweenSkewY;
+
+ this._node.setSkewX(skewx);
+ this._node.setSkewY(skewy);
+ }
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.SkewFrame}
+ */
+ clone: function () {
+ var frame = new ccs.SkewFrame();
+ frame.setSkewX(this._skewX);
+ frame.setSkewY(this._skewY);
+
+ frame._cloneProperty(this);
+
+ return frame;
+ },
+
+ /**
+ * Set the skew x
+ * @param {Number} skewx
+ */
+ setSkewX: function (skewx) {
+ this._skewX = skewx;
+ },
+
+ /**
+ * Gets the skew x
+ * @returns {Number}
+ */
+ getSkewX: function () {
+ return this._skewX;
+ },
+
+ /**
+ * Set the skew y
+ * @param {Number} skewy
+ */
+ setSkewY: function (skewy) {
+ this._skewY = skewy;
+ },
+
+ /**
+ * Gets the skew y
+ * @returns {Number}
+ */
+ getSkewY: function () {
+ return this._skewY;
+ }
+
+});
+
+/**
+ * Create the Skew frame
+ *
+ * @deprecated v3.0, please use new ccs.SkewFrame() instead.
+ * @returns {ccs.SkewFrame}
+ */
+ccs.SkewFrame.create = function () {
+ return new ccs.SkewFrame();
+};
+
+/**
+ * Rotation skew frame
+ * @class
+ * @extend ccs.SkewFrame
+ */
+ccs.RotationSkewFrame = ccs.SkewFrame.extend({
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (!this._node)
+ return;
+ this._node.setRotationX(this._skewX);
+ this._node.setRotationY(this._skewY);
+
+ if (this._tween) {
+ this._betweenSkewX = nextFrame._skewX - this._skewX;
+ this._betweenSkewY = nextFrame._skewY - this._skewY;
+ }
+
+ },
+
+ /**
+ * Each frame logic
+ * @param {number} percent
+ */
+ _onApply: function (percent) {
+ if (this._node && (this._betweenSkewX !== 0 || this._betweenSkewY !== 0)) {
+ var skewx = this._skewX + percent * this._betweenSkewX;
+ var skewy = this._skewY + percent * this._betweenSkewY;
+
+ this._node.setRotationX(skewx);
+ this._node.setRotationY(skewy);
+ }
+
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.RotationSkewFrame}
+ */
+ clone: function () {
+ var frame = new ccs.RotationSkewFrame();
+ frame.setSkewX(this._skewX);
+ frame.setSkewY(this._skewY);
+
+ frame._cloneProperty(this);
+
+ return frame;
+
+ }
+
+});
+
+/**
+ * Create the RotationSkew frame
+ *
+ * @deprecated v3.0, please use new ccs.RotationSkewFrame() instead.
+ * @returns {ccs.RotationSkewFrame}
+ */
+ccs.RotationSkewFrame.create = function () {
+ return new ccs.RotationSkewFrame();
+};
+
+/**
+ * Position frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.PositionFrame = ccs.Frame.extend({
+
+ _position: null,
+ _betweenX: null,
+ _betweenY: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._position = cc.p(0, 0);
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (!this._node)
+ return;
+
+ this._node.setPosition(this._position);
+
+ if (this._tween) {
+ this._betweenX = nextFrame._position.x - this._position.x;
+ this._betweenY = nextFrame._position.y - this._position.y;
+ }
+ },
+
+ /**
+ * Each frame logic
+ * @param {number} percent
+ */
+ _onApply: function (percent) {
+ if (this._node && (this._betweenX !== 0 || this._betweenY !== 0)) {
+ var p = cc.p(0, 0);
+ p.x = this._position.x + this._betweenX * percent;
+ p.y = this._position.y + this._betweenY * percent;
+
+ this._node.setPosition(p);
+ }
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.PositionFrame}
+ */
+ clone: function () {
+ var frame = new ccs.PositionFrame();
+ frame.setPosition(this._position);
+
+ frame._cloneProperty(this);
+
+ return frame;
+ },
+
+ /**
+ * Set the position
+ * @param {cc.p} position
+ */
+ setPosition: function (position) {
+ this._position = position;
+ },
+
+ /**
+ * gets the position
+ * @returns {cc.p}
+ */
+ getPosition: function () {
+ return this._position;
+ },
+
+ /**
+ * Set the position x
+ * @param {Number} x
+ */
+ setX: function (x) {
+ this._position.x = x;
+ },
+
+ /**
+ * Gets the position x
+ * @returns {Number}
+ */
+ getX: function () {
+ return this._position.x;
+ },
+
+ /**
+ * Set the position y
+ * @param {Number} y
+ */
+ setY: function (y) {
+ this._position.y = y;
+ },
+
+ /**
+ * Gets the position y
+ * @returns {Number}
+ */
+ getY: function () {
+ return this._position.y;
+ }
+
+});
+
+/**
+ * Create the Position frame
+ *
+ * @deprecated v3.0, please use new ccs.PositionFrame() instead.
+ * @returns {ccs.PositionFrame}
+ */
+ccs.PositionFrame.create = function () {
+ return new ccs.PositionFrame();
+};
+
+/**
+ * Scale frame
+ * @class
+ * @xtend ccs.Frame
+ */
+ccs.ScaleFrame = ccs.Frame.extend({
+
+ _scaleX: null,
+ _scaleY: null,
+ _betweenScaleX: null,
+ _betweenScaleY: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._scaleX = 1;
+ this._scaleY = 1;
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (!this._node)
+ return;
+ this._node.setScaleX(this._scaleX);
+ this._node.setScaleY(this._scaleY);
+
+ if (this._tween) {
+ this._betweenScaleX = nextFrame._scaleX - this._scaleX;
+ this._betweenScaleY = nextFrame._scaleY - this._scaleY;
+ }
+
+ },
+
+ /**
+ * Each frame logic
+ * @param {number} percent
+ */
+ _onApply: function (percent) {
+ if (this._node && (this._betweenScaleX !== 0 || this._betweenScaleY !== 0)) {
+ var scaleX = this._scaleX + this._betweenScaleX * percent;
+ var scaleY = this._scaleY + this._betweenScaleY * percent;
+
+ this._node.setScaleX(scaleX);
+ this._node.setScaleY(scaleY);
+ }
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.ScaleFrame}
+ */
+ clone: function () {
+ var frame = new ccs.ScaleFrame();
+ frame.setScaleX(this._scaleX);
+ frame.setScaleY(this._scaleY);
+
+ frame._cloneProperty(this);
+
+ return frame;
+
+ },
+
+ /**
+ * Set the scale
+ * @param {Number} scale
+ */
+ setScale: function (scale) {
+ this._scaleX = scale;
+ this._scaleY = scale;
+ },
+
+ /**
+ * Set the scale x
+ * @param {Number} scaleX
+ */
+ setScaleX: function (scaleX) {
+ this._scaleX = scaleX;
+ },
+
+ /**
+ * Gets the scale x
+ * @returns {Number}
+ */
+ getScaleX: function () {
+ return this._scaleX;
+ },
+
+ /**
+ * Set the scale y
+ * @param {Number} scaleY
+ */
+ setScaleY: function (scaleY) {
+ this._scaleY = scaleY;
+ },
+
+ /**
+ * Gets the scale y
+ * @returns {Number}
+ */
+ getScaleY: function () {
+ return this._scaleY;
+ }
+
+});
+
+/**
+ * Create the Scale frame
+ *
+ * @deprecated v3.0, please use new ccs.ScaleFrame() instead.
+ * @returns {ccs.ScaleFrame}
+ */
+ccs.ScaleFrame.create = function () {
+ return new ccs.ScaleFrame();
+};
+
+/**
+ * AnchorPoint frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.AnchorPointFrame = ccs.Frame.extend({
+
+ _anchorPoint: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._anchorPoint = cc.p(0, 0);
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (this._node)
+ this._node.setAnchorPoint(this._anchorPoint);
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.AnchorPointFrame}
+ */
+ clone: function () {
+ var frame = new ccs.AnchorPointFrame();
+ frame.setAnchorPoint(this._anchorPoint);
+
+ frame._cloneProperty(this);
+
+ return frame;
+ },
+
+ /**
+ * Set the anchor point
+ * @param {cc.p} point
+ */
+ setAnchorPoint: function (point) {
+ this._anchorPoint = point;
+ },
+
+ /**
+ * Gets the anchor point
+ * @returns {cc.p}
+ */
+ getAnchorPoint: function () {
+ return this._anchorPoint;
+ }
+
+});
+
+/**
+ * Create the AnchorPoint frame
+ *
+ * @deprecated v3.0, please use new ccs.AnchorPointFrame() instead.
+ * @returns {ccs.AnchorPointFrame}
+ */
+ccs.AnchorPointFrame.create = function () {
+ return new ccs.AnchorPointFrame();
+};
+
+/**
+ * Static param
+ * @namespace
+ */
+ccs.InnerActionType = {
+ LoopAction: 0,
+ NoLoopAction: 1,
+ SingleFrame: 2
+};
+
+/**
+ * Inner action frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.InnerActionFrame = ccs.Frame.extend({
+
+ _innerActionType: null,
+ _startFrameIndex: null,
+
+ _endFrameIndex: 0,
+ _singleFrameIndex: 0,
+ _enterWithName: null,
+ _animationName: "",
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+
+ this._enterWithName = false;
+ this._innerActionType = ccs.InnerActionType.LoopAction;
+ this._startFrameIndex = 0;
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (!this._node) return;
+ var innerActiontimeline = this._node.getActionByTag(this._node.getTag());
+ if (!innerActiontimeline) return;
+ if (ccs.InnerActionType.SingleFrame === this._innerActionType) {
+ innerActiontimeline.gotoFrameAndPause(this._singleFrameIndex);
+ return;
+ }
+
+ var innerStart = this._startFrameIndex;
+ var innerEnd = this._endFrameIndex;
+ if (this._enterWithName) {
+ if (this._animationName === "-- ALL --") {
+ innerStart = 0;
+ innerEnd = innerActiontimeline.getDuration();
+ } else if (innerActiontimeline.isAnimationInfoExists(this._animationName)) {
+ var info = innerActiontimeline.getAnimationInfo(this._animationName);
+ innerStart = info.startIndex;
+ innerEnd = info.endIndex;
+ } else {
+ cc.log("Animation %s not exists!", this._animationName);
+ }
+ }
+
+ var duration = this._timeline.getActionTimeline().getDuration();
+ var odddiff = duration - this._frameIndex - innerEnd + innerStart;
+ if (odddiff < 0) {
+ innerEnd += odddiff;
+ }
+
+ if (ccs.InnerActionType.NoLoopAction === this._innerActionType) {
+ innerActiontimeline.gotoFrameAndPlay(innerStart, innerEnd, false);
+ } else if (ccs.InnerActionType.LoopAction === this._innerActionType) {
+ innerActiontimeline.gotoFrameAndPlay(innerStart, innerEnd, true);
+ }
+ },
+
+ setAnimationName: function (animationName) {
+ this._animationName = animationName;
+ },
+
+ setSingleFrameIndex: function (frameIndex) {
+ this._singleFrameIndex = frameIndex;
+ },
+
+ getSingleFrameIndex: function () {
+ return this._startFrameIndex;
+ },
+
+ setEnterWithName: function (isEnterWithName) {
+ this._enterWithName = isEnterWithName;
+ },
+
+ getEnterWithName: function () {
+ return this._enterWithName;
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.InnerActionFrame}
+ */
+ clone: function () {
+ var frame = new ccs.InnerActionFrame();
+ frame.setInnerActionType(this._innerActionType);
+ frame.setStartFrameIndex(this._startFrameIndex);
+ frame.setEnterWithName(this._enterWithName);
+ frame.setAnimationName(this._animationName);
+ frame.setSingleFrameIndex(this._singleFrameIndex);
+
+ frame._cloneProperty(this);
+
+ return frame;
+
+ },
+
+ /**
+ * Set the inner action type
+ * @param {ccs.InnerActionType} type
+ */
+ setInnerActionType: function (type) {
+ this._innerActionType = type;
+ },
+
+ /**
+ * Gets the inner action type
+ * @returns {ccs.InnerActionType}
+ */
+ getInnerActionType: function () {
+ return this._innerActionType;
+ },
+
+ /**
+ * Set the start frame index
+ * @param {Number} frameIndex
+ */
+ setStartFrameIndex: function (frameIndex) {
+ this._startFrameIndex = frameIndex;
+ },
+
+ /**
+ * Get the start frame index
+ * @returns {Number}
+ */
+ getStartFrameIndex: function () {
+ return this._startFrameIndex;
+ }
+
+});
+
+/**
+ * Create the InnerAction frame
+ *
+ * @deprecated v3.0, please use new ccs.InnerActionFrame() instead.
+ * @returns {ccs.InnerActionFrame}
+ */
+ccs.InnerActionFrame.create = function () {
+ return new ccs.InnerActionFrame();
+};
+
+/**
+ * Color frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.ColorFrame = ccs.Frame.extend({
+
+ _alpha: null,
+ _color: null,
+
+ _betweenAlpha: null,
+ _betweenRed: null,
+ _betweenGreen: null,
+ _betweenBlue: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._color = cc.color(255, 255, 255);
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.ColorFrame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (!this._node)
+ return;
+ this._node.setColor(this._color);
+ if (this._tween) {
+ var color = nextFrame._color;
+ this._betweenRed = color.r - this._color.r;
+ this._betweenGreen = color.g - this._color.g;
+ this._betweenBlue = color.b - this._color.b;
+ }
+
+ },
+
+ /**
+ * Each frame logic
+ * @param {number} percent
+ */
+ _onApply: function (percent) {
+ if (this._node && this._tween && (this._betweenAlpha !== 0 || this._betweenRed !== 0 || this._betweenGreen !== 0 || this._betweenBlue !== 0)) {
+
+ var color = cc.color(255, 255, 255);
+ color.r = this._color.r + this._betweenRed * percent;
+ color.g = this._color.g + this._betweenGreen * percent;
+ color.b = this._color.b + this._betweenBlue * percent;
+
+ this._node.setColor(color);
+ if (this._alpha !== null) {
+ var alpha = this._alpha + this._betweenAlpha * percent;
+ this._node.setOpacity(alpha);
+ }
+
+ }
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.ColorFrame}
+ */
+ clone: function () {
+ var frame = new ccs.ColorFrame();
+ frame.setColor(this._color);
+ frame._cloneProperty(this);
+ return frame;
+ },
+
+ /**
+ * Set the color
+ * @param {cc.color} color
+ */
+ setColor: function (color) {
+ this._color = color;
+ },
+
+ /**
+ * Gets the color
+ * @returns {cc.color}
+ */
+ getColor: function () {
+ return this._color;
+ }
+
+});
+
+/**
+ * Create the Color frame
+ *
+ * @deprecated v3.0, please use new ccs.ColorFrame() instead.
+ * @returns {ccs.ColorFrame}
+ */
+ccs.ColorFrame.create = function () {
+ return new ccs.ColorFrame();
+};
+
+/**
+ * Alpha frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.AlphaFrame = ccs.Frame.extend({
+
+ _alpha: null,
+ _betweenAlpha: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._alpha = 255;
+ },
+
+ onEnter: function (nextFrame) {
+ if (!this._node)
+ return;
+ this._node.setOpacity(this._alpha);
+ if (this._tween) {
+ this._betweenAlpha = nextFrame._alpha - this._alpha;
+ }
+ },
+
+ _onApply: function (percent) {
+ if (!this._node)
+ return;
+ var alpha = this._alpha + this._betweenAlpha * percent;
+ this._node.setOpacity(alpha);
+ },
+
+ /**
+ * Set the alpha
+ * @param {Number} alpha
+ */
+ setAlpha: function (alpha) {
+ this._alpha = alpha;
+ },
+
+ /**
+ * Gets the alpha
+ * @returns {Number}
+ */
+ getAlpha: function () {
+ return this._alpha;
+ },
+
+ clone: function () {
+ var frame = new ccs.AlphaFrame();
+ frame.setAlpha(this._alpha);
+ frame._cloneProperty(this);
+ return frame;
+ }
+});
+
+/**
+ * Event frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.EventFrame = ccs.Frame.extend({
+
+ _event: null,
+
+ ctor: function () {
+ ccs.Frame.prototype.ctor.call(this);
+ this._event = "";
+ this._enterWhenPassed = true;
+ },
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ this._emitEvent();
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.EventFrame}
+ */
+ clone: function () {
+ var frame = new ccs.EventFrame();
+ frame.setEvent(this._event);
+
+ frame._cloneProperty(this);
+
+ return frame;
+ },
+
+ /**
+ * Set the event
+ * @param event
+ */
+ setEvent: function (event) {
+ this._event = event;
+ },
+
+ /**
+ * Gets the event
+ * @returns {null}
+ */
+ getEvent: function () {
+ return this._event;
+ }
+
+});
+
+/**
+ * Create the Event frame
+ *
+ * @deprecated v3.0, please use new ccs.EventFrame() instead.
+ * @returns {ccs.EventFrame}
+ */
+ccs.EventFrame.create = function () {
+ return new ccs.EventFrame();
+};
+
+/**
+ * zOrder frame
+ * @class
+ * @extend ccs.Frame
+ */
+ccs.ZOrderFrame = ccs.Frame.extend({
+
+ _zorder: 0,
+
+ /**
+ * the execution of the callback
+ * @param {ccs.Frame} nextFrame
+ */
+ onEnter: function (nextFrame) {
+ if (this._node)
+ this._node.setLocalZOrder(this._zorder);
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.ZOrderFrame}
+ */
+ clone: function () {
+ var frame = new ccs.ZOrderFrame();
+ frame.setZOrder(this._zorder);
+
+ frame._cloneProperty(this);
+
+ return frame;
+ },
+
+ /**
+ * Set the zOrder
+ * @param {Number} zorder
+ */
+ setZOrder: function (zorder) {
+ this._zorder = zorder;
+ },
+
+ /**
+ * Gets the zOrder
+ * @returns {Number}
+ */
+ getZOrder: function () {
+ return this._zorder;
+ }
+
+});
+
+/**
+ * Create the ZOrder frame
+ *
+ * @deprecated v3.0, please use new ccs.ZOrderFrame() instead.
+ * @returns {ccs.ZOrderFrame}
+ */
+ccs.ZOrderFrame.create = function () {
+ return new ccs.ZOrderFrame();
+};
+
+ccs.BlendFuncFrame = ccs.Frame.extend({
+ ctor: function () {
+ this._super();
+ this._blendFunc = null;
+ },
+
+ onEnter: function (nextFrame, currentFrameIndex) {
+ if (this._node && this._blendFunc)
+ this._node.setBlendFunc(this._blendFunc);
+ },
+
+ clone: function () {
+ var frame = new ccs.BlendFuncFrame();
+ frame.setBlendFunc(this._blendFunc);
+ frame._cloneProperty(this);
+ return frame;
+ },
+
+ setBlendFunc: function (blendFunc) {
+ if (blendFunc && blendFunc.src && blendFunc.dst)
+ this._blendFunc = blendFunc;
+ },
+
+ getBlendFunc: function () {
+ return this._blendFunc;
+ }
+});
+
+ccs.BlendFuncFrame.create = function () {
+ return new ccs.BlendFuncFrame();
+};
diff --git a/extensions/cocostudio/timeline/Timeline.js b/extensions/cocostudio/timeline/Timeline.js
new file mode 100644
index 0000000000..fe2818c5f8
--- /dev/null
+++ b/extensions/cocostudio/timeline/Timeline.js
@@ -0,0 +1,329 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * timeline object
+ * @class
+ * @extend ccs.Class
+ */
+ccs.Timeline = ccs.Class.extend({
+
+ //{ccs.Frame}
+ _frames: null,
+ //{ccs.Frame}
+ _currentKeyFrame: null,
+ //{Number}
+ _currentKeyFrameIndex: null,
+ //{Number}
+ _fromIndex: null,
+ //{Number}
+ _toIndex: null,
+ //{Number}
+ _betweenDuration: null,
+ //{Number}
+ _actionTag: null,
+ //{ccs.ActionTimeline}
+ _ActionTimeline: null,
+ //{cc.Node}
+ _node: null,
+
+ ctor: function () {
+ this._frames = [];
+ this._currentKeyFrame = null;
+ this._currentKeyFrameIndex = 0;
+ this._fromIndex = 0;
+ this._toIndex = 0;
+ this._betweenDuration = 0;
+ this._actionTag = 0;
+ this._ActionTimeline = null;
+ this._node = null;
+ },
+
+ _gotoFrame: function (frameIndex) {
+ if (this._frames.length === 0)
+ return;
+
+ this._binarySearchKeyFrame(frameIndex);
+ this._apply(frameIndex);
+ },
+
+ _stepToFrame: function (frameIndex) {
+ if (this._frames.length === 0)
+ return;
+
+ this._updateCurrentKeyFrame(frameIndex);
+ this._apply(frameIndex);
+ },
+
+ /**
+ * Get the frame list
+ * @returns {ccs.Frame}
+ */
+ getFrames: function () {
+ return this._frames;
+ },
+
+ /**
+ * push frame to frame list
+ * @param {ccs.Frame} frame
+ */
+ addFrame: function (frame) {
+ this._frames.push(frame);
+ frame.setTimeline(this)
+ },
+
+ /**
+ * insert the frame to frame list
+ * @param {ccs.Frame} frame
+ * @param {Number} index
+ */
+ insertFrame: function (frame, index) {
+ this._frames.splice(index, 0, frame);
+ frame.setTimeline(this);
+
+ },
+
+ /**
+ * remove frame
+ * @param {ccs.Frame} frame
+ */
+ removeFrame: function (frame) {
+ cc.arrayRemoveObject(this._frames, frame);
+ frame.setTimeline(null);
+ },
+
+ /**
+ * Set the action tag
+ * @param {Number} tag
+ */
+ setActionTag: function (tag) {
+ this._actionTag = tag;
+ },
+
+ /**
+ * Gets the action tag
+ * return {Number}
+ */
+ getActionTag: function () {
+ return this._actionTag;
+ },
+
+ /**
+ * Set the node
+ * @param {cc.Node} node
+ */
+ setNode: function (node) {
+ for (var i = 0; i < this._frames.length; i++) {
+ var frame = this._frames[i];
+ frame.setNode(node);
+ }
+ },
+
+ /**
+ * Gets the node
+ * return {cc.Node}
+ */
+ getNode: function () {
+ return this._node;
+ },
+
+ /**
+ * Set the action timeline
+ * @param {ccs.ActionTimeline} action
+ */
+ setActionTimeline: function (action) {
+ this._ActionTimeline = action;
+ },
+
+ /**
+ * get the action timeline
+ * return {cc.Action}
+ */
+ getActionTimeline: function () {
+ return this._ActionTimeline;
+ },
+
+ /**
+ * to copy object with deep copy.
+ * returns a clone of action.
+ * @return {ccs.Timeline}
+ */
+ clone: function () {
+ var timeline = new ccs.Timeline();
+ timeline._actionTag = this._actionTag;
+
+ for (var i = 0; i < this._frames.length; i++) {
+ var frame = this._frames[i];
+ var newFrame = frame.clone();
+ timeline.addFrame(newFrame);
+ }
+
+ return timeline;
+
+ },
+
+ _apply: function (frameIndex) {
+ if (this._currentKeyFrame) {
+ var currentPercent = this._betweenDuration <= 0 ? 0 : (frameIndex - this._currentKeyFrameIndex) / this._betweenDuration;
+ this._currentKeyFrame.apply(currentPercent);
+ }
+ },
+
+ _binarySearchKeyFrame: function (frameIndex) {
+ var from = null;
+ var to = null;
+
+ var length = this._frames.length;
+ var needEnterFrame = false;
+
+ do {
+ if (frameIndex < this._frames[0].getFrameIndex()) {
+ if (this._currentKeyFrameIndex >= this._frames[0].getFrameIndex())
+ needEnterFrame = true;
+
+ this._fromIndex = 0;
+ this._toIndex = 0;
+
+ from = to = this._frames[0];
+ this._currentKeyFrameIndex = 0;
+ this._betweenDuration = this._frames[0].getFrameIndex();
+ break;
+ } else if (frameIndex >= this._frames[length - 1].getFrameIndex()) {
+ this._fromIndex = length - 1;
+ this._toIndex = 0;
+
+ from = to = this._frames[length - 1];
+ this._currentKeyFrameIndex = this._frames[length - 1].getFrameIndex();
+ this._betweenDuration = 0;
+ break;
+ }
+
+ var target = -1;
+ var low = 0,
+ high = length - 1,
+ mid = 0;
+ while (low <= high) {
+ mid = Math.ceil(( low + high ) / 2);
+ if (frameIndex >= this._frames[mid].getFrameIndex() && frameIndex < this._frames[mid + 1].getFrameIndex()) {
+ target = mid;
+ break;
+ }
+ if (this._frames[mid].getFrameIndex() > frameIndex)
+ high = mid - 1;
+ else
+ low = mid + 1;
+ }
+
+ this._fromIndex = target;
+
+ if (length > 1)
+ this._toIndex = (target + 1) | 0;
+ else
+ this._toIndex = (target) | 0;
+
+ from = this._frames[this._fromIndex];
+ to = this._frames[this._toIndex];
+
+ from = this._frames[target];
+ to = this._frames[target + 1];
+
+ if (target === 0 && this._currentKeyFrameIndex < from.getFrameIndex())
+ needEnterFrame = true;
+
+ this._currentKeyFrameIndex = from.getFrameIndex();
+ this._betweenDuration = to.getFrameIndex() - from.getFrameIndex();
+ } while (0);
+
+ if (needEnterFrame || this._currentKeyFrame != from) {
+ this._currentKeyFrame = from;
+ this._currentKeyFrame.onEnter(to);
+ }
+
+ },
+
+ _updateCurrentKeyFrame: function (frameIndex) {
+ if (frameIndex > 60)
+ var a = 0;
+ //! If play to current frame's front or back, then find current frame again
+ if (frameIndex < this._currentKeyFrameIndex || frameIndex >= this._currentKeyFrameIndex + this._betweenDuration) {
+ var from = null;
+ var to = null;
+
+ do
+ {
+ var length = this._frames.length;
+
+ if (frameIndex < this._frames[0].getFrameIndex()) {
+ from = to = this._frames[0];
+ this._currentKeyFrameIndex = 0;
+ this._betweenDuration = this._frames[0].getFrameIndex();
+ break;
+ }
+ else if (frameIndex >= this._frames[length - 1].getFrameIndex()) {
+ var lastFrameIndex = this._frames[length - 1].getFrameIndex();
+ if (this._currentKeyFrameIndex >= lastFrameIndex)
+ return;
+ frameIndex = lastFrameIndex;
+ }
+
+ do {
+ this._fromIndex = this._toIndex;
+ from = this._frames[this._fromIndex];
+ this._currentKeyFrameIndex = from.getFrameIndex();
+
+ this._toIndex = this._fromIndex + 1;
+ if (this._toIndex >= length) {
+ this._toIndex = 0;
+ }
+
+ to = this._frames[this._toIndex];
+
+ if (frameIndex === from.getFrameIndex())
+ break;
+ if (frameIndex > from.getFrameIndex() && frameIndex < to.getFrameIndex())
+ break;
+ if (from.isEnterWhenPassed())
+ from.onEnter(to);
+ } while (true);
+
+ this._betweenDuration = to.getFrameIndex() - from.getFrameIndex();
+
+ } while (0);
+
+ this._currentKeyFrame = from;
+ this._currentKeyFrame.onEnter(to);
+ }
+ }
+
+});
+
+/**
+ * Create the Timeline
+ *
+ * @deprecated v3.0, please use new ccs.Timeline() instead.
+ * @returns {ccs.Timeline}
+ */
+ccs.Timeline.create = function () {
+ return new ccs.Timeline();
+};
diff --git a/extensions/cocostudio/trigger/ObjectFactory.js b/extensions/cocostudio/trigger/ObjectFactory.js
new file mode 100644
index 0000000000..c2bc197c82
--- /dev/null
+++ b/extensions/cocostudio/trigger/ObjectFactory.js
@@ -0,0 +1,99 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The singleton object that creating object factory, it creates object with class name, and manager the type mapping.
+ * @class
+ * @name ccs.objectFactory
+ */
+ccs.objectFactory = /** @lends ccs.objectFactory# */{
+ _typeMap: {},
+
+ /**
+ * Creates object with class name. if the the class name without register in type map, it returns null.
+ * @param {String} className
+ * @returns {*}
+ */
+ createObject: function (className) {
+ var o = null;
+ var t = this._typeMap[className];
+ if (t) {
+ if(cc.isFunction(t._fun))
+ o = new t._fun();
+ else
+ o = t._fun;
+ }
+ return o;
+ },
+
+ /**
+ * Registers class type in type map.
+ * @param {ccs.TInfo} t
+ */
+ registerType: function (t) {
+ this._typeMap[t._className] = t;
+ },
+
+ /**
+ * Creates ccui widget object.
+ * @param {String} name widget name
+ * @returns {ccui.Widget|null}
+ */
+ createGUI: function(name){
+ var object = null;
+ if(name === "Panel")
+ name = "Layout";
+ else if(name === "TextArea")
+ name = "Label";
+ else if(name === "TextButton")
+ name = "Button";
+
+ var t = this._typeMap[name];
+ if(t && t._fun)
+ object = t._fun;
+
+ return object;
+ },
+
+ removeAll: function(){
+ this._typeMap = {};
+ }
+};
+
+ccs.TInfo = ccs.Class.extend({
+ _className: "",
+ _fun: null,
+
+ ctor: function (c, f) {
+ if (f) {
+ this._className = c;
+ this._fun = f;
+ } else {
+ this._className = c._className;
+ this._fun = c._fun;
+ }
+ ccs.objectFactory.registerType(this);
+ }
+});
diff --git a/extensions/CocoStudio/GUI/UIWidgets/Compatible/CompatibleClasses.js b/extensions/cocostudio/trigger/TriggerBase.js
similarity index 64%
rename from extensions/CocoStudio/GUI/UIWidgets/Compatible/CompatibleClasses.js
rename to extensions/cocostudio/trigger/TriggerBase.js
index 9b489d9c54..4c773e4476 100644
--- a/extensions/CocoStudio/GUI/UIWidgets/Compatible/CompatibleClasses.js
+++ b/extensions/cocostudio/trigger/TriggerBase.js
@@ -1,5 +1,6 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,26 +23,27 @@
THE SOFTWARE.
****************************************************************************/
-//class type define
-cc.UIPanel =cc.Layout ;
-cc.UITextArea=cc.UILabel;
-cc.UIContainerWidget=cc.Layout;
-cc.UITextButton=cc.UIButton;
-cc.UINodeContainer=cc.UIWidget;
-cc.PanelColorType=cc.LayoutBackGroundColorType;
-
/**
- * Base class for cc.UIZoomButton
- * @class
- * @extends cc.UITextButton
+ * Sends event by trigger manager.
+ * @function
+ * @param {Number} event
*/
-cc.UIZoomButton = cc.UITextButton.extend({
- init: function () {
- if (cc.UITextButton.prototype.init.call(this)) {
- this.setScale9Enabled(true);
- this.setPressedActionEnabled(true);
- return true;
- }
- return false;
+ccs.sendEvent = function (event) {
+ var triggerObjArr = ccs.triggerManager.get(event);
+ if (triggerObjArr == null)
+ return;
+ for (var i = 0; i < triggerObjArr.length; i++) {
+ var triObj = triggerObjArr[i];
+ if (triObj != null && triObj.detect())
+ triObj.done();
}
-});
+};
+
+/**
+ * Registers a trigger class to objectFactory type map.
+ * @param {String} className
+ * @param {function} func
+ */
+ccs.registerTriggerClass = function (className, func) {
+ new ccs.TInfo(className, func);
+};
\ No newline at end of file
diff --git a/extensions/cocostudio/trigger/TriggerMng.js b/extensions/cocostudio/trigger/TriggerMng.js
new file mode 100644
index 0000000000..e0167a1ab6
--- /dev/null
+++ b/extensions/cocostudio/trigger/TriggerMng.js
@@ -0,0 +1,301 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The trigger manager of Cocostudio
+ * @class
+ * @name ccs.triggerManager
+ */
+ccs.triggerManager = /** @lends ccs.triggerManager# */{
+ _eventTriggers: {},
+ _triggerObjs: {},
+ _movementDispatches: [],
+
+ /**
+ * Parses the triggers.
+ * @param {Array} triggers
+ */
+ parse: function (triggers) {
+ for (var i = 0; i < triggers.length; ++i) {
+ var subDict = triggers[i];
+ var triggerObj = new ccs.TriggerObj();
+ triggerObj.serialize(subDict);
+ var events = triggerObj.getEvents();
+ for (var j = 0; j < events.length; j++) {
+ var event = events[j];
+ this.add(event, triggerObj);
+ }
+ this._triggerObjs[triggerObj.getId()] = triggerObj;
+ }
+ },
+
+ /**
+ * Returns the event triggers by event id.
+ * @param {Number} event
+ * @returns {Array}
+ */
+ get: function (event) {
+ return this._eventTriggers[event];
+ },
+
+ /**
+ * Returns the trigger object by id
+ * @param {Number} id
+ * @returns {ccs.TriggerObj}
+ */
+ getTriggerObj: function (id) {
+ return this._triggerObjs[id];
+ },
+
+ /**
+ * Adds event and trigger object to trigger manager.
+ * @param event
+ * @param triggerObj
+ */
+ add: function (event, triggerObj) {
+ var eventTriggers = this._eventTriggers[event];
+ if (!eventTriggers)
+ eventTriggers = [];
+ if (eventTriggers.indexOf(triggerObj) === -1) {
+ eventTriggers.push(triggerObj);
+ this._eventTriggers[event] = eventTriggers;
+ }
+ },
+
+ /**
+ * Removes all event triggers from manager.
+ */
+ removeAll: function () {
+ for (var key in this._eventTriggers) {
+ var triObjArr = this._eventTriggers[key];
+ for (var j = 0; j < triObjArr.length; j++) {
+ var obj = triObjArr[j];
+ obj.removeAll();
+ }
+ }
+ this._eventTriggers = {};
+ },
+
+ /**
+ * Removes event object from trigger manager.
+ * @param {*} event
+ * @param {*} Obj
+ * @returns {Boolean}
+ */
+ remove: function (event, Obj) {
+ if (Obj)
+ return this._removeObj(event, Obj);
+
+ var bRet = false;
+ do {
+ var triObjects = this._eventTriggers[event];
+ if (!triObjects)
+ break;
+ for (var i = 0; i < triObjects.length; i++) {
+ var triObject = triObjects[i];
+ if (triObject)
+ triObject.removeAll();
+ }
+ delete this._eventTriggers[event];
+ bRet = true;
+ } while (0);
+ return bRet;
+ },
+
+ _removeObj: function (event, Obj) {
+ var bRet = false;
+ do
+ {
+ var triObjects = this._eventTriggers[event];
+ if (!triObjects) break;
+ for (var i = 0; i < triObjects.length; i++) {
+ var triObject = triObjects[i];
+ if (triObject && triObject == Obj) {
+ triObject.removeAll();
+ triObjects.splice(i, 1);
+ break;
+ }
+ }
+ bRet = true;
+ } while (0);
+ return bRet;
+ },
+
+ /**
+ * Removes trigger object from manager
+ * @param {Number} id
+ * @returns {boolean}
+ */
+ removeTriggerObj: function (id) {
+ var obj = this.getTriggerObj(id);
+ if (!obj)
+ return false;
+ var events = obj.getEvents();
+ for (var i = 0; i < events.length; i++) {
+ var event = events[i];
+ this.remove(event, obj);
+ }
+ return true;
+ },
+
+ /**
+ * Returns the event triggers whether is empty.
+ * @returns {boolean}
+ */
+ isEmpty: function () {
+ return !this._eventTriggers || this._eventTriggers.length <= 0;
+ },
+
+ /**
+ * Adds an armature movement callback to manager.
+ * @param {ccs.Armature} armature
+ * @param {function} callFunc
+ * @param {Object} target
+ */
+ addArmatureMovementCallBack: function (armature, callFunc, target) {
+ if (armature == null || target == null || callFunc == null)
+ return;
+ var locAmd, hasADD = false;
+ for (var i = 0; i < this._movementDispatches.length; i++) {
+ locAmd = this._movementDispatches[i];
+ if (locAmd && locAmd[0] === armature) {
+ locAmd.addAnimationEventCallBack(callFunc, target);
+ hasADD = true;
+ }
+ }
+ if (!hasADD) {
+ var newAmd = new ccs.ArmatureMovementDispatcher();
+ armature.getAnimation().setMovementEventCallFunc(newAmd.animationEvent, newAmd);
+ newAmd.addAnimationEventCallBack(callFunc, target);
+ this._movementDispatches.push([armature, newAmd]);
+ }
+ },
+
+ /**
+ * Removes armature movement callback from manager.
+ * @param {ccs.Armature} armature
+ * @param {Object} target
+ * @param {function} callFunc
+ */
+ removeArmatureMovementCallBack: function (armature, target, callFunc) {
+ if (armature == null || target == null || callFunc == null)
+ return;
+ var locAmd;
+ for (var i = 0; i < this._movementDispatches.length; i++) {
+ locAmd = this._movementDispatches[i];
+ if (locAmd && locAmd[0] === armature)
+ locAmd.removeAnimationEventCallBack(callFunc, target);
+ }
+ },
+
+ /**
+ * Removes an armature's all movement callbacks.
+ * @param {ccs.Armature} armature
+ */
+ removeArmatureAllMovementCallBack: function (armature) {
+ if (armature == null)
+ return;
+ var locAmd;
+ for (var i = 0; i < this._movementDispatches.length; i++) {
+ locAmd = this._movementDispatches[i];
+ if (locAmd && locAmd[0] === armature) {
+ this._movementDispatches.splice(i, 1);
+ break;
+ }
+ }
+ },
+
+ /**
+ * Removes all armature movement callbacks from ccs.triggerManager.
+ */
+ removeAllArmatureMovementCallBack: function () {
+ this._movementDispatches.length = 0;
+ },
+
+ /**
+ * Returns the version of ccs.triggerManager
+ * @returns {string}
+ */
+ version: function () {
+ return "1.2.0.0";
+ }
+};
+
+/**
+ * The armature movement dispatcher for trigger manager.
+ * @class
+ * @extends ccs.Class
+ */
+ccs.ArmatureMovementDispatcher = ccs.Class.extend(/** @lends ccs.ArmatureMovementDispatcher# */{
+ _mapEventAnimation: null,
+
+ /**
+ * Constructor of ArmatureMovementDispatcher.
+ */
+ ctor: function () {
+ this._mapEventAnimation = [];
+ },
+
+ /**
+ * Calls armature movement events.
+ * @param {ccs.Armature} armature
+ * @param {Number} movementType
+ * @param {String} movementID
+ */
+ animationEvent: function (armature, movementType, movementID) {
+ var locEventAni, locTarget, locFunc;
+ for (var i = 0; i < this._mapEventAnimation.length; i++) {
+ locEventAni = this._mapEventAnimation[i];
+ locTarget = locEventAni[0];
+ locFunc = locEventAni[1];
+ if (locFunc)
+ locFunc.call(locTarget, armature, movementType, movementID);
+ }
+ },
+
+ /**
+ * Adds animation event callback to event animation list
+ * @param {function} callFunc
+ * @param {Object|null} [target]
+ */
+ addAnimationEventCallBack: function (callFunc, target) {
+ this._mapEventAnimation.push([target, callFunc]);
+ },
+
+ /**
+ * Removes animation event callback from trigger manager.
+ * @param {function} callFunc
+ * @param {Object|null} [target]
+ */
+ removeAnimationEventCallBack: function (callFunc, target) {
+ var locEventAni;
+ for (var i = 0; i < this._mapEventAnimation.length; i++) {
+ locEventAni = this._mapEventAnimation[i];
+ if (locEventAni[0] === target) {
+ this._mapEventAnimation.splice(i, 1);
+ }
+ }
+ }
+});
\ No newline at end of file
diff --git a/extensions/cocostudio/trigger/TriggerObj.js b/extensions/cocostudio/trigger/TriggerObj.js
new file mode 100644
index 0000000000..6a8e3c1226
--- /dev/null
+++ b/extensions/cocostudio/trigger/TriggerObj.js
@@ -0,0 +1,263 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The base class of trigger condition.
+ * @class
+ * @extends ccs.Class
+ */
+ccs.BaseTriggerCondition = ccs.Class.extend(/** @lends ccs.BaseTriggerCondition# */{
+ /**
+ * Construction of ccs.BaseTriggerCondition
+ */
+ ctor:function(){
+ },
+
+ /**
+ * initializes a BaseTriggerCondition class.
+ * @returns {boolean}
+ */
+ init: function () {
+ return true;
+ },
+
+ /**
+ * Detects trigger condition
+ * @returns {boolean}
+ */
+ detect: function () {
+ return true;
+ },
+
+ /**
+ * Serialize a BaseTriggerCondition object.
+ * @param jsonVal
+ */
+ serialize: function (jsonVal) {
+ },
+
+ /**
+ * Removes all condition
+ */
+ removeAll: function () {
+ }
+});
+
+/**
+ * The base class of trigger action
+ * @class
+ * @extends ccs.Class
+ */
+ccs.BaseTriggerAction = ccs.Class.extend(/** @lends ccs.BaseTriggerAction# */{
+ /**
+ * Construction of ccs.BaseTriggerAction
+ */
+ ctor:function(){
+ },
+
+ /**
+ * Initializes a BaseTriggerAction object.
+ * @returns {boolean}
+ */
+ init: function () {
+ return true;
+ },
+
+ /**
+ * Sets the action to done.
+ */
+ done: function () {
+ },
+
+ /**
+ * Serializes a ccs.BaseTriggerAction object.
+ * @param jsonVal
+ */
+ serialize: function (jsonVal) {
+ },
+
+ /**
+ * Removes all actions.
+ */
+ removeAll: function () {
+ }
+});
+
+/**
+ * The trigger object of Cocostudio.
+ * @class
+ * @extends ccs.Class
+ */
+ccs.TriggerObj = ccs.Class.extend(/** @lends ccs.TriggerObj# */{
+ _cons: null,
+ _acts: null,
+ _id: 0,
+ _enable: true,
+ _vInt: null,
+
+ ctor: function () {
+ this._id = 0;
+ this._enable = true;
+
+ ccs.TriggerObj.prototype.init.call(this);
+ },
+
+ /**
+ * Initializes a ccs.TriggerObj
+ * @returns {boolean}
+ */
+ init: function () {
+ this._cons = [];
+ this._acts = [];
+ this._vInt = [];
+ return true;
+ },
+
+ /**
+ * Detects trigger's conditions.
+ * @returns {boolean}
+ */
+ detect: function () {
+ if (!this._enable || this._cons.length === 0) {
+ return true;
+ }
+ var ret = true;
+ var obj = null;
+ for (var i = 0; i < this._cons.length; i++) {
+ obj = this._cons[i];
+ if (obj && obj.detect)
+ ret = ret && obj.detect();
+ }
+ return ret;
+ },
+
+ /**
+ * Sets trigger's actions to done.
+ */
+ done: function () {
+ if (!this._enable || this._acts.length === 0)
+ return;
+ var obj;
+ for (var i = 0; i < this._acts.length; i++) {
+ obj = this._acts[i];
+ if (obj && obj.done)
+ obj.done();
+ }
+ },
+
+ /**
+ * Removes all condition and actions from ccs.TriggerObj.
+ */
+ removeAll: function () {
+ var obj = null;
+ for (var i = 0; i < this._cons.length; i++) {
+ obj = this._cons[i];
+ if (obj)
+ obj.removeAll();
+ }
+ this._cons = [];
+ for (var i = 0; i < this._acts.length; i++) {
+ obj = this._acts[i];
+ if (obj)
+ obj.removeAll();
+ }
+ this._acts = [];
+ },
+
+ /**
+ * Serializes ccs.TriggerObj
+ * @param jsonVal
+ */
+ serialize: function (jsonVal) {
+ this._id = jsonVal["id"] || 0;
+ var conditions = jsonVal["conditions"] || [];
+ for (var i = 0; i < conditions.length; i++) {
+ var subDict = conditions[i];
+ var classname = subDict["classname"];
+ var con = ccs.objectFactory.createObject(classname);
+ if (!con) {
+ cc.log("class named classname(" + classname + ") can not implement!");
+ continue;
+ }
+
+ con.serialize(subDict);
+ con.init();
+ this._cons.push(con);
+ }
+
+ var actions = jsonVal["actions"] || [];
+ for (var i = 0; i < actions.length; i++) {
+ var subDict = actions[i];
+ var classname = subDict["classname"];
+ var act = ccs.objectFactory.createObject(classname);
+ if (!act) {
+ cc.log("class named classname(" + classname + ") can not implement!");
+ continue;
+ }
+
+ act.serialize(subDict);
+ act.init();
+ this._acts.push(act);
+ }
+
+ var events = jsonVal["events"] || [];
+ for (var i = 0; i < events.length; i++) {
+ var subDict = events[i];
+ var event = subDict["id"];
+ if (event < 0) {
+ continue;
+ }
+ this._vInt.push(event);
+ }
+ },
+
+ /**
+ * Returns the id of ccs.TriggerObj.
+ * @returns {number}
+ */
+ getId: function () {
+ return this._id;
+ },
+
+ /**
+ * Sets enable value.
+ * @param {Boolean} enable
+ */
+ setEnable: function (enable) {
+ this._enable = enable;
+ },
+
+ /**
+ * Returns the events of ccs.TriggerObj.
+ * @returns {null|Array}
+ */
+ getEvents: function () {
+ return this._vInt;
+ }
+});
+
+ccs.TriggerObj.create = function () {
+ return new ccs.TriggerObj();
+};
\ No newline at end of file
diff --git a/extensions/editbox/CCEditBox.js b/extensions/editbox/CCEditBox.js
new file mode 100644
index 0000000000..3a535438f2
--- /dev/null
+++ b/extensions/editbox/CCEditBox.js
@@ -0,0 +1,1420 @@
+/****************************************************************************
+ Copyright (c) 2013-2016 Chukong Technologies Inc.
+ Copyright (c) 2012 James Chen
+ Copyright (c) 2011-2012 cocos2d-x.org
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.KEYBOARD_RETURNTYPE_DEFAULT = 0;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.KEYBOARD_RETURNTYPE_DONE = 1;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.KEYBOARD_RETURNTYPE_SEND = 2;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.KEYBOARD_RETURNTYPE_SEARCH = 3;
+
+/**
+ * @constant
+ * @type Number
+ */
+cc.KEYBOARD_RETURNTYPE_GO = 4;
+
+/**
+ * The EditBoxInputMode defines the type of text that the user is allowed * to enter.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_MODE_ANY = 0;
+
+/**
+ * The user is allowed to enter an e-mail address.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_MODE_EMAILADDR = 1;
+
+/**
+ * The user is allowed to enter an integer value.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_MODE_NUMERIC = 2;
+
+/**
+ * The user is allowed to enter a phone number.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_MODE_PHONENUMBER = 3;
+
+/**
+ * The user is allowed to enter a URL.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_MODE_URL = 4;
+
+/**
+ * The user is allowed to enter a real number value.
+ * This extends kEditBoxInputModeNumeric by allowing a decimal point.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_MODE_DECIMAL = 5;
+
+/**
+ * The user is allowed to enter any text, except for line breaks.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_MODE_SINGLELINE = 6;
+
+/**
+ * Indicates that the text entered is confidential data that should be
+ * obscured whenever possible. This implies EDIT_BOX_INPUT_FLAG_SENSITIVE.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_FLAG_PASSWORD = 0;
+
+/**
+ * Indicates that the text entered is sensitive data that the
+ * implementation must never store into a dictionary or table for use
+ * in predictive, auto-completing, or other accelerated input schemes.
+ * A credit card number is an example of sensitive data.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_FLAG_SENSITIVE = 1;
+
+/**
+ * This flag is a hint to the implementation that during text editing,
+ * the initial letter of each word should be capitalized.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD = 2;
+
+/**
+ * This flag is a hint to the implementation that during text editing,
+ * the initial letter of each sentence should be capitalized.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE = 3;
+
+/**
+ * Capitalize all characters automatically.
+ * @constant
+ * @type Number
+ */
+cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS = 4;
+
+/**
+ * @class
+ * @extends cc.Class
+ */
+cc.EditBoxDelegate = cc.Class.extend({
+ /**
+ * This method is called when an edit box gains focus after keyboard is shown.
+ * @param {cc.EditBox} sender
+ */
+ editBoxEditingDidBegin: function (sender) {
+ },
+
+ /**
+ * This method is called when an edit box loses focus after keyboard is hidden.
+ * @param {cc.EditBox} sender
+ */
+ editBoxEditingDidEnd: function (sender) {
+ },
+
+ /**
+ * This method is called when the edit box text was changed.
+ * @param {cc.EditBox} sender
+ * @param {String} text
+ */
+ editBoxTextChanged: function (sender, text) {
+ },
+
+ /**
+ * This method is called when the return button was pressed.
+ * @param {cc.EditBox} sender
+ */
+ editBoxReturn: function (sender) {
+ }
+});
+
+
+/**
+ * cc.EditBox is a brief Class for edit box.
+ * You can use this widget to gather small amounts of text from the user.
+ *
+ * @class
+ * @extends cc.Node
+ *
+ * @property {String} string - Content string of edit box
+ * @property {String} maxLength - Max length of the content string
+ * @property {String} font - <@writeonly> Config font of edit box
+ * @property {String} fontName - <@writeonly> Config font name of edit box
+ * @property {Number} fontSize - <@writeonly> Config font size of edit box
+ * @property {cc.Color} fontColor - <@writeonly> Config font color of edit box
+ * @property {String} placeHolder - Place holder of edit box
+ * @property {String} placeHolderFont - <@writeonly> Config font of place holder
+ * @property {String} placeHolderFontName - <@writeonly> Config font name of place holder
+ * @property {Number} placeHolderFontSize - <@writeonly> Config font size of place holder
+ * @property {cc.Color} placeHolderFontColor - <@writeonly> Config font color of place holder
+ * @property {Number} inputFlag - <@writeonly> Input flag of edit box, one of the EditBoxInputFlag constants. e.g.cc.EDITBOX_INPUT_FLAG_PASSWORD
+ * @property {Object} delegate - <@writeonly> Delegate of edit box
+ * @property {Number} inputMode - <@writeonly> Input mode of the edit box. Value should be one of the EditBoxInputMode constants.
+ * @property {Number} returnType - <@writeonly> Return type of edit box, value should be one of the KeyboardReturnType constants.
+ *
+ */
+cc.EditBox = cc.Node.extend({
+ _backgroundSprite: null,
+ _delegate: null,
+ _editBoxInputMode: cc.EDITBOX_INPUT_MODE_ANY,
+ _editBoxInputFlag: cc.EDITBOX_INPUT_FLAG_SENSITIVE,
+ _keyboardReturnType: cc.KEYBOARD_RETURNTYPE_DEFAULT,
+ _maxLength: 50,
+ _text: '',
+ _textColor: null,
+ _placeholderText: '',
+ _placeholderFontName: '',
+ _placeholderFontSize: 14,
+ _placeholderColor: null,
+ _className: 'EditBox',
+ _touchListener: null,
+ _touchEnabled: true,
+
+ /**
+ * constructor of cc.EditBox
+ * @param {cc.Size} size
+ * @param {cc.Scale9Sprite} normal9SpriteBg
+ * @param {cc.Scale9Sprite} press9SpriteBg
+ * @param {cc.Scale9Sprite} disabled9SpriteBg
+ */
+ ctor: function (size, normal9SpriteBg) {
+ cc.Node.prototype.ctor.call(this);
+
+ this._anchorPoint = cc.p(0.5, 0.5);
+ this._textColor = cc.color.WHITE;
+ this._placeholderColor = cc.color.GRAY;
+
+ this._renderCmd._createLabels();
+ this.createDomElementIfNeeded();
+ this.initWithSizeAndBackgroundSprite(size, normal9SpriteBg);
+
+ this._touchListener = cc.EventListener.create({
+ event: cc.EventListener.TOUCH_ONE_BY_ONE,
+ swallowTouches: true,
+ onTouchBegan: this._onTouchBegan.bind(this),
+ onTouchEnded: this._onTouchEnded.bind(this)
+ });
+ cc.eventManager.addListener(this._touchListener, this);
+
+ this.setInputFlag(this._editBoxInputFlag);
+ },
+
+ setTouchEnabled: function (enable) {
+ if (this._touchEnabled === enable) {
+ return;
+ }
+ this._touchEnabled = enable;
+ if (this._touchEnabled) {
+ cc.eventManager.addListener(this._touchListener, this);
+ } else {
+ cc.eventManager.removeListener(this._touchListener);
+ }
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+ return new cc.EditBox.CanvasRenderCmd(this);
+ } else {
+ return new cc.EditBox.WebGLRenderCmd(this);
+ }
+ },
+
+ setContentSize: function (width, height) {
+ if (width.width !== undefined && width.height !== undefined) {
+ height = width.height;
+ width = width.width;
+ }
+ cc.Node.prototype.setContentSize.call(this, width, height);
+ this._updateEditBoxSize(width, height);
+ },
+
+ setVisible: function (visible) {
+ cc.Node.prototype.setVisible.call(this, visible);
+ this._renderCmd.updateVisibility();
+ },
+
+ createDomElementIfNeeded: function () {
+ if (!this._renderCmd._edTxt) {
+ this._renderCmd._createDomTextArea();
+ }
+ },
+
+ setTabIndex: function (index) {
+ if (this._renderCmd._edTxt) {
+ this._renderCmd._edTxt.tabIndex = index;
+ }
+ },
+
+ getTabIndex: function () {
+ if (this._renderCmd._edTxt) {
+ return this._renderCmd._edTxt.tabIndex;
+ }
+ cc.warn('The dom control is not created!');
+ return -1;
+ },
+
+ setFocus: function () {
+ if (this._renderCmd._edTxt) {
+ this._renderCmd._edTxt.focus();
+ }
+ },
+
+ isFocused: function () {
+ if (this._renderCmd._edTxt) {
+ return document.activeElement === this._renderCmd._edTxt;
+ }
+ cc.warn('The dom control is not created!');
+ return false;
+ },
+
+ stayOnTop: function (flag) {
+ if (this._alwaysOnTop === flag) return;
+
+ this._alwaysOnTop = flag;
+ this._renderCmd.stayOnTop(this._alwaysOnTop);
+ },
+
+ cleanup: function () {
+ this._super();
+
+ this._renderCmd._removeDomFromGameContainer();
+ },
+
+ _isAncestorsVisible: function (node) {
+ if (null == node)
+ return true;
+
+ var parent = node.getParent();
+
+ if (parent && !parent.isVisible())
+ return false;
+ return this._isAncestorsVisible(parent);
+ },
+
+ _onTouchBegan: function (touch) {
+ if (!this.isVisible() || !this._isAncestorsVisible(this)) {
+ return;
+ }
+ var touchPoint = touch.getLocation();
+ var bb = cc.rect(0, 0, this._contentSize.width, this._contentSize.height);
+ var hitted = cc.rectContainsPoint(bb, this.convertToNodeSpace(touchPoint));
+ if (hitted) {
+ return true;
+ }
+ else {
+ this._renderCmd._endEditing();
+ return false;
+ }
+ },
+
+ _onTouchEnded: function () {
+ if (!this.isVisible() || !this._isAncestorsVisible(this)) {
+ return;
+ }
+ this._renderCmd._beginEditing();
+ },
+
+ _updateBackgroundSpriteSize: function (width, height) {
+ if (this._backgroundSprite) {
+ this._backgroundSprite.setContentSize(width, height);
+ }
+ },
+
+ _updateEditBoxSize: function (size, height) {
+ var newWidth = (typeof size.width === 'number') ? size.width : size;
+ var newHeight = (typeof size.height === 'number') ? size.height : height;
+
+ this._updateBackgroundSpriteSize(newWidth, newHeight);
+ this._renderCmd.updateSize(newWidth, newHeight);
+ },
+
+ setLineHeight: function (lineHeight) {
+ this._renderCmd.setLineHeight(lineHeight);
+ },
+
+ /**
+ * Sets the font.
+ * @param {String} fontName The font name.
+ * @param {Number} fontSize The font size.
+ */
+ setFont: function (fontName, fontSize) {
+ this._renderCmd.setFont(fontName, fontSize);
+ },
+
+ _setFont: function (fontStyle) {
+ this._renderCmd._setFont(fontStyle);
+ },
+
+ getBackgroundSprite: function () {
+ return this._backgroundSprite;
+ },
+
+ /**
+ * Sets fontName
+ * @param {String} fontName
+ */
+ setFontName: function (fontName) {
+ this._renderCmd.setFontName(fontName);
+ },
+
+ /**
+ * Sets fontSize
+ * @param {Number} fontSize
+ */
+ setFontSize: function (fontSize) {
+ this._renderCmd.setFontSize(fontSize);
+ },
+
+ /**
+ * Sets the text entered in the edit box.
+ * @param {string} text The given text.
+ */
+ setString: function (text) {
+ if (text.length >= this._maxLength) {
+ text = text.slice(0, this._maxLength);
+ }
+ this._text = text;
+ this._renderCmd.setString(text);
+ },
+
+ /**
+ * Sets the font color of the widget's text.
+ * @param {cc.Color} color
+ */
+ setFontColor: function (color) {
+ this._textColor = color;
+ this._renderCmd.setFontColor(color);
+ },
+
+ /**
+ * Sets the maximum input length of the edit box.
+ * Setting this value enables multiline input mode by default.
+ * @param {Number} maxLength The maximum length.
+ */
+ setMaxLength: function (maxLength) {
+ if (!isNaN(maxLength)) {
+ if (maxLength < 0) {
+ //we can't set Number.MAX_VALUE to input's maxLength property
+ //so we use a magic number here, it should works at most use cases.
+ maxLength = 65535;
+ }
+ this._maxLength = maxLength;
+ this._renderCmd.setMaxLength(maxLength);
+ }
+ },
+
+ /**
+ * Gets the maximum input length of the edit box.
+ * @return {Number} Maximum input length.
+ */
+ getMaxLength: function () {
+ return this._maxLength;
+ },
+
+ /**
+ * Sets a text in the edit box that acts as a placeholder when an edit box is empty.
+ * @param {string} text The given text.
+ */
+ setPlaceHolder: function (text) {
+ if (text !== null) {
+ this._renderCmd.setPlaceHolder(text);
+ this._placeholderText = text;
+ }
+ },
+
+ /**
+ * Sets the placeholder's font.
+ * @param {String} fontName
+ * @param {Number} fontSize
+ */
+ setPlaceholderFont: function (fontName, fontSize) {
+ this._placeholderFontName = fontName;
+ this._placeholderFontSize = fontSize;
+ this._renderCmd._updateDOMPlaceholderFontStyle();
+ },
+
+ _setPlaceholderFont: function (fontStyle) {
+ var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
+ if (res) {
+ this._placeholderFontName = res[2];
+ this._placeholderFontSize = parseInt(res[1]);
+ this._renderCmd._updateDOMPlaceholderFontStyle();
+ }
+ },
+
+ /**
+ * Sets the placeholder's fontName.
+ * @param {String} fontName
+ */
+ setPlaceholderFontName: function (fontName) {
+ this._placeholderFontName = fontName;
+ this._renderCmd._updateDOMPlaceholderFontStyle();
+ },
+
+ /**
+ * Sets the placeholder's fontSize.
+ * @param {Number} fontSize
+ */
+ setPlaceholderFontSize: function (fontSize) {
+ this._placeholderFontSize = fontSize;
+ this._renderCmd._updateDOMPlaceholderFontStyle();
+ },
+
+ /**
+ * Sets the font color of the placeholder text when the edit box is empty.
+ * @param {cc.Color} color
+ */
+ setPlaceholderFontColor: function (color) {
+ this._placeholderColor = color;
+ this._renderCmd.setPlaceholderFontColor(color);
+ },
+
+ /**
+ * Sets the input flags that are to be applied to the edit box.
+ * @param {Number} inputFlag One of the EditBoxInputFlag constants.
+ * e.g.cc.EDITBOX_INPUT_FLAG_PASSWORD
+ */
+ setInputFlag: function (inputFlag) {
+ this._editBoxInputFlag = inputFlag;
+ this._renderCmd.setInputFlag(inputFlag);
+ },
+
+ /**
+ * Gets the input string of the edit box.
+ * @return {string}
+ */
+ getString: function () {
+ return this._text;
+ },
+
+ /**
+ * Init edit box with specified size.
+ * @param {cc.Size} size
+ * @param {cc.Color | cc.Scale9Sprite} normal9SpriteBg
+ */
+ initWithSizeAndBackgroundSprite: function (size, normal9SpriteBg) {
+ if (this._backgroundSprite) {
+ this._backgroundSprite.removeFromParent();
+ }
+ this._backgroundSprite = normal9SpriteBg;
+ this.setContentSize(size);
+
+ if (this._backgroundSprite && !this._backgroundSprite.parent) {
+ this._backgroundSprite.setAnchorPoint(cc.p(0, 0));
+ this.addChild(this._backgroundSprite);
+
+ this._updateBackgroundSpriteSize(size.width, size.height);
+ }
+
+ this.x = 0;
+ this.y = 0;
+ return true;
+ },
+
+ /**
+ * Sets the delegate for edit box.
+ * @param {cc.EditBoxDelegate} delegate
+ */
+ setDelegate: function (delegate) {
+ this._delegate = delegate;
+ },
+
+ /**
+ * Gets the text in the edit box that acts as a placeholder when an
+ * edit box is empty.
+ * @return {String}
+ */
+ getPlaceHolder: function () {
+ return this._placeholderText;
+ },
+
+ /**
+ * Sets the input mode of the edit box.
+ * @param {Number} inputMode One of the EditBoxInputMode constants.
+ */
+ setInputMode: function (inputMode) {
+ if (this._editBoxInputMode === inputMode) return;
+
+ var oldText = this.getString();
+ this._editBoxInputMode = inputMode;
+
+ this._renderCmd.setInputMode(inputMode);
+ this._renderCmd.transform();
+
+ this.setString(oldText);
+ this._renderCmd._updateLabelPosition(this.getContentSize());
+ },
+
+ /**
+ * Sets the return type that are to be applied to the edit box.
+ * @param {Number} returnType One of the CCKeyboardReturnType constants.
+ */
+ setReturnType: function (returnType) {
+ this._keyboardReturnType = returnType;
+ this._renderCmd._updateDomInputType();
+ },
+
+ /**
+ * @warning HTML5 Only
+ * @param {cc.Size} size
+ * @param {cc.color} bgColor
+ */
+ initWithBackgroundColor: function (size, bgColor) {
+ this._edWidth = size.width;
+ this.dom.style.width = this._edWidth.toString() + 'px';
+ this._edHeight = size.height;
+ this.dom.style.height = this._edHeight.toString() + 'px';
+ this.dom.style.backgroundColor = cc.colorToHex(bgColor);
+ }
+});
+
+var _p = cc.EditBox.prototype;
+
+// Extended properties
+/** @expose */
+_p.font;
+cc.defineGetterSetter(_p, 'font', null, _p._setFont);
+/** @expose */
+_p.fontName;
+cc.defineGetterSetter(_p, 'fontName', null, _p.setFontName);
+/** @expose */
+_p.fontSize;
+cc.defineGetterSetter(_p, 'fontSize', null, _p.setFontSize);
+/** @expose */
+_p.fontColor;
+cc.defineGetterSetter(_p, 'fontColor', null, _p.setFontColor);
+/** @expose */
+_p.string;
+cc.defineGetterSetter(_p, 'string', _p.getString, _p.setString);
+/** @expose */
+_p.maxLength;
+cc.defineGetterSetter(_p, 'maxLength', _p.getMaxLength, _p.setMaxLength);
+/** @expose */
+_p.placeHolder;
+cc.defineGetterSetter(_p, 'placeholder', _p.getPlaceHolder, _p.setPlaceHolder);
+/** @expose */
+_p.placeHolderFont;
+cc.defineGetterSetter(_p, 'placeholderFont', null, _p._setPlaceholderFont);
+/** @expose */
+_p.placeHolderFontName;
+cc.defineGetterSetter(_p, 'placeholderFontName', null, _p.setPlaceholderFontName);
+/** @expose */
+_p.placeHolderFontSize;
+cc.defineGetterSetter(_p, 'placeholderFontSize', null, _p.setPlaceholderFontSize);
+/** @expose */
+_p.placeHolderFontColor;
+cc.defineGetterSetter(_p, 'placeholderFontColor', null, _p.setPlaceholderFontColor);
+/** @expose */
+_p.inputFlag;
+cc.defineGetterSetter(_p, 'inputFlag', null, _p.setInputFlag);
+/** @expose */
+_p.delegate;
+cc.defineGetterSetter(_p, 'delegate', null, _p.setDelegate);
+/** @expose */
+_p.inputMode;
+cc.defineGetterSetter(_p, 'inputMode', null, _p.setInputMode);
+/** @expose */
+_p.returnType;
+cc.defineGetterSetter(_p, 'returnType', null, _p.setReturnType);
+
+_p = null;
+
+/**
+ * create a edit box with size and background-color or
+ * @deprecated since v3.0, please use new cc.EditBox(size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg) instead
+ * @param {cc.Size} size
+ * @param {cc.Scale9Sprite } normal9SpriteBg
+ * @param {cc.Scale9Sprite } [press9SpriteBg]
+ * @param {cc.Scale9Sprite } [disabled9SpriteBg]
+ * @return {cc.EditBox}
+ */
+cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg) {
+ return new cc.EditBox(size, normal9SpriteBg, press9SpriteBg, disabled9SpriteBg);
+};
+
+
+(function (editbox) {
+ editbox._polyfill = {
+ zoomInvalid: false
+ };
+
+ if (cc.sys.OS_ANDROID === cc.sys.os
+ && (cc.sys.browserType === cc.sys.BROWSER_TYPE_SOUGOU
+ || cc.sys.browserType === cc.sys.BROWSER_TYPE_360)) {
+ editbox._polyfill.zoomInvalid = true;
+ }
+})(cc.EditBox);
+
+(function (polyfill) {
+ // https://segmentfault.com/q/1010000002914610
+ var SCROLLY = 40;
+ var TIMER_NAME = 400;
+ var LEFT_PADDING = 2;
+
+ function adjustEditBoxPosition (editBox) {
+ var worldPos = editBox.convertToWorldSpace(cc.p(0,0));
+ var windowHeight = cc.visibleRect.height;
+ var windowWidth = cc.visibleRect.width;
+ var factor = 0.5;
+ if(windowWidth > windowHeight) {
+ factor = 0.7;
+ }
+ setTimeout(function() {
+ if(window.scrollY < SCROLLY && worldPos.y < windowHeight * factor) {
+ var scrollOffset = windowHeight * factor - worldPos.y - window.scrollY;
+ if (scrollOffset < 35) scrollOffset = 35;
+ if (scrollOffset > 320) scrollOffset = 320;
+ window.scrollTo(scrollOffset, scrollOffset);
+ }
+ }, TIMER_NAME);
+ }
+
+ var capitalize = function(string) {
+ return string.replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
+ };
+
+ function capitalizeFirstLetter(string) {
+ return string.charAt(0).toUpperCase() + string.slice(1);
+ }
+
+ var EditBoxImpl = function () {
+ };
+ var proto = EditBoxImpl.prototype = Object.create(Object.prototype);
+
+ proto.updateMatrix = function () {
+ if (!this._edTxt) return;
+
+ var node = this._node, scaleX = cc.view._scaleX, scaleY = cc.view._scaleY;
+ var dpr = cc.view._devicePixelRatio;
+ var t = this._worldTransform;
+
+ scaleX /= dpr;
+ scaleY /= dpr;
+
+ var container = cc.game.container;
+ var a = t.a * scaleX, b = t.b, c = t.c, d = t.d * scaleY;
+
+ var offsetX = container && container.style.paddingLeft && parseInt(container.style.paddingLeft);
+ var offsetY = container && container.style.paddingBottom && parseInt(container.style.paddingBottom);
+ var tx = t.tx * scaleX + offsetX, ty = t.ty * scaleY + offsetY;
+
+ if (polyfill.zoomInvalid) {
+ this.updateSize(node._contentSize.width * a, node._contentSize.height * d);
+ a = 1;
+ d = 1;
+ }
+
+ var matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")";
+ this._edTxt.style['transform'] = matrix;
+ this._edTxt.style['-webkit-transform'] = matrix;
+ this._edTxt.style['transform-origin'] = '0px 100% 0px';
+ this._edTxt.style['-webkit-transform-origin'] = '0px 100% 0px';
+ };
+
+ proto.updateVisibility = function () {
+ if (!this._edTxt) return;
+
+ if (this._node.visible) {
+ this._edTxt.style.visibility = 'visible';
+ } else {
+ this._edTxt.style.visibility = 'hidden';
+ }
+ };
+
+ proto.stayOnTop = function (flag) {
+ if (flag) {
+ this._removeLabels();
+ this._edTxt.style.display = '';
+ } else {
+ this._createLabels();
+ this._edTxt.style.display = 'none';
+ this._showLabels();
+ }
+ };
+
+ // Called before editbox focus to register cc.view status
+ proto._beginEditingOnMobile = function (editBox) {
+ this.__orientationChanged = function () {
+ adjustEditBoxPosition(editBox);
+ };
+
+ window.addEventListener('orientationchange', this.__orientationChanged);
+
+ if (cc.view.isAutoFullScreenEnabled()) {
+ this.__fullscreen = true;
+ cc.view.enableAutoFullScreen(false);
+ cc.screen.exitFullScreen();
+ } else {
+ this.__fullscreen = false;
+ }
+ this.__autoResize = cc.view.__resizeWithBrowserSize;
+ cc.view.resizeWithBrowserSize(false);
+ };
+ // Called after keyboard disappeared to readapte the game view
+ proto._endEditingOnMobile = function () {
+ if (this.__rotateScreen) {
+ var containerStyle = cc.game.container.style;
+ containerStyle['-webkit-transform'] = 'rotate(90deg)';
+ containerStyle.transform = 'rotate(90deg)';
+
+ var view = cc.view;
+ var width = view._originalDesignResolutionSize.width;
+ var height = view._originalDesignResolutionSize.height;
+ if (width > 0) {
+ view.setDesignResolutionSize(width, height, view._resolutionPolicy);
+ }
+ this.__rotateScreen = false;
+ }
+
+ window.removeEventListener('orientationchange', this.__orientationChanged);
+
+ window.scrollTo(0, 0);
+ if (this.__fullscreen) {
+ cc.view.enableAutoFullScreen(true);
+ }
+ if (this.__autoResize) {
+ cc.view.resizeWithBrowserSize(true);
+ }
+ };
+ // Called after editbox focus to readapte the game view
+ proto._onFocusOnMobile = function (editBox) {
+ if (cc.view._isRotated) {
+ var containerStyle = cc.game.container.style;
+ containerStyle['-webkit-transform'] = 'rotate(0deg)';
+ containerStyle.transform = 'rotate(0deg)';
+ containerStyle.margin = '0px';
+ // cc.view._isRotated = false;
+ // var policy = cc.view.getResolutionPolicy();
+ // policy.apply(cc.view, cc.view.getDesignResolutionSize());
+ // cc.view._isRotated = true;
+ //use window scrollTo to adjust the input area
+ window.scrollTo(35, 35);
+ this.__rotateScreen = true;
+ } else {
+ this.__rotateScreen = false;
+ }
+ adjustEditBoxPosition(editBox);
+ };
+
+
+ proto._createDomInput = function () {
+ this._removeDomFromGameContainer();
+ var thisPointer = this;
+ var tmpEdTxt = this._edTxt = document.createElement('input');
+ tmpEdTxt.type = 'text';
+ tmpEdTxt.style.fontFamily = this._edFontName;
+ tmpEdTxt.style.fontSize = this._edFontSize + 'px';
+ tmpEdTxt.style.color = '#000000';
+ tmpEdTxt.style.border = 0;
+ tmpEdTxt.style.background = 'transparent';
+ tmpEdTxt.style.width = '100%';
+ tmpEdTxt.style.height = '100%';
+ tmpEdTxt.style.active = 0;
+ tmpEdTxt.style.outline = 'medium';
+ tmpEdTxt.style.padding = '0';
+ tmpEdTxt.style.textTransform = 'uppercase';
+ tmpEdTxt.style.display = 'none';
+
+ tmpEdTxt.style.position = "absolute";
+ tmpEdTxt.style.bottom = "0px";
+ tmpEdTxt.style.left = LEFT_PADDING + "px";
+ tmpEdTxt.style.className = "cocosEditBox";
+ this.setMaxLength(thisPointer._editBox._maxLength);
+
+ tmpEdTxt.addEventListener('input', function () {
+ var editBox = thisPointer._editBox;
+
+
+ if (this.value.length > this.maxLength) {
+ this.value = this.value.slice(0, this.maxLength);
+ }
+
+ if (editBox._delegate && editBox._delegate.editBoxTextChanged) {
+ if (editBox._text !== this.value) {
+ editBox._text = this.value;
+ thisPointer._updateDomTextCases();
+ editBox._delegate.editBoxTextChanged(editBox, editBox._text);
+ }
+ }
+ });
+ tmpEdTxt.addEventListener('keypress', function (e) {
+ var editBox = thisPointer._editBox;
+
+ if (e.keyCode === cc.KEY.enter) {
+ e.stopPropagation();
+ e.preventDefault();
+ if (this.value === '') {
+ this.style.fontSize = editBox._placeholderFontSize + 'px';
+ this.style.color = cc.colorToHex(editBox._placeholderColor);
+ }
+
+ editBox._text = this.value;
+ thisPointer._updateDomTextCases();
+
+ thisPointer._endEditing();
+ if (editBox._delegate && editBox._delegate.editBoxReturn) {
+ editBox._delegate.editBoxReturn(editBox);
+ }
+ cc._canvas.focus();
+ }
+ });
+
+ tmpEdTxt.addEventListener('focus', function () {
+ var editBox = thisPointer._editBox;
+ this.style.fontSize = thisPointer._edFontSize + 'px';
+ this.style.color = cc.colorToHex(editBox._textColor);
+ thisPointer._hiddenLabels();
+
+ if (cc.sys.isMobile) {
+ thisPointer._onFocusOnMobile(editBox);
+ }
+
+ if (editBox._delegate && editBox._delegate.editBoxEditingDidBegin) {
+ editBox._delegate.editBoxEditingDidBegin(editBox);
+ }
+ });
+ tmpEdTxt.addEventListener('blur', function () {
+ var editBox = thisPointer._editBox;
+ editBox._text = this.value;
+ thisPointer._updateDomTextCases();
+
+ if (editBox._delegate && editBox._delegate.editBoxEditingDidEnd) {
+ editBox._delegate.editBoxEditingDidEnd(editBox);
+ }
+
+ if (this.value === '') {
+ this.style.fontSize = editBox._placeholderFontSize + 'px';
+ this.style.color = cc.colorToHex(editBox._placeholderColor);
+ }
+ thisPointer._endEditing();
+ });
+
+ this._addDomToGameContainer();
+ return tmpEdTxt;
+ };
+
+ proto._createDomTextArea = function () {
+ this._removeDomFromGameContainer();
+ var thisPointer = this;
+ var tmpEdTxt = this._edTxt = document.createElement('textarea');
+ tmpEdTxt.type = 'text';
+ tmpEdTxt.style.fontFamily = this._edFontName;
+ tmpEdTxt.style.fontSize = this._edFontSize + 'px';
+ tmpEdTxt.style.color = '#000000';
+ tmpEdTxt.style.border = 0;
+ tmpEdTxt.style.background = 'transparent';
+ tmpEdTxt.style.width = '100%';
+ tmpEdTxt.style.height = '100%';
+ tmpEdTxt.style.active = 0;
+ tmpEdTxt.style.outline = 'medium';
+ tmpEdTxt.style.padding = '0';
+ tmpEdTxt.style.resize = 'none';
+ tmpEdTxt.style.textTransform = 'uppercase';
+ tmpEdTxt.style.overflow_y = 'scroll';
+ tmpEdTxt.style.display = 'none';
+ tmpEdTxt.style.position = "absolute";
+ tmpEdTxt.style.bottom = "0px";
+ tmpEdTxt.style.left = LEFT_PADDING + "px";
+ tmpEdTxt.style.className = "cocosEditBox";
+ this.setMaxLength(thisPointer._editBox._maxLength);
+
+ tmpEdTxt.addEventListener('input', function () {
+ if (this.value.length > this.maxLength) {
+ this.value = this.value.slice(0, this.maxLength);
+ }
+
+ var editBox = thisPointer._editBox;
+ if (editBox._delegate && editBox._delegate.editBoxTextChanged) {
+ if (editBox._text.toLowerCase() !== this.value.toLowerCase()) {
+ editBox._text = this.value;
+ thisPointer._updateDomTextCases();
+ editBox._delegate.editBoxTextChanged(editBox, editBox._text);
+ }
+ }
+ });
+
+ tmpEdTxt.addEventListener('focus', function () {
+ var editBox = thisPointer._editBox;
+ thisPointer._hiddenLabels();
+
+ this.style.fontSize = thisPointer._edFontSize + 'px';
+ this.style.color = cc.colorToHex(editBox._textColor);
+
+ if (cc.sys.isMobile) {
+ thisPointer._onFocusOnMobile(editBox);
+ }
+
+ if (editBox._delegate && editBox._delegate.editBoxEditingDidBegin) {
+ editBox._delegate.editBoxEditingDidBegin(editBox);
+ }
+
+ });
+ tmpEdTxt.addEventListener('keypress', function (e) {
+ var editBox = thisPointer._editBox;
+
+ if (e.keyCode === cc.KEY.enter) {
+ e.stopPropagation();
+
+ if (editBox._delegate && editBox._delegate.editBoxReturn) {
+ editBox._delegate.editBoxReturn(editBox);
+ }
+ }
+ });
+ tmpEdTxt.addEventListener('blur', function () {
+ var editBox = thisPointer._editBox;
+ editBox._text = this.value;
+ thisPointer._updateDomTextCases();
+
+ if (editBox._delegate && editBox._delegate.editBoxEditingDidEnd) {
+ editBox._delegate.editBoxEditingDidEnd(editBox);
+ }
+
+ if (this.value === '') {
+ this.style.fontSize = editBox._placeholderFontSize + 'px';
+ this.style.color = cc.colorToHex(editBox._placeholderColor);
+ }
+
+ thisPointer._endEditing();
+ });
+
+ this._addDomToGameContainer();
+ return tmpEdTxt;
+ };
+
+ proto._createLabels = function () {
+ var editBoxSize = this._editBox.getContentSize();
+ if (!this._textLabel) {
+ this._textLabel = new cc.LabelTTF();
+ this._textLabel.setAnchorPoint(cc.p(0, 1));
+ this._editBox.addChild(this._textLabel, 100);
+ }
+
+ if (!this._placeholderLabel) {
+ this._placeholderLabel = new cc.LabelTTF();
+ this._placeholderLabel.setAnchorPoint(cc.p(0, 1));
+ this._placeholderLabel.setColor(cc.color.GRAY);
+ this._editBox.addChild(this._placeholderLabel, 100);
+ }
+
+ this._updateLabelPosition(editBoxSize);
+ };
+
+ proto._removeLabels = function () {
+ if (!this._textLabel) return;
+
+ this._editBox.removeChild(this._textLabel);
+ this._textLabel = null;
+ };
+
+ proto._updateLabelPosition = function (editBoxSize) {
+ if (!this._textLabel || !this._placeholderLabel) return;
+
+ var labelContentSize = cc.size(editBoxSize.width - LEFT_PADDING, editBoxSize.height);
+ this._textLabel.setContentSize(labelContentSize);
+ this._textLabel.setDimensions(labelContentSize);
+ this._placeholderLabel.setLineHeight(editBoxSize.height);
+ var placeholderLabelSize = this._placeholderLabel.getContentSize();
+
+ if (this._editBox._editBoxInputMode === cc.EDITBOX_INPUT_MODE_ANY) {
+ this._textLabel.setPosition(LEFT_PADDING, editBoxSize.height);
+ this._placeholderLabel.setPosition(LEFT_PADDING, editBoxSize.height);
+ this._placeholderLabel.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_TOP);
+ this._textLabel.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_TOP);
+ // this._textLabel.enableWrapText(true);
+ }
+ else {
+ // this._textLabel.enableWrapText(false);
+ this._textLabel.setPosition(LEFT_PADDING, editBoxSize.height);
+ this._placeholderLabel.setPosition(LEFT_PADDING, (editBoxSize.height + placeholderLabelSize.height) / 2);
+ this._placeholderLabel.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
+ this._textLabel.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER);
+ }
+
+ };
+
+ proto.setLineHeight = function (lineHeight) {
+ if (this._textLabel) {
+ this._textLabel.setLineHeight(lineHeight);
+ }
+ };
+
+ proto._hiddenLabels = function () {
+ if (this._textLabel) {
+ this._textLabel.setVisible(false);
+ }
+
+ if (this._placeholderLabel) {
+ this._placeholderLabel.setVisible(false);
+ }
+ };
+
+ proto._updateDomTextCases = function () {
+ var inputFlag = this._editBox._editBoxInputFlag;
+ if (inputFlag === cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS) {
+ this._editBox._text = this._editBox._text.toUpperCase();
+ }
+ else if (inputFlag === cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD) {
+ this._editBox._text = capitalize(this._editBox._text);
+ }
+ else if (inputFlag === cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE) {
+ this._editBox._text = capitalizeFirstLetter(this._editBox._text);
+ }
+ };
+
+ proto._updateLabelStringStyle = function () {
+ if (this._edTxt.type === 'password') {
+ var passwordString = '';
+ var len = this._editBox._text.length;
+ for (var i = 0; i < len; ++i) {
+ passwordString += '\u25CF';
+ }
+ if (this._textLabel) {
+ this._textLabel.setString(passwordString);
+ }
+ } else {
+ this._updateDomTextCases();
+ if (this._textLabel) {
+ this._textLabel.setString(this._editBox._text);
+ }
+ }
+ };
+
+ proto._showLabels = function () {
+ this._hiddenLabels();
+ if (this._edTxt.value === '') {
+ if (this._placeholderLabel) {
+ this._placeholderLabel.setVisible(true);
+ this._placeholderLabel.setString(this._editBox._placeholderText);
+ }
+ }
+ else {
+ if (this._textLabel) {
+ this._textLabel.setVisible(true);
+ this._textLabel.setString(this._editBox._text);
+ }
+ }
+ this._updateLabelStringStyle();
+ };
+
+ proto._beginEditing = function () {
+ if (!this._editBox._alwaysOnTop) {
+ if (this._edTxt.style.display === 'none') {
+ this._edTxt.style.display = '';
+ this._edTxt.focus();
+ }
+ }
+
+ if (cc.sys.isMobile && !this._editingMode) {
+ // Pre adaptation and
+ this._beginEditingOnMobile(this._editBox);
+ }
+ this._editingMode = true;
+ };
+
+ proto._endEditing = function () {
+ if (!this._editBox._alwaysOnTop) {
+ this._edTxt.style.display = 'none';
+ }
+ this._showLabels();
+ if (cc.sys.isMobile && this._editingMode) {
+ var self = this;
+ // Delay end editing adaptation to ensure virtual keyboard is disapeared
+ setTimeout(function () {
+ self._endEditingOnMobile();
+ }, TIMER_NAME);
+ }
+ this._editingMode = false;
+ };
+
+ proto._setFont = function (fontStyle) {
+ var res = cc.LabelTTF._fontStyleRE.exec(fontStyle);
+ var textFontName = res[2];
+ var textFontSize = parseInt(res[1]);
+ if (res) {
+ this.setFont(textFontName, textFontSize);
+ }
+ };
+
+ proto.setFont = function (fontName, fontSize) {
+ this._edFontName = fontName || this._edFontName;
+ this._edFontSize = fontSize || this._edFontSize;
+ this._updateDOMFontStyle();
+ };
+
+ proto.setFontName = function (fontName) {
+ this._edFontName = fontName || this._edFontName;
+ this._updateDOMFontStyle();
+ };
+
+ proto.setFontSize = function (fontSize) {
+ this._edFontSize = fontSize || this._edFontSize;
+ this._updateDOMFontStyle();
+ };
+
+ proto.setFontColor = function (color) {
+ if (!this._edTxt) return;
+
+ if (this._edTxt.value !== this._editBox._placeholderText) {
+ this._edTxt.style.color = cc.colorToHex(color);
+ }
+ if (this._textLabel) {
+ this._textLabel.setColor(color);
+ }
+ };
+
+ proto.setPlaceHolder = function (text) {
+ this._placeholderLabel.setString(text);
+ };
+
+ proto.setMaxLength = function (maxLength) {
+ if (!this._edTxt) return;
+ this._edTxt.maxLength = maxLength;
+ };
+
+ proto._updateDOMPlaceholderFontStyle = function () {
+ this._placeholderLabel.setFontName(this._editBox._placeholderFontName);
+ this._placeholderLabel.setFontSize(this._editBox._placeholderFontSize);
+ };
+
+ proto.setPlaceholderFontColor = function (color) {
+ this._placeholderLabel.setColor(color);
+ };
+
+ proto._updateDomInputType = function () {
+ var inputMode = this._editBox._editBoxInputMode;
+ if (inputMode === cc.EDITBOX_INPUT_MODE_EMAILADDR) {
+ this._edTxt.type = 'email';
+ } else if (inputMode === cc.EDITBOX_INPUT_MODE_DECIMAL ||
+ inputMode === cc.EDITBOX_INPUT_MODE_NUMERIC) {
+ this._edTxt.type = 'number';
+ } else if (inputMode === cc.EDITBOX_INPUT_MODE_PHONENUMBER) {
+ this._edTxt.type = 'number';
+ this._edTxt.pattern = '[0-9]*';
+ } else if (inputMode === cc.EDITBOX_INPUT_MODE_URL) {
+ this._edTxt.type = 'url';
+ } else {
+ this._edTxt.type = 'text';
+
+ if (this._editBox._keyboardReturnType === cc.KEYBOARD_RETURNTYPE_SEARCH) {
+ this._edTxt.type = 'search';
+ }
+ }
+
+ if (this._editBox._editBoxInputFlag === cc.EDITBOX_INPUT_FLAG_PASSWORD) {
+ this._edTxt.type = 'password';
+ }
+ };
+
+ proto.setInputFlag = function (inputFlag) {
+ if (!this._edTxt) return;
+
+ this._updateDomInputType();
+
+ this._edTxt.style.textTransform = 'none';
+
+ if (inputFlag === cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS) {
+ this._edTxt.style.textTransform = 'uppercase';
+ }
+ else if (inputFlag === cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD) {
+ this._edTxt.style.textTransform = 'capitalize';
+ }
+ this._updateLabelStringStyle();
+ };
+
+ proto.setInputMode = function (inputMode) {
+ if (inputMode === cc.EDITBOX_INPUT_MODE_ANY) {
+ this._createDomTextArea();
+ }
+ else {
+ this._createDomInput();
+ }
+
+ this._updateDomInputType();
+ var contentSize = this._node.getContentSize();
+ this.updateSize(contentSize.width, contentSize.height);
+ };
+
+ proto.setString = function (text) {
+ if (!this._edTxt) return;
+
+ if (text !== null) {
+ this._edTxt.value = text;
+
+ if (text === '') {
+ if (this._placeholderLabel) {
+ this._placeholderLabel.setString(this._editBox._placeholderText);
+ this._placeholderLabel.setColor(this._editBox._placeholderColor);
+ }
+ if (!this._editingMode) {
+ if (this._placeholderLabel) {
+ this._placeholderLabel.setVisible(true);
+ }
+
+ if (this._textLabel) {
+ this._textLabel.setVisible(false);
+ }
+ }
+ }
+ else {
+ this._edTxt.style.color = cc.colorToHex(this._editBox._textColor);
+ if (this._textLabel) {
+ this._textLabel.setColor(this._editBox._textColor);
+ }
+ if (!this._editingMode) {
+ if (this._placeholderLabel) {
+ this._placeholderLabel.setVisible(false);
+ }
+ if (this._textLabel) {
+ this._textLabel.setVisible(true);
+ }
+ }
+
+ this._updateLabelStringStyle();
+ }
+ }
+ };
+
+ proto._updateDOMFontStyle = function () {
+ if (!this._edTxt) return;
+
+ if (this._edTxt.value !== '') {
+ this._edTxt.style.fontFamily = this._edFontName;
+ this._edTxt.style.fontSize = this._edFontSize + 'px';
+ }
+ if (this._textLabel) {
+ this._textLabel.setFontSize(this._edFontSize);
+ this._textLabel.setFontName(this._edFontName);
+ }
+ };
+
+
+ proto.updateSize = function (newWidth, newHeight) {
+ var editboxDomNode = this._edTxt;
+ if (!editboxDomNode) return;
+
+ editboxDomNode.style['width'] = newWidth + 'px';
+ editboxDomNode.style['height'] = newHeight + 'px';
+
+ this._updateLabelPosition(cc.size(newWidth, newHeight));
+ };
+
+ proto._addDomToGameContainer = function () {
+ cc.game.container.appendChild(this._edTxt);
+ };
+
+ proto._removeDomFromGameContainer = function () {
+ var editBox = this._edTxt;
+ if (editBox) {
+ var hasChild = false;
+ if ('contains' in cc.game.container) {
+ hasChild = cc.game.container.contains(editBox);
+ } else {
+ hasChild = cc.game.container.compareDocumentPosition(editBox) % 16;
+ }
+ if (hasChild)
+ cc.game.container.removeChild(editBox);
+ }
+ this._edTxt = null;
+ };
+
+ proto.initializeRenderCmd = function (node) {
+ this._editBox = node;
+
+ //it's a dom node, may be assigned with Input or TextArea.
+ this._edFontSize = 14;
+ this._edFontName = 'Arial';
+ this._textLabel = null;
+ this._placeholderLabel = null;
+ this._editingMode = false;
+
+ this.__fullscreen = false;
+ this.__autoResize = false;
+ this.__rotateScreen = false;
+ this.__orientationChanged = null;
+ };
+
+ //define the canvas render command
+ cc.EditBox.CanvasRenderCmd = function (node) {
+ this._rootCtor(node);
+ this.initializeRenderCmd(node);
+ };
+
+ var canvasRenderCmdProto = cc.EditBox.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+
+ cc.inject(proto, canvasRenderCmdProto);
+ canvasRenderCmdProto.constructor = cc.EditBox.CanvasRenderCmd;
+
+ canvasRenderCmdProto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+ this.updateMatrix();
+ };
+
+
+ //define the webgl render command
+ cc.EditBox.WebGLRenderCmd = function (node) {
+ this._rootCtor(node);
+ this.initializeRenderCmd(node);
+ };
+
+ var webGLRenderCmdProto = cc.EditBox.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+ cc.inject(proto, webGLRenderCmdProto);
+ webGLRenderCmdProto.constructor = cc.EditBox.WebGLRenderCmd;
+
+ webGLRenderCmdProto.transform = function (parentCmd, recursive) {
+ this.originTransform(parentCmd, recursive);
+ this.updateMatrix();
+ };
+
+}(cc.EditBox._polyfill));
diff --git a/extensions/GUI/CCControlExtension/CCControl.js b/extensions/gui/control-extension/CCControl.js
similarity index 76%
rename from extensions/GUI/CCControlExtension/CCControl.js
rename to extensions/gui/control-extension/CCControl.js
index 6a85ee02cf..e4071a3ef2 100644
--- a/extensions/GUI/CCControlExtension/CCControl.js
+++ b/extensions/gui/control-extension/CCControl.js
@@ -1,6 +1,7 @@
/**
- *
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
* Copyright 2011 Yannick Loriot.
* http://yannickloriot.com
*
@@ -22,8 +23,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
- *
- * converted to Javascript / cocos2d-x by Angus C
*/
/** Number of kinds of control event. */
@@ -56,49 +55,56 @@ cc.CONTROL_STATE_INITIAL = 1 << 3;
* certain events occur.
* To use the CCControl you have to subclass it.
* @class
- * @extends cc.LayerRGBA
+ * @extends cc.Layer
+ *
+ * @property {Number} state - <@readonly> The current control state: cc.CONTROL_STATE_NORMAL | cc.CONTROL_STATE_HIGHLIGHTED | cc.CONTROL_STATE_DISABLED | cc.CONTROL_STATE_SELECTED | cc.CONTROL_STATE_INITIAL
+ * @property {Boolean} enabled - Indicate whether the control node is enbaled
+ * @property {Boolean} selected - Indicate whether the control node is selected
+ * @property {Boolean} highlighted - Indicate whether the control node is highlighted
*/
-cc.Control = cc.LayerRGBA.extend({
- _isOpacityModifyRGB:false,
- _hasVisibleParents:false,
+cc.Control = cc.Layer.extend(/** @lends cc.Control# */{
+ _isOpacityModifyRGB: false,
+ _hasVisibleParents: false,
+ _touchListener: null,
+ _className: "Control",
- isOpacityModifyRGB:function () {
+ isOpacityModifyRGB: function () {
return this._isOpacityModifyRGB;
},
- setOpacityModifyRGB:function (opacityModifyRGB) {
+ setOpacityModifyRGB: function (opacityModifyRGB) {
this._isOpacityModifyRGB = opacityModifyRGB;
var children = this.getChildren();
for (var i = 0, len = children.length; i < len; i++) {
var selNode = children[i];
- if (selNode && selNode.RGBAProtocol)
+ if (selNode)
selNode.setOpacityModifyRGB(opacityModifyRGB);
}
},
/** The current control state constant. */
- _state:cc.CONTROL_STATE_NORMAL,
- getState:function () {
+ _state: cc.CONTROL_STATE_NORMAL,
+ getState: function () {
return this._state;
},
- _enabled:false,
- _selected:false,
- _highlighted:false,
+ _enabled: false,
+ _selected: false,
+ _highlighted: false,
- _dispatchTable:null,
+ _dispatchTable: null,
/**
* Tells whether the control is enabled
* @param {Boolean} enabled
*/
- setEnabled:function (enabled) {
+ setEnabled: function (enabled) {
this._enabled = enabled;
- this._state = enabled ? cc.CONTROL_STATE_NORMAL:cc.CONTROL_STATE_DISABLED;
+ this._state = enabled ? cc.CONTROL_STATE_NORMAL : cc.CONTROL_STATE_DISABLED;
this.needsLayout();
},
- isEnabled:function () {
+ isEnabled: function () {
return this._enabled;
},
@@ -106,11 +112,11 @@ cc.Control = cc.LayerRGBA.extend({
* A Boolean value that determines the control selected state.
* @param {Boolean} selected
*/
- setSelected:function (selected) {
+ setSelected: function (selected) {
this._selected = selected;
this.needsLayout();
},
- isSelected:function () {
+ isSelected: function () {
return this._selected;
},
@@ -118,15 +124,15 @@ cc.Control = cc.LayerRGBA.extend({
* A Boolean value that determines whether the control is highlighted.
* @param {Boolean} highlighted
*/
- setHighlighted:function (highlighted) {
+ setHighlighted: function (highlighted) {
this._highlighted = highlighted;
this.needsLayout();
},
- isHighlighted:function () {
+ isHighlighted: function () {
return this._highlighted;
},
- hasVisibleParents:function () {
+ hasVisibleParents: function () {
var parent = this.getParent();
for (var c = parent; c != null; c = c.getParent()) {
if (!c.isVisible())
@@ -135,36 +141,40 @@ cc.Control = cc.LayerRGBA.extend({
return true;
},
- ctor:function () {
- cc.LayerRGBA.prototype.ctor.call(this);
+ ctor: function () {
+ cc.Layer.prototype.ctor.call(this);
this._dispatchTable = {};
- this._color = cc.white();
+ this._color = cc.color.WHITE;
},
- init:function () {
- if (cc.LayerRGBA.prototype.init.call(this)) {
- //this.setTouchEnabled(true);
- //m_bIsTouchEnabled=true;
- // Initialise instance variables
- this._state = cc.CONTROL_STATE_NORMAL;
- this._enabled = true;
- this._selected = false;
- this._highlighted = false;
-
- // Set the touch dispatcher priority by default to 1
- this._defaultTouchPriority = 1;
- this.setTouchPriority(1);
- // Initialise the tables
- //this._dispatchTable = {};
- //dispatchTable.autorelease();
- // dispatchTable_ = [[NSMutableDictionary alloc] initWithCapacity:1];
- return true;
- } else
- return false;
+ init: function () {
+ // Initialise instance variables
+ this._state = cc.CONTROL_STATE_NORMAL;
+ this._enabled = true;
+ this._selected = false;
+ this._highlighted = false;
+
+ var listener = cc.EventListener.create({
+ event: cc.EventListener.TOUCH_ONE_BY_ONE,
+ swallowTouches: true
+ });
+ if (this.onTouchBegan)
+ listener.onTouchBegan = this.onTouchBegan.bind(this);
+ if (this.onTouchMoved)
+ listener.onTouchMoved = this.onTouchMoved.bind(this);
+ if (this.onTouchEnded)
+ listener.onTouchEnded = this.onTouchEnded.bind(this);
+ if (this.onTouchCancelled)
+ listener.onTouchCancelled = this.onTouchCancelled.bind(this);
+ this._touchListener = listener;
+ return true;
},
- registerWithTouchDispatcher:function () {
- cc.registerTargetedDelegate(this.getTouchPriority(), true, this);
+ onEnter: function () {
+ var locListener = this._touchListener;
+ if (!locListener._isRegistered())
+ cc.eventManager.addListener(locListener, this);
+ cc.Node.prototype.onEnter.call(this);
},
/**
@@ -172,7 +182,7 @@ cc.Control = cc.LayerRGBA.extend({
* which action messages are sent. See "CCControlEvent" for bitmask constants.
* @param {Number} controlEvents A bitmask whose set flags specify the control events for
*/
- sendActionsForControlEvents:function (controlEvents) {
+ sendActionsForControlEvents: function (controlEvents) {
// For each control events
for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
// If the given controlEvents bitmask contains the curent event
@@ -199,7 +209,7 @@ cc.Control = cc.LayerRGBA.extend({
* @param {function} action A selector identifying an action message. It cannot be NULL.
* @param {Number} controlEvents A bitmask specifying the control events for which the action message is sent. See "CCControlEvent" for bitmask constants.
*/
- addTargetWithActionForControlEvents:function (target, action, controlEvents) {
+ addTargetWithActionForControlEvents: function (target, action, controlEvents) {
// For each control events
for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
// If the given controlEvents bit mask contains the current event
@@ -215,7 +225,7 @@ cc.Control = cc.LayerRGBA.extend({
* @param {function} action A selector identifying an action message. Pass NULL to remove all action messages paired with target.
* @param {Number} controlEvents A bitmask specifying the control events associated with target and action. See "CCControlEvent" for bitmask constants.
*/
- removeTargetWithActionForControlEvents:function (target, action, controlEvents) {
+ removeTargetWithActionForControlEvents: function (target, action, controlEvents) {
// For each control events
for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) {
// If the given controlEvents bitmask contains the current event
@@ -229,7 +239,7 @@ cc.Control = cc.LayerRGBA.extend({
* control space coordinates.
* @param {cc.Touch} touch A CCTouch object that represents a touch.
*/
- getTouchLocation:function (touch) {
+ getTouchLocation: function (touch) {
var touchLocation = touch.getLocation(); // Get the touch position
return this.convertToNodeSpace(touchLocation); // Convert to the node space of this class
},
@@ -240,7 +250,7 @@ cc.Control = cc.LayerRGBA.extend({
* @param {cc.Touch} touch A cc.Touch object that represents a touch.
* @return {Boolean} YES whether a touch is inside the receiver's rect.
*/
- isTouchInside:function (touch) {
+ isTouchInside: function (touch) {
var touchLocation = touch.getLocation(); // Get the touch position
touchLocation = this.getParent().convertToNodeSpace(touchLocation);
return cc.rectContainsPoint(this.getBoundingBox(), touchLocation);
@@ -258,7 +268,7 @@ cc.Control = cc.LayerRGBA.extend({
*
* @return {cc.Invocation} an CCInvocation object able to construct messages using a given target-action pair.
*/
- _invocationWithTargetAndActionForControlEvent:function (target, action, controlEvent) {
+ _invocationWithTargetAndActionForControlEvent: function (target, action, controlEvent) {
return null;
},
@@ -268,10 +278,10 @@ cc.Control = cc.LayerRGBA.extend({
* @param {Number} controlEvent A control events for which the action message is sent. See "CCControlEvent" for constants.
* @return {cc.Invocation} the cc.Invocation list for the given control event.
*/
- _dispatchListforControlEvent:function (controlEvent) {
+ _dispatchListforControlEvent: function (controlEvent) {
controlEvent = controlEvent.toString();
// If the invocation list does not exist for the dispatch table, we create it
- if (!this._dispatchTable.hasOwnProperty(controlEvent))
+ if (!this._dispatchTable[controlEvent])
this._dispatchTable[controlEvent] = [];
return this._dispatchTable[controlEvent];
},
@@ -289,7 +299,7 @@ cc.Control = cc.LayerRGBA.extend({
* @param controlEvent A control event for which the action message is sent.
* See "CCControlEvent" for constants.
*/
- _addTargetWithActionForControlEvent:function (target, action, controlEvent) {
+ _addTargetWithActionForControlEvent: function (target, action, controlEvent) {
// Create the invocation object
var invocation = new cc.Invocation(target, action, controlEvent);
@@ -305,7 +315,7 @@ cc.Control = cc.LayerRGBA.extend({
* @param {function} action A selector identifying an action message. Pass NULL to remove all action messages paired with target.
* @param {Number} controlEvent A control event for which the action message is sent. See "CCControlEvent" for constants.
*/
- _removeTargetWithActionForControlEvent:function (target, action, controlEvent) {
+ _removeTargetWithActionForControlEvent: function (target, action, controlEvent) {
// Retrieve all invocations for the given control event
//
var eventInvocationList = this._dispatchListforControlEvent(controlEvent);
@@ -318,16 +328,18 @@ cc.Control = cc.LayerRGBA.extend({
eventInvocationList.length = 0;
} else {
//normally we would use a predicate, but this won't work here. Have to do it manually
- for (var i = 0; i < eventInvocationList.length; i++) {
+ for (var i = 0; i < eventInvocationList.length;) {
var invocation = eventInvocationList[i];
var shouldBeRemoved = true;
if (target)
- shouldBeRemoved = (target == invocation.getTarget());
+ shouldBeRemoved = (target === invocation.getTarget());
if (action)
- shouldBeRemoved = (shouldBeRemoved && (action == invocation.getAction()));
+ shouldBeRemoved = (shouldBeRemoved && (action === invocation.getAction()));
// Remove the corresponding invocation object
if (shouldBeRemoved)
- cc.ArrayRemoveObject(eventInvocationList, invocation);
+ cc.arrayRemoveObject(eventInvocationList, invocation);
+ else
+ i++;
}
}
},
@@ -335,10 +347,28 @@ cc.Control = cc.LayerRGBA.extend({
/**
* Updates the control layout using its current internal state.
*/
- needsLayout:function () {
+ needsLayout: function () {
}
});
+var _p = cc.Control.prototype;
+
+// Extended properties
+/** @expose */
+_p.state;
+cc.defineGetterSetter(_p, "state", _p.getState);
+/** @expose */
+_p.enabled;
+cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled);
+/** @expose */
+_p.selected;
+cc.defineGetterSetter(_p, "selected", _p.isSelected, _p.setSelected);
+/** @expose */
+_p.highlighted;
+cc.defineGetterSetter(_p, "highlighted", _p.isHighlighted, _p.setHighlighted);
+
+_p = null;
+
cc.Control.create = function () {
var retControl = new cc.Control();
if (retControl && retControl.init())
diff --git a/extensions/GUI/CCControlExtension/CCControlButton.js b/extensions/gui/control-extension/CCControlButton.js
similarity index 68%
rename from extensions/GUI/CCControlExtension/CCControlButton.js
rename to extensions/gui/control-extension/CCControlButton.js
index e57fcf0ec4..9e70ef291c 100644
--- a/extensions/GUI/CCControlExtension/CCControlButton.js
+++ b/extensions/gui/control-extension/CCControlButton.js
@@ -1,7 +1,9 @@
/**
* CCControlButton.m
*
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
* Copyright 2011 Yannick Loriot.
* http://yannickloriot.com
*
@@ -24,53 +26,75 @@
* THE SOFTWARE.
*/
+/**
+ * @ignore
+ */
cc.CONTROL_ZOOM_ACTION_TAG = 0xCCCB0001;
-/** @class CCControlButton Button control for Cocos2D. */
-cc.ControlButton = cc.Control.extend({
- _doesAdjustBackgroundImage:false,
- _zoomOnTouchDown:false,
+/**
+ * CCControlButton: Button control for Cocos2D.
+ * @class
+ * @extends cc.Control
+ *
+ * @property {Boolean} adjustBackgroundImage - Indicate whether the background image will be adjusted
+ * @property {Boolean} zoomOnTouchDown - Indicate whether the button will be zoomed while touch down
+ * @property {cc.Size} preferredSize - The preferred size of the control button
+ * @property {Boolean} labelAnchor - The anchor point for the label of the control button
+ */
+cc.ControlButton = cc.Control.extend(/** @lends cc.ControlButton# */{
+ _doesAdjustBackgroundImage: false,
+ zoomOnTouchDown: false,
_preferredSize: null,
_labelAnchorPoint: null,
_currentTitle: null,
_currentTitleColor: null,
- _titleLabel:null,
- _backgroundSprite:null,
- _opacity:0,
- _isPushed:false,
- _titleDispatchTable:null,
- _titleColorDispatchTable:null,
- _titleLabelDispatchTable:null,
- _backgroundSpriteDispatchTable:null,
- _parentInited:false,
-
- _marginV:0,
- _marginH:0,
-
- ctor:function () {
+ _titleLabel: null,
+ _backgroundSprite: null,
+ _opacity: 0,
+ _isPushed: false,
+ _titleDispatchTable: null,
+ _titleColorDispatchTable: null,
+ _titleLabelDispatchTable: null,
+ _backgroundSpriteDispatchTable: null,
+ _parentInited: false,
+
+ _marginV: 0,
+ _marginH: 0,
+ _className: "ControlButton",
+
+ ctor: function (label, backgroundSprite, fontSize) {
cc.Control.prototype.ctor.call(this);
- this._preferredSize = new cc.Size(0, 0);
- this._labelAnchorPoint = new cc.Point(0, 0);
+ this._preferredSize = cc.size(0, 0);
+ this._labelAnchorPoint = cc.p(0, 0);
this._currentTitle = "";
- this._currentTitleColor = cc.white();
+ this._currentTitleColor = cc.color.WHITE;
this._titleDispatchTable = {};
this._titleColorDispatchTable = {};
this._titleLabelDispatchTable = {};
this._backgroundSpriteDispatchTable = {};
+
+ if(fontSize != undefined)
+ this.initWithTitleAndFontNameAndFontSize(label, backgroundSprite, fontSize);
+ else if(backgroundSprite != undefined)
+ this.initWithLabelAndBackgroundSprite(label, backgroundSprite);
+ else if(label != undefined)
+ this.initWithBackgroundSprite(label);
+ else
+ this.init();
},
- init:function () {
- return this.initWithLabelAndBackgroundSprite(cc.LabelTTF.create("", "Arial", 12), cc.Scale9Sprite.create());
+ init: function () {
+ return this.initWithLabelAndBackgroundSprite(new cc.LabelTTF("", "Arial", 12), new cc.Scale9Sprite());
},
- needsLayout:function () {
+ needsLayout: function () {
if (!this._parentInited) {
return;
}
// Hide the background and the label
- if(this._titleLabel)
+ if (this._titleLabel)
this._titleLabel.setVisible(false);
- if(this._backgroundSprite)
+ if (this._backgroundSprite)
this._backgroundSprite.setVisible(false);
// Update anchor of all labels
@@ -87,30 +111,34 @@ cc.ControlButton = cc.Control.extend({
var label = this._titleLabel;
if (label && label.setString)
label.setString(this._currentTitle);
- if (label && label.RGBAProtocol)
+ if (label)
label.setColor(this._currentTitleColor);
var locContentSize = this.getContentSize();
- if(label)
+ if (label)
label.setPosition(locContentSize.width / 2, locContentSize.height / 2);
// Update the background sprite
this._backgroundSprite = this.getBackgroundSpriteForState(locState);
var locBackgroundSprite = this._backgroundSprite;
- if(locBackgroundSprite)
+ if (locBackgroundSprite)
locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2);
// Get the title label size
- var titleLabelSize = label ? label.getBoundingBox().size : cc.size(0, 0);
-
+ var titleLabelSize = cc.size(0, 0);
+ if (label) {
+ var boundingBox = label.getBoundingBox();
+ titleLabelSize.width = boundingBox.width;
+ titleLabelSize.height = boundingBox.height;
+ }
// Adjust the background image if necessary
if (this._doesAdjustBackgroundImage) {
// Add the margins
- if(locBackgroundSprite)
- locBackgroundSprite.setContentSize(cc.size(titleLabelSize.width + this._marginH * 2, titleLabelSize.height + this._marginV * 2));
+ if (locBackgroundSprite)
+ locBackgroundSprite.setContentSize(titleLabelSize.width + this._marginH * 2, titleLabelSize.height + this._marginV * 2);
} else {
//TODO: should this also have margins if one of the preferred sizes is relaxed?
- if(locBackgroundSprite){
+ if (locBackgroundSprite) {
var preferredSize = locBackgroundSprite.getPreferredSize();
preferredSize = cc.size(preferredSize.width, preferredSize.height);
if (preferredSize.width <= 0)
@@ -123,26 +151,27 @@ cc.ControlButton = cc.Control.extend({
}
// Set the content size
- var rectTitle = label? label.getBoundingBox():cc.rect(0,0,0,0);
- var rectBackground = locBackgroundSprite? locBackgroundSprite.getBoundingBox():cc.rect(0,0,0,0);
+ var rectTitle = label ? label.getBoundingBox() : cc.rect(0, 0, 0, 0);
+ var rectBackground = locBackgroundSprite ? locBackgroundSprite.getBoundingBox() : cc.rect(0, 0, 0, 0);
var maxRect = cc.rectUnion(rectTitle, rectBackground);
- this.setContentSize(cc.size(maxRect.width, maxRect.height));
+ this.setContentSize(maxRect.width, maxRect.height);
locContentSize = this.getContentSize();
- if(label){
+ if (label) {
label.setPosition(locContentSize.width / 2, locContentSize.height / 2);
label.setVisible(true);
}
- if(locBackgroundSprite){
+ if (locBackgroundSprite) {
locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2);
locBackgroundSprite.setVisible(true);
}
},
- initWithLabelAndBackgroundSprite:function (label, backgroundSprite) {
+ initWithLabelAndBackgroundSprite: function (label, backgroundSprite) {
+ if (!label)
+ throw new Error("cc.ControlButton.initWithLabelAndBackgroundSprite(): label should be non-null");
+ if (!backgroundSprite)
+ throw new Error("cc.ControlButton.initWithLabelAndBackgroundSprite(): backgroundSprite should be non-null");
if (cc.Control.prototype.init.call(this, true)) {
- cc.Assert(label != null, "node must not be nil");
- cc.Assert(label != null || label.RGBAProtocol || backgroundSprite != null, "");
-
this._parentInited = true;
// Initialize the button state tables
@@ -151,22 +180,21 @@ cc.ControlButton = cc.Control.extend({
this._titleLabelDispatchTable = {};
this._backgroundSpriteDispatchTable = {};
- this.setTouchEnabled(true);
this._isPushed = false;
- this._zoomOnTouchDown = true;
+ this.zoomOnTouchDown = true;
this._currentTitle = null;
// Adjust the background image by default
this.setAdjustBackgroundImage(true);
- this.setPreferredSize(cc.size(0,0));
+ this.setPreferredSize(cc.size(0, 0));
// Zooming button by default
- this._zoomOnTouchDown = true;
+ this.zoomOnTouchDown = true;
// Set the default anchor point
this.ignoreAnchorPointForPosition(false);
- this.setAnchorPoint(cc.p(0.5, 0.5));
+ this.setAnchorPoint(0.5, 0.5);
// Set the nodes
this._titleLabel = label;
@@ -190,9 +218,9 @@ cc.ControlButton = cc.Control.extend({
this._marginH = 24;
this._marginV = 12;
- this._labelAnchorPoint = new cc.Point(0.5, 0.5);
+ this._labelAnchorPoint = cc.p(0.5, 0.5);
- this.setPreferredSize(cc.SizeZero());
+ this.setPreferredSize(cc.size(0, 0));
// Layout update
this.needsLayout();
@@ -202,44 +230,44 @@ cc.ControlButton = cc.Control.extend({
return false;
},
- initWithTitleAndFontNameAndFontSize:function (title, fontName, fontSize) {
- var label = cc.LabelTTF.create(title, fontName, fontSize);
- return this.initWithLabelAndBackgroundSprite(label, cc.Scale9Sprite.create());
+ initWithTitleAndFontNameAndFontSize: function (title, fontName, fontSize) {
+ var label = new cc.LabelTTF(title, fontName, fontSize);
+ return this.initWithLabelAndBackgroundSprite(label, new cc.Scale9Sprite());
},
- initWithBackgroundSprite:function (sprite) {
- var label = cc.LabelTTF.create("", "Arial", 30);//
+ initWithBackgroundSprite: function (sprite) {
+ var label = new cc.LabelTTF("", "Arial", 30);//
return this.initWithLabelAndBackgroundSprite(label, sprite);
},
/**
- * Adjust the background image. YES by default. If the property is set to NO, the background will use the prefered size of the background image.
+ * Adjust the background image. YES by default. If the property is set to NO, the background will use the preferred size of the background image.
* @return {Boolean}
*/
- doesAdjustBackgroundImage:function () {
+ doesAdjustBackgroundImage: function () {
return this._doesAdjustBackgroundImage;
},
- setAdjustBackgroundImage:function (adjustBackgroundImage) {
+ setAdjustBackgroundImage: function (adjustBackgroundImage) {
this._doesAdjustBackgroundImage = adjustBackgroundImage;
this.needsLayout();
},
/** Adjust the button zooming on touchdown. Default value is YES. */
- getZoomOnTouchDown:function () {
- return this._zoomOnTouchDown;
+ getZoomOnTouchDown: function () {
+ return this.zoomOnTouchDown;
},
- setZoomOnTouchDown:function (zoomOnTouchDown) {
- return this._zoomOnTouchDown = zoomOnTouchDown;
+ setZoomOnTouchDown: function (zoomOnTouchDown) {
+ return this.zoomOnTouchDown = zoomOnTouchDown;
},
- /** The prefered size of the button, if label is larger it will be expanded. */
- getPreferredSize:function () {
+ /** The preferred size of the button, if label is larger it will be expanded. */
+ getPreferredSize: function () {
return this._preferredSize;
},
- setPreferredSize:function (size) {
+ setPreferredSize: function (size) {
if (size.width === 0 && size.height === 0) {
this._doesAdjustBackgroundImage = true;
} else {
@@ -252,12 +280,12 @@ cc.ControlButton = cc.Control.extend({
this.needsLayout();
},
- getLabelAnchorPoint:function () {
+ getLabelAnchorPoint: function () {
return this._labelAnchorPoint;
},
- setLabelAnchorPoint:function (labelAnchorPoint) {
+ setLabelAnchorPoint: function (labelAnchorPoint) {
this._labelAnchorPoint = labelAnchorPoint;
- if(this._titleLabel)
+ if (this._titleLabel)
this._titleLabel.setAnchorPoint(labelAnchorPoint);
},
@@ -265,58 +293,59 @@ cc.ControlButton = cc.Control.extend({
* The current title that is displayed on the button.
* @return {string}
*/
- _getCurrentTitle:function () {
+ _getCurrentTitle: function () {
return this._currentTitle;
},
/** The current color used to display the title. */
- _getCurrentTitleColor:function () {
+ _getCurrentTitleColor: function () {
return this._currentTitleColor;
},
/* Override setter to affect a background sprite too */
- getOpacity:function () {
+ getOpacity: function () {
return this._opacity;
},
- setOpacity:function (opacity) {
+ setOpacity: function (opacity) {
// XXX fixed me if not correct
- cc.Control.prototype.setOpacity.call(opacity);
+ cc.Control.prototype.setOpacity.call(this, opacity);
/*this._opacity = opacity;
- var controlChildren = this.getChildren();
- for (var i = 0; i < controlChildren.length; i++) {
- var selChild = controlChildren[i];
- if (selChild && selChild.RGBAProtocol)
- selChild.setOpacity(opacity);
- }*/
+ var controlChildren = this.getChildren();
+ for (var i = 0; i < controlChildren.length; i++) {
+ var selChild = controlChildren[i];
+ if (selChild)
+ selChild.setOpacity(opacity);
+ }*/
var locTable = this._backgroundSpriteDispatchTable;
for (var itemKey in locTable)
locTable[itemKey].setOpacity(opacity);
},
- setColor:function(color){
- cc.Control.prototype.setColor.call(this,color);
+ setColor: function (color) {
+ cc.Control.prototype.setColor.call(this, color);
var locTable = this._backgroundSpriteDispatchTable;
- for(var key in locTable)
+ for (var key in locTable)
locTable[key].setColor(color);
},
- getColor:function(){
- return this._realColor;
+ getColor: function () {
+ var locRealColor = this._realColor;
+ return cc.color(locRealColor.r, locRealColor.g, locRealColor.b, locRealColor.a);
},
/** Flag to know if the button is currently pushed. */
- isPushed:function () {
+ isPushed: function () {
return this._isPushed;
},
/* Define the button margin for Top/Bottom edge */
- _getVerticalMargin:function () {
+ _getVerticalMargin: function () {
return this._marginV;
},
/* Define the button margin for Left/Right edge */
- _getHorizontalOrigin:function () {
+ _getHorizontalOrigin: function () {
return this._marginH;
},
@@ -325,40 +354,40 @@ cc.ControlButton = cc.Control.extend({
* @param {Number} marginH
* @param {Number} marginV
*/
- setMargins:function (marginH, marginV) {
+ setMargins: function (marginH, marginV) {
this._marginV = marginV;
this._marginH = marginH;
this.needsLayout();
},
- setEnabled:function (enabled) {
+ setEnabled: function (enabled) {
cc.Control.prototype.setEnabled.call(this, enabled);
this.needsLayout();
},
- setSelected:function (enabled) {
+ setSelected: function (enabled) {
cc.Control.prototype.setSelected.call(this, enabled);
this.needsLayout();
},
- setHighlighted:function (enabled) {
- this._state = enabled?cc.CONTROL_STATE_HIGHLIGHTED:cc.CONTROL_STATE_NORMAL;
+ setHighlighted: function (enabled) {
+ this._state = enabled ? cc.CONTROL_STATE_HIGHLIGHTED : cc.CONTROL_STATE_NORMAL;
cc.Control.prototype.setHighlighted.call(this, enabled);
var action = this.getActionByTag(cc.CONTROL_ZOOM_ACTION_TAG);
if (action)
this.stopAction(action);
- this.needsLayout();
- if (this._zoomOnTouchDown) {
+ //this.needsLayout();// needn't
+ if (this.zoomOnTouchDown) {
var scaleValue = (this.isHighlighted() && this.isEnabled() && !this.isSelected()) ? 1.1 : 1.0;
- var zoomAction = cc.ScaleTo.create(0.05, scaleValue);
+ var zoomAction = cc.scaleTo(0.05, scaleValue);
zoomAction.setTag(cc.CONTROL_ZOOM_ACTION_TAG);
this.runAction(zoomAction);
}
},
- onTouchBegan:function (touch, event) {
- if (!this.isTouchInside(touch) || !this.isEnabled()|| !this.isVisible()||!this.hasVisibleParents())
+ onTouchBegan: function (touch, event) {
+ if (!this.isTouchInside(touch) || !this.isEnabled() || !this.isVisible() || !this.hasVisibleParents())
return false;
this._isPushed = true;
@@ -367,7 +396,7 @@ cc.ControlButton = cc.Control.extend({
return true;
},
- onTouchMoved:function (touch, event) {
+ onTouchMoved: function (touch, event) {
if (!this._enabled || !this._isPushed || this._selected) {
if (this._highlighted)
this.setHighlighted(false);
@@ -387,7 +416,7 @@ cc.ControlButton = cc.Control.extend({
this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_OUTSIDE);
}
},
- onTouchEnded:function (touch, event) {
+ onTouchEnded: function (touch, event) {
this._isPushed = false;
this.setHighlighted(false);
@@ -398,7 +427,7 @@ cc.ControlButton = cc.Control.extend({
}
},
- onTouchCancelled:function (touch, event) {
+ onTouchCancelled: function (touch, event) {
this._isPushed = false;
this.setHighlighted(false);
this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_CANCEL);
@@ -410,7 +439,7 @@ cc.ControlButton = cc.Control.extend({
* @param {Number} state The state that uses the title. Possible values are described in "CCControlState".
* @return {string} The title for the specified state.
*/
- getTitleForState:function (state) {
+ getTitleForState: function (state) {
var locTable = this._titleDispatchTable;
if (locTable) {
if (locTable[state])
@@ -428,11 +457,11 @@ cc.ControlButton = cc.Control.extend({
* @param {string} title The title string to use for the specified state.
* @param {Number} state The state that uses the specified title. The values are described in "CCControlState".
*/
- setTitleForState:function (title, state) {
+ setTitleForState: function (title, state) {
this._titleDispatchTable[state] = title || "";
// If the current state if equal to the given state we update the layout
- if (this.getState() == state)
+ if (this.getState() === state)
this.needsLayout();
},
@@ -440,7 +469,7 @@ cc.ControlButton = cc.Control.extend({
* Returns the title color used for a state.
*
* @param {Number} state The state that uses the specified color. The values are described in "CCControlState".
- * @return {cc.Color3B} The color of the title for the specified state.
+ * @return {cc.Color} The color of the title for the specified state.
*/
getTitleColorForState: function (state) {
var colorObject = this._titleColorDispatchTable[state];
@@ -449,21 +478,21 @@ cc.ControlButton = cc.Control.extend({
colorObject = this._titleColorDispatchTable[cc.CONTROL_STATE_NORMAL];
if (colorObject)
return colorObject;
- return cc.white();
+ return cc.color.WHITE;
},
/**
* Sets the color of the title to use for the specified state.
*
- * @param {cc.Color3B} color The color of the title to use for the specified state.
+ * @param {cc.Color} color The color of the title to use for the specified state.
* @param {Number} state The state that uses the specified color. The values are described in "CCControlState".
*/
- setTitleColorForState:function (color, state) {
+ setTitleColorForState: function (color, state) {
//ccColor3B* colorValue=&color;
this._titleColorDispatchTable[state] = color;
// If the current state if equal to the given state we update the layout
- if (this.getState() == state)
+ if (this.getState() === state)
this.needsLayout();
},
@@ -473,9 +502,9 @@ cc.ControlButton = cc.Control.extend({
* @param state The state that uses the title label. Possible values are described in "CCControlState".
* @return {cc.Node} the title label used for a state.
*/
- getTitleLabelForState:function (state) {
+ getTitleLabelForState: function (state) {
var locTable = this._titleLabelDispatchTable;
- if (locTable.hasOwnProperty(state) && locTable[state])
+ if (locTable[state])
return locTable[state];
return locTable[cc.CONTROL_STATE_NORMAL];
@@ -488,9 +517,9 @@ cc.ControlButton = cc.Control.extend({
* @param {cc.Node} titleLabel The title label to use for the specified state.
* @param {Number} state The state that uses the specified title. The values are described in "CCControlState".
*/
- setTitleLabelForState:function (titleLabel, state) {
+ setTitleLabelForState: function (titleLabel, state) {
var locTable = this._titleLabelDispatchTable;
- if (locTable.hasOwnProperty(state)) {
+ if (locTable[state]) {
var previousLabel = locTable[state];
if (previousLabel)
this.removeChild(previousLabel, true);
@@ -498,11 +527,11 @@ cc.ControlButton = cc.Control.extend({
locTable[state] = titleLabel;
titleLabel.setVisible(false);
- titleLabel.setAnchorPoint(cc.p(0.5, 0.5));
+ titleLabel.setAnchorPoint(0.5, 0.5);
this.addChild(titleLabel, 1);
// If the current state if equal to the given state we update the layout
- if (this.getState() == state)
+ if (this.getState() === state)
this.needsLayout();
},
@@ -511,11 +540,11 @@ cc.ControlButton = cc.Control.extend({
* @param {string} fntFile
* @param {Number} state
*/
- setTitleTTFForState:function (fntFile, state) {
+ setTitleTTFForState: function (fntFile, state) {
var title = this.getTitleForState(state);
if (!title)
title = "";
- this.setTitleLabelForState(cc.LabelTTF.create(title, fntFile, 12), state);
+ this.setTitleLabelForState(new cc.LabelTTF(title, fntFile, 12), state);
},
/**
@@ -523,7 +552,7 @@ cc.ControlButton = cc.Control.extend({
* @param {Number} state
* @returns {string}
*/
- getTitleTTFForState:function (state) {
+ getTitleTTFForState: function (state) {
var labelTTF = this.getTitleLabelForState(state);
if ((labelTTF != null) && (labelTTF instanceof cc.LabelTTF)) {
return labelTTF.getFontName();
@@ -536,7 +565,7 @@ cc.ControlButton = cc.Control.extend({
* @param {Number} size
* @param {Number} state
*/
- setTitleTTFSizeForState:function (size, state) {
+ setTitleTTFSizeForState: function (size, state) {
var labelTTF = this.getTitleLabelForState(state);
if ((labelTTF != null) && (labelTTF instanceof cc.LabelTTF)) {
labelTTF.setFontSize(size);
@@ -548,7 +577,7 @@ cc.ControlButton = cc.Control.extend({
* @param {Number} state
* @returns {Number}
*/
- getTitleTTFSizeForState:function (state) {
+ getTitleTTFSizeForState: function (state) {
var labelTTF = this.getTitleLabelForState(state);
if ((labelTTF != null) && (labelTTF instanceof cc.LabelTTF)) {
return labelTTF.getFontSize();
@@ -561,14 +590,14 @@ cc.ControlButton = cc.Control.extend({
* @param {string} fntFile The name of the font to change to
* @param {Number} state The state that uses the specified fntFile. The values are described in "CCControlState".
*/
- setTitleBMFontForState:function (fntFile, state) {
+ setTitleBMFontForState: function (fntFile, state) {
var title = this.getTitleForState(state);
if (!title)
title = "";
- this.setTitleLabelForState(cc.LabelBMFont.create(title, fntFile), state);
+ this.setTitleLabelForState(new cc.LabelBMFont(title, fntFile), state);
},
- getTitleBMFontForState:function (state) {
+ getTitleBMFontForState: function (state) {
var labelBMFont = this.getTitleLabelForState(state);
if ((labelBMFont != null) && (labelBMFont instanceof cc.LabelBMFont)) {
return labelBMFont.getFntFile();
@@ -581,9 +610,9 @@ cc.ControlButton = cc.Control.extend({
*
* @param {Number} state The state that uses the background sprite. Possible values are described in "CCControlState".
*/
- getBackgroundSpriteForState:function (state) {
+ getBackgroundSpriteForState: function (state) {
var locTable = this._backgroundSpriteDispatchTable;
- if (locTable.hasOwnProperty(state) && locTable[state]) {
+ if (locTable[state]) {
return locTable[state];
}
return locTable[cc.CONTROL_STATE_NORMAL];
@@ -595,9 +624,9 @@ cc.ControlButton = cc.Control.extend({
* @param {Scale9Sprite} sprite The background sprite to use for the specified state.
* @param {Number} state The state that uses the specified image. The values are described in "CCControlState".
*/
- setBackgroundSpriteForState:function (sprite, state) {
+ setBackgroundSpriteForState: function (sprite, state) {
var locTable = this._backgroundSpriteDispatchTable;
- if (locTable.hasOwnProperty(state)) {
+ if (locTable[state]) {
var previousSprite = locTable[state];
if (previousSprite)
this.removeChild(previousSprite, true);
@@ -605,7 +634,7 @@ cc.ControlButton = cc.Control.extend({
locTable[state] = sprite;
sprite.setVisible(false);
- sprite.setAnchorPoint(cc.p(0.5, 0.5));
+ sprite.setAnchorPoint(0.5, 0.5);
this.addChild(sprite);
var locPreferredSize = this._preferredSize;
@@ -624,31 +653,36 @@ cc.ControlButton = cc.Control.extend({
* @param {SpriteFrame} spriteFrame The background spriteFrame to use for the specified state.
* @param {Number} state The state that uses the specified image. The values are described in "CCControlState".
*/
- setBackgroundSpriteFrameForState:function (spriteFrame, state) {
+ setBackgroundSpriteFrameForState: function (spriteFrame, state) {
var sprite = cc.Scale9Sprite.createWithSpriteFrame(spriteFrame);
this.setBackgroundSpriteForState(sprite, state);
}
});
-cc.ControlButton.create = function(label, backgroundSprite) {
- var controlButton;
- if (arguments.length == 0) {
- controlButton = new cc.ControlButton();
- if (controlButton && controlButton.init()) {
- return controlButton;
- }
- return null;
- } else if (arguments.length == 1) {
- controlButton = new cc.ControlButton();
- controlButton.initWithBackgroundSprite(arguments[0]);
- } else if (arguments.length == 2) {
- controlButton = new cc.ControlButton();
- controlButton.initWithLabelAndBackgroundSprite(label, backgroundSprite);
- } else if (arguments.length == 3) {
- controlButton = new cc.ControlButton();
- controlButton.initWithTitleAndFontNameAndFontSize(arguments[0], arguments[1], arguments[2]);
- }
- return controlButton;
+var _p = cc.ControlButton.prototype;
+
+// Extended properties
+/** @expose */
+_p.adjustBackground;
+cc.defineGetterSetter(_p, "adjustBackground", _p.getAdjustBackgroundImage, _p.setAdjustBackgroundImage);
+/** @expose */
+_p.preferredSize;
+cc.defineGetterSetter(_p, "preferredSize", _p.getPreferredSize, _p.setPreferredSize);
+/** @expose */
+_p.labelAnchor;
+cc.defineGetterSetter(_p, "labelAnchor", _p.getLabelAnchorPoint, _p.setLabelAnchorPoint);
+
+_p = null;
+
+/**
+ * @deprecated
+ * @param label
+ * @param backgroundSprite
+ * @param fontSize
+ * @returns {ControlButton}
+ */
+cc.ControlButton.create = function (label, backgroundSprite, fontSize) {
+ return new cc.ControlButton(label, backgroundSprite, fontSize);
};
diff --git a/extensions/GUI/CCControlExtension/CCControlColourPicker.js b/extensions/gui/control-extension/CCControlColourPicker.js
similarity index 71%
rename from extensions/GUI/CCControlExtension/CCControlColourPicker.js
rename to extensions/gui/control-extension/CCControlColourPicker.js
index a456f5eb71..6cdfd6bcc8 100644
--- a/extensions/GUI/CCControlExtension/CCControlColourPicker.js
+++ b/extensions/gui/control-extension/CCControlColourPicker.js
@@ -1,6 +1,8 @@
/**
*
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
*
* Copyright 2012 Stewart Hamilton-Arrandale.
* http://creativewax.co.uk
@@ -24,26 +26,34 @@
* 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.
+ * THE SOFTWARE. *
*
- *
- * converted to Javascript / cocos2d-x by Angus C
*/
-
-cc.ControlColourPicker = cc.Control.extend({
+/**
+ * ControlColourPicker: color picker ui component.
+ * @class
+ * @extends cc.Control
+ *
+ * @property {cc.Sprite} background - <@readonly> The background sprite
+ */
+cc.ControlColourPicker = cc.Control.extend(/** @lends cc.ControlColourPicker# */{
_hsv:null,
_colourPicker:null,
_huePicker:null,
_background:null,
-
+ _className:"ControlColourPicker",
+ ctor:function () {
+ cc.Control.prototype.ctor.call(this);
+ this.init();
+ },
hueSliderValueChanged:function (sender, controlEvent) {
this._hsv.h = sender.getHue();
// Update the value
var rgb = cc.ControlUtils.RGBfromHSV(this._hsv);
- cc.Control.prototype.setColor.call(this,cc.c3(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
+ cc.Control.prototype.setColor.call(this,cc.color(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
// Send CCControl callback
this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
@@ -57,7 +67,7 @@ cc.ControlColourPicker = cc.Control.extend({
// Update the value
var rgb = cc.ControlUtils.RGBfromHSV(this._hsv);
- cc.Control.prototype.setColor.call(this,cc.c3(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
+ cc.Control.prototype.setColor.call(this,cc.color(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
// Send CCControl callback
this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED);
@@ -82,12 +92,11 @@ cc.ControlColourPicker = cc.Control.extend({
init:function () {
if (cc.Control.prototype.init.call(this)) {
- this.setTouchEnabled(true);
// Cache the sprites
- cc.SpriteFrameCache.getInstance().addSpriteFrames("res/extensions/CCControlColourPickerSpriteSheet.plist");
+ cc.spriteFrameCache.addSpriteFrames(res.CCControlColourPickerSpriteSheet_plist);
// Create the sprite batch node
- var spriteSheet = cc.SpriteBatchNode.create("res/extensions/CCControlColourPickerSpriteSheet.png");
+ var spriteSheet = new cc.SpriteBatchNode(res.CCControlColourPickerSpriteSheet_png);
this.addChild(spriteSheet);
/*// MIPMAP
@@ -101,7 +110,7 @@ cc.ControlColourPicker = cc.Control.extend({
this._hsv = new cc.HSV(0, 0, 0);
// Add image
- this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("menuColourPanelBackground.png", spriteSheet, cc.PointZero(), cc.p(0.5, 0.5));
+ this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("menuColourPanelBackground.png", spriteSheet, cc.p(0,0), cc.p(0.5, 0.5));
var backgroundPointZero = cc.pSub(this._background.getPosition(),
cc.p(this._background.getContentSize().width / 2, this._background.getContentSize().height / 2));
@@ -110,8 +119,8 @@ cc.ControlColourPicker = cc.Control.extend({
var hueShift = 8;
var colourShift = 28;
- this._huePicker = cc.ControlHuePicker.create(spriteSheet, cc.p(backgroundPointZero.x + hueShift, backgroundPointZero.y + hueShift));
- this._colourPicker = cc.ControlSaturationBrightnessPicker.create(spriteSheet, cc.p(backgroundPointZero.x + colourShift, backgroundPointZero.y + colourShift));
+ this._huePicker = new cc.ControlHuePicker(spriteSheet, cc.p(backgroundPointZero.x + hueShift, backgroundPointZero.y + hueShift));
+ this._colourPicker = new cc.ControlSaturationBrightnessPicker(spriteSheet, cc.p(backgroundPointZero.x + colourShift, backgroundPointZero.y + colourShift));
// Setup events
this._huePicker.addTargetWithActionForControlEvents(this, this.hueSliderValueChanged, cc.CONTROL_EVENT_VALUECHANGED);
@@ -142,7 +151,7 @@ cc.ControlColourPicker = cc.Control.extend({
},
setEnabled:function (enabled) {
cc.Control.prototype.setEnabled.call(this, enabled);
- if (this._huePicker != null) {
+ if (this._huePicker !== null) {
this._huePicker.setEnabled(enabled);
}
if (this._colourPicker) {
@@ -155,8 +164,24 @@ cc.ControlColourPicker = cc.Control.extend({
}
});
+var _p = cc.ControlColourPicker.prototype;
+
+// Extended properties
+/** @expose */
+_p.background;
+cc.defineGetterSetter(_p, "background", _p.getBackground);
+
+_p = null;
+
+/**
+ * @deprecated
+ * @returns {ControlColourPicker}
+ */
cc.ControlColourPicker.create = function () {
- var pRet = new cc.ControlColourPicker();
- pRet.init();
- return pRet;
-};
\ No newline at end of file
+ return new cc.ControlColourPicker();
+};
+
+// compatible with NPM
+var res = res || {};
+res.CCControlColourPickerSpriteSheet_plist = res.CCControlColourPickerSpriteSheet_plist || "res/extensions/CCControlColourPickerSpriteSheet.plist";
+res.CCControlColourPickerSpriteSheet_png = res.CCControlColourPickerSpriteSheet_png || "res/extensions/CCControlColourPickerSpriteSheet.png";
\ No newline at end of file
diff --git a/extensions/GUI/CCControlExtension/CCControlHuePicker.js b/extensions/gui/control-extension/CCControlHuePicker.js
similarity index 75%
rename from extensions/GUI/CCControlExtension/CCControlHuePicker.js
rename to extensions/gui/control-extension/CCControlHuePicker.js
index 10952b4370..9c002740f4 100644
--- a/extensions/GUI/CCControlExtension/CCControlHuePicker.js
+++ b/extensions/gui/control-extension/CCControlHuePicker.js
@@ -1,6 +1,8 @@
/**
*
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
*
* Copyright 2012 Stewart Hamilton-Arrandale.
* http://creativewax.co.uk
@@ -30,12 +32,34 @@
* converted to Javascript / cocos2d-x by Angus C
*/
-cc.ControlHuePicker = cc.Control.extend({
+/**
+ * ControlHuePicker: HUE picker ui component.
+ * @class
+ * @extends cc.Control
+ *
+ * @property {Number} hue - The hue value
+ * @property {Number} huePercent - The hue value in percentage
+ * @property {cc.Sprite} background - <@readonly> The background sprite
+ * @property {cc.Sprite} slider - <@readonly> The slider sprite
+ * @property {cc.Point} startPos - <@readonly> The start position of the picker
+ */
+cc.ControlHuePicker = cc.Control.extend(/** @lends cc.ControlHuePicker# */{
_hue:0,
_huePercentage:0,
_background:null,
_slider:null,
_startPos:null,
+ _className:"ControlHuePicker",
+
+ /**
+ * The constructor of cc.ControlHuePicker
+ * @param {cc.Node} target
+ * @param {cc.Point} pos position
+ */
+ ctor:function(target, pos) {
+ cc.Control.prototype.ctor.call(this);
+ pos && this.initWithTargetAndPos(target, pos);
+ },
//maunally put in the setters
getHue:function () {
@@ -65,12 +89,12 @@ cc.ControlHuePicker = cc.Control.extend({
// Update angle
var angleDeg = this._huePercentage * 360.0 - 180.0;
- var angle = cc.DEGREES_TO_RADIANS(angleDeg);
+ var angle = cc.degreesToRadians(angleDeg);
// Set new position of the slider
var x = centerX + limit * Math.cos(angle);
var y = centerY + limit * Math.sin(angle);
- this._slider.setPosition(cc.p(x, y));
+ this._slider.setPosition(x, y);
},
setEnabled:function (enabled) {
@@ -92,12 +116,11 @@ cc.ControlHuePicker = cc.Control.extend({
initWithTargetAndPos:function (target, pos) {
if (cc.Control.prototype.init.call(this)) {
- this.setTouchEnabled(true);
// Add background and slider sprites
this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("huePickerBackground.png", target, pos, cc.p(0.0, 0.0));
this._slider = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPicker.png", target, pos, cc.p(0.5, 0.5));
- this._slider.setPosition(cc.p(pos.x, pos.y + this._background.getBoundingBox().height * 0.5));
+ this._slider.setPosition(pos.x, pos.y + this._background.getBoundingBox().height * 0.5);
this._startPos = pos;
// Sets the default value
@@ -122,7 +145,7 @@ cc.ControlHuePicker = cc.Control.extend({
// Update angle by using the direction of the location
var angle = Math.atan2(dy, dx);
- var angleDeg = cc.RADIANS_TO_DEGREES(angle) + 180.0;
+ var angleDeg = cc.radiansToDegrees(angle) + 180.0;
// use the position / slider width to determin the percentage the dragger is at
this.setHue(angleDeg);
@@ -163,8 +186,33 @@ cc.ControlHuePicker = cc.Control.extend({
}
});
+var _p = cc.ControlHuePicker.prototype;
+
+// Extended properties
+/** @expose */
+_p.hue;
+cc.defineGetterSetter(_p, "hue", _p.getHue, _p.setHue);
+/** @expose */
+_p.huePercent;
+cc.defineGetterSetter(_p, "huePercent", _p.getHuePercentage, _p.setHuePercentage);
+/** @expose */
+_p.background;
+cc.defineGetterSetter(_p, "background", _p.getBackground);
+/** @expose */
+_p.slider;
+cc.defineGetterSetter(_p, "slider", _p.getSlider);
+/** @expose */
+_p.startPos;
+cc.defineGetterSetter(_p, "startPos", _p.getStartPos);
+
+_p = null;
+
+/**
+ * @deprecated
+ * @param target
+ * @param pos
+ * @returns {ControlHuePicker}
+ */
cc.ControlHuePicker.create = function (target, pos) {
- var pRet = new cc.ControlHuePicker();
- pRet.initWithTargetAndPos(target, pos);
- return pRet;
+ return new cc.ControlHuePicker(target, pos);
};
\ No newline at end of file
diff --git a/extensions/GUI/CCControlExtension/CCControlPotentiometer.js b/extensions/gui/control-extension/CCControlPotentiometer.js
similarity index 74%
rename from extensions/GUI/CCControlExtension/CCControlPotentiometer.js
rename to extensions/gui/control-extension/CCControlPotentiometer.js
index a7245ef9ec..7c035efd5c 100644
--- a/extensions/GUI/CCControlExtension/CCControlPotentiometer.js
+++ b/extensions/gui/control-extension/CCControlPotentiometer.js
@@ -1,5 +1,8 @@
/**
- * Copyright (c) 2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
+ *
* http://www.cocos2d-x.org
*
* Copyright 2012 Yannick Loriot. All rights reserved.
@@ -26,11 +29,18 @@
*/
/**
- * CCControlPotentiometer Potentiometer control for Cocos2D.
+ * CCControlPotentiometer: Potentiometer control for Cocos2D.
* @class
* @extends cc.Control
+ *
+ * @property {Number} value - The current value of the potentionmeter
+ * @property {Number} minValue - The minimum value of the potentionmeter
+ * @property {Number} maxValue - The maximum value of the potentionmeter
+ * @property {cc.ProgressTimer} progressTimer - The progress timer of the potentionmeter
+ * @property {cc.Sprite} thumbSprite - The thumb sprite of the potentionmeter
+ * @property {cc.Point} prevLocation - The previous location of the potentionmeter
*/
-cc.ControlPotentiometer = cc.Control.extend({
+cc.ControlPotentiometer = cc.Control.extend(/** @lends cc.ControlPotentiometer# */{
_thumbSprite:null,
_progressTimer:null,
_previousLocation:null,
@@ -42,6 +52,22 @@ cc.ControlPotentiometer = cc.Control.extend({
/** Contains the maximum value of the receiver.
* The default value of this property is 1.0. */
_maximumValue:1,
+ _className:"ControlPotentiometer",
+
+ ctor:function (backgroundFile, progressFile, thumbFile) {
+ cc.Control.prototype.ctor.call(this);
+ if (thumbFile != undefined) {
+ // Prepare track for potentiometer
+ var backgroundSprite = new cc.Sprite(backgroundFile);
+
+ // Prepare thumb for potentiometer
+ var thumbSprite = new cc.Sprite(thumbFile);
+
+ // Prepare progress for potentiometer
+ var progressTimer = new cc.ProgressTimer(new cc.Sprite(progressFile));
+ this.initWithTrackSprite_ProgressTimer_ThumbSprite(backgroundSprite, progressTimer, thumbSprite);
+ }
+ },
/**
*
@@ -52,8 +78,6 @@ cc.ControlPotentiometer = cc.Control.extend({
*/
initWithTrackSprite_ProgressTimer_ThumbSprite:function (trackSprite, progressTimer, thumbSprite) {
if (this.init()) {
- this.setTouchEnabled(true);
-
this.setProgressTimer(progressTimer);
this.setThumbSprite(thumbSprite);
this._thumbSprite.setPosition(progressTimer.getPosition());
@@ -75,7 +99,7 @@ cc.ControlPotentiometer = cc.Control.extend({
setEnabled:function (enabled) {
this.setEnabled(enabled);
- if (this._thumbSprite != NULL) {
+ if (this._thumbSprite !== null) {
this._thumbSprite.setOpacity((enabled) ? 255 : 128);
}
},
@@ -197,7 +221,7 @@ cc.ControlPotentiometer = cc.Control.extend({
potentiometerBegan:function (location) {
this.setSelected(true);
- this.getThumbSprite().setColor(cc.GRAY);
+ this.getThumbSprite().setColor(cc.color.GRAY);
},
potentiometerMoved:function (location) {
@@ -217,7 +241,7 @@ cc.ControlPotentiometer = cc.Control.extend({
},
potentiometerEnded:function (location) {
- this.getThumbSprite().setColor(cc.WHITE);
+ this.getThumbSprite().setColor(cc.color.WHITE);
this.setSelected(false);
},
setThumbSprite:function (sprite) {
@@ -240,20 +264,37 @@ cc.ControlPotentiometer = cc.Control.extend({
}
});
+var _p = cc.ControlPotentiometer.prototype;
+
+// Extended properties
+/** @expose */
+_p.value;
+cc.defineGetterSetter(_p, "value", _p.getValue, _p.setValue);
+/** @expose */
+_p.minValue;
+cc.defineGetterSetter(_p, "minValue", _p.getMinimumValue, _p.setMinimumValue);
+/** @expose */
+_p.maxValue;
+cc.defineGetterSetter(_p, "maxValue", _p.getMaximumValue, _p.setMaximumValue);
+/** @expose */
+_p.progressTimer;
+cc.defineGetterSetter(_p, "progressTimer", _p.getProgressTimer, _p.setProgressTimer);
+/** @expose */
+_p.thumbSprite;
+cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite, _p.setThumbSprite);
+/** @expose */
+_p.prevLocation;
+cc.defineGetterSetter(_p, "prevLocation", _p.getPreviousLocation, _p.setPreviousLocation);
+
+_p = null;
+
+/**
+ * @deprecated
+ * @param backgroundFile
+ * @param progressFile
+ * @param thumbFile
+ * @returns {ControlPotentiometer}
+ */
cc.ControlPotentiometer.create = function (backgroundFile, progressFile, thumbFile) {
- var pRet = new cc.ControlPotentiometer();
- if (pRet) {
- // Prepare track for potentiometer
- var backgroundSprite = cc.Sprite.create(backgroundFile);
-
- // Prepare thumb for potentiometer
- var thumbSprite = cc.Sprite.create(thumbFile);
-
- // Prepare progress for potentiometer
- var progressTimer = cc.ProgressTimer.create(cc.Sprite.create(progressFile));
- if (pRet.initWithTrackSprite_ProgressTimer_ThumbSprite(backgroundSprite, progressTimer, thumbSprite)) {
- return pRet;
- }
- }
- return null;
+ return new cc.ControlPotentiometer(backgroundFile, progressFile, thumbFile);
};
\ No newline at end of file
diff --git a/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js b/extensions/gui/control-extension/CCControlSaturationBrightnessPicker.js
similarity index 77%
rename from extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js
rename to extensions/gui/control-extension/CCControlSaturationBrightnessPicker.js
index c6ceb37226..a9045c43d0 100644
--- a/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js
+++ b/extensions/gui/control-extension/CCControlSaturationBrightnessPicker.js
@@ -1,6 +1,8 @@
/**
*
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
*
* Copyright 2012 Stewart Hamilton-Arrandale.
* http://creativewax.co.uk
@@ -30,7 +32,20 @@
* converted to Javascript / cocos2d-x by Angus C
*/
-cc.ControlSaturationBrightnessPicker = cc.Control.extend({
+/**
+ * ControlSaturationBrightnessPicker: Saturation brightness picker ui component.
+ * @class
+ * @extends cc.Control
+ *
+ * @property {Number} saturation - <@readonly> Saturation value of the picker
+ * @property {Number} brightness - <@readonly> Brightness value of the picker
+ * @property {cc.Sprite} background - <@readonly> The background sprite
+ * @property {cc.Sprite} overlay - <@readonly> The overlay sprite
+ * @property {cc.Sprite} shadow - <@readonly> The shadow sprite
+ * @property {cc.Sprite} slider - <@readonly> The slider sprite
+ * @property {cc.Point} startPos - <@readonly> The start position of the picker
+ */
+cc.ControlSaturationBrightnessPicker = cc.Control.extend(/** @lends cc.ControlSaturationBrightnessPicker# */{
_saturation:0,
_brightness:0,
@@ -42,7 +57,17 @@ cc.ControlSaturationBrightnessPicker = cc.Control.extend({
_boxPos:0,
_boxSize:0,
+ _className:"ControlSaturationBrightnessPicker",
+ /**
+ * The constructor of cc.ControlSaturationBrightnessPicker
+ * @param {cc.Node} target
+ * @param {cc.Point} pos position
+ */
+ ctor:function (target, pos) {
+ cc.Control.prototype.ctor.call(this);
+ pos && this.initWithTargetAndPos(target, pos);
+ },
getSaturation:function () {
return this._saturation;
},
@@ -69,7 +94,6 @@ cc.ControlSaturationBrightnessPicker = cc.Control.extend({
initWithTargetAndPos:function (target, pos) {
if (cc.Control.prototype.init.call(this)) {
- this.setTouchEnabled(true);
// Add background and slider sprites
this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPickerBackground.png", target, pos, cc.p(0.0, 0.0));
this._overlay = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("colourPickerOverlay.png", target, pos, cc.p(0.0, 0.0));
@@ -98,7 +122,7 @@ cc.ControlSaturationBrightnessPicker = cc.Control.extend({
hsvTemp.v = 1;
var rgb = cc.ControlUtils.RGBfromHSV(hsvTemp);
- this._background.setColor(cc.c3(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
+ this._background.setColor(cc.color(0 | (rgb.r * 255), 0 | (rgb.g * 255), 0 | (rgb.b * 255)));
},
updateDraggerWithHSV:function (hsv) {
// Set the position of the slider to the correct saturation and brightness
@@ -195,8 +219,39 @@ cc.ControlSaturationBrightnessPicker = cc.Control.extend({
}
});
+var _p = cc.ControlSaturationBrightnessPicker.prototype;
+
+// Extended properties
+/** @expose */
+_p.saturation;
+cc.defineGetterSetter(_p, "saturation", _p.getSaturation);
+/** @expose */
+_p.brightness;
+cc.defineGetterSetter(_p, "brightness", _p.getBrightness);
+/** @expose */
+_p.background;
+cc.defineGetterSetter(_p, "background", _p.getBackground);
+/** @expose */
+_p.overlay;
+cc.defineGetterSetter(_p, "overlay", _p.getOverlay);
+/** @expose */
+_p.shadow;
+cc.defineGetterSetter(_p, "shadow", _p.getShadow);
+/** @expose */
+_p.slider;
+cc.defineGetterSetter(_p, "slider", _p.getSlider);
+/** @expose */
+_p.startPos;
+cc.defineGetterSetter(_p, "startPos", _p.getStartPos);
+
+_p = null;
+
+/**
+ * Creates a cc.ControlSaturationBrightnessPicker
+ * @param {cc.Node} target
+ * @param {cc.Point} pos position
+ * @returns {ControlSaturationBrightnessPicker}
+ */
cc.ControlSaturationBrightnessPicker.create = function (target, pos) {
- var pRet = new cc.ControlSaturationBrightnessPicker();
- pRet.initWithTargetAndPos(target, pos);
- return pRet;
+ return new cc.ControlSaturationBrightnessPicker(target, pos);
};
\ No newline at end of file
diff --git a/extensions/GUI/CCControlExtension/CCControlSlider.js b/extensions/gui/control-extension/CCControlSlider.js
similarity index 68%
rename from extensions/GUI/CCControlExtension/CCControlSlider.js
rename to extensions/gui/control-extension/CCControlSlider.js
index 33b47b644b..e4a757b3c8 100644
--- a/extensions/GUI/CCControlExtension/CCControlSlider.js
+++ b/extensions/gui/control-extension/CCControlSlider.js
@@ -1,6 +1,8 @@
/**
*
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
*
* Copyright 2011 Yannick Loriot. All rights reserved.
* http://yannickloriot.com
@@ -27,10 +29,27 @@
* converted to Javascript / cocos2d-x by Angus C
*/
+/**
+ * @ignore
+ */
cc.SLIDER_MARGIN_H = 24;
cc.SLIDER_MARGIN_V = 8;
-cc.ControlSlider = cc.Control.extend({
+/**
+ * ControlSlider: Slider ui component.
+ * @class
+ * @extends cc.Control
+ *
+ * @property {Number} value - The value of the slider
+ * @property {Number} minValue - The minimum value of the slider
+ * @property {Number} maxValue - The maximum value of the slider
+ * @property {Number} minAllowedValue - The minimum allowed value of the slider
+ * @property {Number} maxAllowedValue - The maximum allowed value of the slider
+ * @property {Number} thumbSprite - <@readonly> Brightness value of the picker
+ * @property {cc.Sprite} progressSprite - <@readonly> The background sprite
+ * @property {cc.Sprite} backgroundSprite - <@readonly> The overlay sprite
+ */
+cc.ControlSlider = cc.Control.extend(/** @lends cc.ControlSlider# */{
_value:0,
_minimumValue:0,
_maximumValue:0,
@@ -40,6 +59,23 @@ cc.ControlSlider = cc.Control.extend({
_thumbSprite:null,
_progressSprite:null,
_backgroundSprite:null,
+ _className:"ControlSlider",
+
+ ctor:function (bgFile, progressFile, thumbFile) {
+ cc.Control.prototype.ctor.call(this);
+ if (thumbFile != undefined) {
+ // Prepare background for slider
+ var bgSprite = new cc.Sprite(bgFile);
+
+ // Prepare progress for slider
+ var progressSprite = new cc.Sprite(progressFile);
+
+ // Prepare thumb (menuItem) for slider
+ var thumbSprite = new cc.Sprite(thumbFile);
+
+ this.initWithSprites(bgSprite, progressSprite, thumbSprite);
+ }
+ },
getValue:function () {
return this._value;
@@ -79,8 +115,8 @@ cc.ControlSlider = cc.Control.extend({
touchLocation = this.getParent().convertToNodeSpace(touchLocation);
var rect = this.getBoundingBox();
- rect.size.width += this._thumbSprite.getContentSize().width;
- rect.origin.x -= this._thumbSprite.getContentSize().width / 2;
+ rect.width += this._thumbSprite.getContentSize().width;
+ rect.x -= this._thumbSprite.getContentSize().width / 2;
return cc.rectContainsPoint(rect, touchLocation);
},
@@ -132,7 +168,6 @@ cc.ControlSlider = cc.Control.extend({
initWithSprites:function (backgroundSprite, progressSprite, thumbSprite) {
if (cc.Control.prototype.init.call(this)) {
this.ignoreAnchorPointForPosition(false);
- this.setTouchEnabled(true);
this._backgroundSprite = backgroundSprite;
this._progressSprite = progressSprite;
@@ -140,21 +175,20 @@ cc.ControlSlider = cc.Control.extend({
// Defines the content size
var maxRect = cc.ControlUtils.CCRectUnion(backgroundSprite.getBoundingBox(), thumbSprite.getBoundingBox());
- var size = cc.size(maxRect.width, maxRect.height);
- this.setContentSize(size);
+ this.setContentSize(maxRect.width, maxRect.height);
// Add the slider background
- this._backgroundSprite.setAnchorPoint(cc.p(0.5, 0.5));
- this._backgroundSprite.setPosition(cc.p(size.width / 2, size.height / 2));
+ this._backgroundSprite.setAnchorPoint(0.5, 0.5);
+ this._backgroundSprite.setPosition(maxRect.width / 2, maxRect.height / 2);
this.addChild(this._backgroundSprite);
// Add the progress bar
- this._progressSprite.setAnchorPoint(cc.p(0.0, 0.5));
- this._progressSprite.setPosition(cc.p(0.0, size.height / 2));
+ this._progressSprite.setAnchorPoint(0.0, 0.5);
+ this._progressSprite.setPosition(0, maxRect.height / 2);
this.addChild(this._progressSprite);
// Add the slider thumb
- this._thumbSprite.setPosition(cc.p(0, size.height / 2));
+ this._thumbSprite.setPosition(0, maxRect.height / 2);
this.addChild(this._thumbSprite);
// Init default values
@@ -175,7 +209,7 @@ cc.ControlSlider = cc.Control.extend({
sliderBegan:function (location) {
this.setSelected(true);
- this.getThumbSprite().setColor(cc.GRAY);
+ this._thumbSprite.setColor(cc.color.GRAY);
this.setValue(this.valueForLocation(location));
},
sliderMoved:function (location) {
@@ -185,7 +219,7 @@ cc.ControlSlider = cc.Control.extend({
if (this.isSelected()) {
this.setValue(this.valueForLocation(this._thumbSprite.getPosition()));
}
- this._thumbSprite.setColor(cc.WHITE);
+ this._thumbSprite.setColor(cc.color.WHITE);
this.setSelected(false);
},
@@ -214,18 +248,17 @@ cc.ControlSlider = cc.Control.extend({
this.sliderMoved(location);
},
onTouchEnded:function (touch, event) {
- this.sliderEnded(cc.PointZero());
+ this.sliderEnded(cc.p(0,0));
},
needsLayout:function(){
var percent = (this._value - this._minimumValue) / (this._maximumValue - this._minimumValue);
- var pos = this._thumbSprite.getPosition();
- pos.x = percent * this._backgroundSprite.getContentSize().width;
- this._thumbSprite.setPosition(pos);
+ this._thumbSprite.setPositionX(percent * this._backgroundSprite.getContentSize().width);
// Stretches content proportional to newLevel
var textureRect = this._progressSprite.getTextureRect();
- textureRect = cc.rect(textureRect.x, textureRect.y, pos.x, textureRect.height);
- this._progressSprite.setTextureRect(textureRect, this._progressSprite.isTextureRectRotated(), textureRect.size);
+ textureRect = cc.rect(textureRect.x, textureRect.y, this._thumbSprite.getPositionX(), textureRect.height);
+ this._progressSprite.setTextureRect(textureRect, this._progressSprite.isTextureRectRotated());
+ this._thumbSprite._renderCmd.transform(this._renderCmd);
},
/** Returns the value for the given location. */
valueForLocation:function (location) {
@@ -234,27 +267,42 @@ cc.ControlSlider = cc.Control.extend({
}
});
+var _p = cc.ControlSlider.prototype;
+
+// Extended properties
+/** @expose */
+_p.value;
+cc.defineGetterSetter(_p, "value", _p.getValue, _p.setValue);
+/** @expose */
+_p.minValue;
+cc.defineGetterSetter(_p, "minValue", _p.getMinimumValue, _p.setMinimumValue);
+/** @expose */
+_p.maxValue;
+cc.defineGetterSetter(_p, "maxValue", _p.getMaximumValue, _p.setMaximumValue);
+/** @expose */
+_p.minAllowedValue;
+cc.defineGetterSetter(_p, "minAllowedValue", _p.getMinimumAllowedValue, _p.setMinimumAllowedValue);
+/** @expose */
+_p.maxAllowedValue;
+cc.defineGetterSetter(_p, "maxAllowedValue", _p.getMaximumAllowedValue, _p.setMaximumAllowedValue);
+/** @expose */
+_p.thumbSprite;
+cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite);
+/** @expose */
+_p.progressSprite;
+cc.defineGetterSetter(_p, "progressSprite", _p.getProgressSprite);
+/** @expose */
+_p.backgroundSprite;
+cc.defineGetterSetter(_p, "backgroundSprite", _p.getBackgroundSprite);
+
+_p = null;
/**
* Creates a slider with a given background sprite and a progress bar and a
* thumb item.
- *
- * @see initWithBackgroundSprite:progressSprite:thumbMenuItem:
+ * @deprecated
+ * @see cc.ControlSlider
*/
cc.ControlSlider.create = function (bgFile, progressFile, thumbFile) {
- if (typeof(bgFile) == "string") {
- // Prepare background for slider
- bgFile = cc.Sprite.create(bgFile);
-
- // Prepare progress for slider
- progressFile = cc.Sprite.create(progressFile);
-
- // Prepare thumb (menuItem) for slider
- thumbFile = cc.Sprite.create(thumbFile);
- }
-
- var pRet = new cc.ControlSlider();
- pRet.initWithSprites(bgFile, progressFile, thumbFile);
- return pRet;
-
+ return new cc.ControlSlider(bgFile, progressFile, thumbFile);
};
\ No newline at end of file
diff --git a/extensions/GUI/CCControlExtension/CCControlStepper.js b/extensions/gui/control-extension/CCControlStepper.js
similarity index 59%
rename from extensions/GUI/CCControlExtension/CCControlStepper.js
rename to extensions/gui/control-extension/CCControlStepper.js
index e0985fe77b..6ac29fb3c1 100644
--- a/extensions/GUI/CCControlExtension/CCControlStepper.js
+++ b/extensions/gui/control-extension/CCControlStepper.js
@@ -1,5 +1,8 @@
/**
- * Copyright (c) 2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
+ *
* http://www.cocos2d-x.org
*
* Copyright 2012 Yannick Loriot. All rights reserved.
@@ -25,21 +28,35 @@
*
*/
+/**
+ * @ignore
+ */
cc.CONTROL_STEPPER_PARTMINUS = 0;
cc.CONTROL_STEPPER_PARTPLUS = 1;
cc.CONTROL_STEPPER_PARTNONE = 2;
-cc.CONTROL_STEPPER_LABELCOLOR_ENABLED = cc.c3b(55, 55, 55);
-cc.CONTROL_STEPPER_LABELCOLOR_DISABLED = cc.c3b(147, 147, 147);
+cc.CONTROL_STEPPER_LABELCOLOR_ENABLED = cc.color(55, 55, 55);
+cc.CONTROL_STEPPER_LABELCOLOR_DISABLED = cc.color(147, 147, 147);
cc.CONTROL_STEPPER_LABELFONT = "CourierNewPSMT";
cc.AUTOREPEAT_DELTATIME = 0.15;
cc.AUTOREPEAT_INCREASETIME_INCREMENT = 12;
/**
- * ControlStepper control for Cocos2D.
+ * ControlStepper: Stepper ui component.
* @class
* @extends cc.Control
+ *
+ * @property {Boolean} wraps - Indicate whether the stepper wraps
+ * @property {Number} value - The value of the stepper control
+ * @property {Number} minValue - The minimum value of the stepper control
+ * @property {Number} maxValue - The maximum value of the stepper control
+ * @property {Number} stepValue - The interval value for each step of the stepper control
+ * @property {Boolean} continuous - <@readonly> Indicate whether the stepper value is continuous
+ * @property {cc.Sprite} minusSprite - The sprite for minus button of the stepper control
+ * @property {cc.Sprite} plusSprite - The sprite for plus button of the stepper control
+ * @property {cc.LabelTTF} minusLabel - The label for minus button of the stepper control
+ * @property {cc.LabelTTF} plusSLabel - The label for plus button of the stepper control
*/
-cc.ControlStepper = cc.Control.extend({
+cc.ControlStepper = cc.Control.extend(/** @lends cc.ControlStepper# */{
_minusSprite:null,
_plusSprite:null,
_minusLabel:null,
@@ -54,7 +71,8 @@ cc.ControlStepper = cc.Control.extend({
_touchInsideFlag:false,
_touchedPart:cc.CONTROL_STEPPER_PARTNONE,
_autorepeatCount:0,
- ctor:function () {
+ _className:"ControlStepper",
+ ctor:function (minusSprite, plusSprite) {
cc.Control.prototype.ctor.call(this);
this._minusSprite = null;
this._plusSprite = null;
@@ -70,15 +88,18 @@ cc.ControlStepper = cc.Control.extend({
this._touchInsideFlag = false;
this._touchedPart = cc.CONTROL_STEPPER_PARTNONE;
this._autorepeatCount = 0;
+
+ plusSprite && this.initWithMinusSpriteAndPlusSprite(minusSprite, plusSprite);
+
},
initWithMinusSpriteAndPlusSprite:function (minusSprite, plusSprite) {
- if (this.init()) {
- cc.Assert(minusSprite, "Minus sprite must be not nil");
- cc.Assert(plusSprite, "Plus sprite must be not nil");
-
- this.setTouchEnabled(true);
+ if(!minusSprite)
+ throw new Error("cc.ControlStepper.initWithMinusSpriteAndPlusSprite(): Minus sprite should be non-null.");
+ if(!plusSprite)
+ throw new Error("cc.ControlStepper.initWithMinusSpriteAndPlusSprite(): Plus sprite should be non-null.");
+ if (this.init()) {
// Set the default values
this._autorepeat = true;
this._continuous = true;
@@ -91,28 +112,28 @@ cc.ControlStepper = cc.Control.extend({
// Add the minus components
this.setMinusSprite(minusSprite);
- this._minusSprite.setPosition(cc.p(minusSprite.getContentSize().width / 2, minusSprite.getContentSize().height / 2));
+ this._minusSprite.setPosition(minusSprite.getContentSize().width / 2, minusSprite.getContentSize().height / 2);
this.addChild(this._minusSprite);
- this.setMinusLabel(cc.LabelTTF.create("-", cc.CONTROL_STEPPER_LABELFONT, 40, cc.size(40, 40), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER));
+ this.setMinusLabel(new cc.LabelTTF("-", cc.CONTROL_STEPPER_LABELFONT, 40, cc.size(40, 40), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER));
this._minusLabel.setColor(cc.CONTROL_STEPPER_LABELCOLOR_DISABLED);
- this._minusLabel.setPosition(cc.p(this._minusSprite.getContentSize().width / 2, this._minusSprite.getContentSize().height / 2));
+ this._minusLabel.setPosition(this._minusSprite.getContentSize().width / 2, this._minusSprite.getContentSize().height / 2);
this._minusSprite.addChild(this._minusLabel);
// Add the plus components
this.setPlusSprite(plusSprite);
- this._plusSprite.setPosition(cc.p(minusSprite.getContentSize().width + plusSprite.getContentSize().width / 2,
- minusSprite.getContentSize().height / 2));
+ this._plusSprite.setPosition(minusSprite.getContentSize().width + plusSprite.getContentSize().width / 2,
+ minusSprite.getContentSize().height / 2);
this.addChild(this._plusSprite);
- this.setPlusLabel(cc.LabelTTF.create("+", cc.CONTROL_STEPPER_LABELFONT, 40, cc.size(40, 40), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER));
+ this.setPlusLabel(new cc.LabelTTF("+", cc.CONTROL_STEPPER_LABELFONT, 40, cc.size(40, 40), cc.TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_CENTER));
this._plusLabel.setColor(cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
- this._plusLabel.setPosition(cc.p(this._plusSprite.getContentSize().width / 2, this._plusSprite.getContentSize().height / 2));
+ this._plusLabel.setPosition(this._plusSprite.getContentSize().width / 2, this._plusSprite.getContentSize().height / 2);
this._plusSprite.addChild(this._plusLabel);
// Defines the content size
var maxRect = cc.ControlUtils.CCRectUnion(this._minusSprite.getBoundingBox(), this._plusSprite.getBoundingBox());
- this.setContentSize(cc.size(this._minusSprite.getContentSize().width + this._plusSprite.getContentSize().height, maxRect.size.height));
+ this.setContentSize(this._minusSprite.getContentSize().width + this._plusSprite.getContentSize().height, maxRect.height);
return true;
}
return false;
@@ -120,7 +141,7 @@ cc.ControlStepper = cc.Control.extend({
//#pragma mark Properties
- setWraps:function (wraps) {
+ setWraps: function (wraps) {
this._wraps = wraps;
if (this._wraps) {
@@ -131,23 +152,31 @@ cc.ControlStepper = cc.Control.extend({
this.setValue(this._value);
},
+ getWraps: function () {
+ return this._wraps;
+ },
+
setMinimumValue:function (minimumValue) {
- if (minimumValue >= this._maximumValue) {
- cc.Assert(0, "Must be numerically less than maximumValue.");
- }
+ if (minimumValue >= this._maximumValue)
+ throw new Error("cc.ControlStepper.setMinimumValue(): minimumValue should be numerically less than maximumValue.");
this._minimumValue = minimumValue;
this.setValue(this._value);
},
+ getMinimumValue: function () {
+ return this._minimumValue;
+ },
setMaximumValue:function (maximumValue) {
- if (maximumValue <= this._minimumValue) {
- cc.Assert(0, "Must be numerically greater than minimumValue.");
- }
+ if (maximumValue <= this._minimumValue)
+ throw new Error("cc.ControlStepper.setMaximumValue(): maximumValue should be numerically less than maximumValue.");
this._maximumValue = maximumValue;
this.setValue(this._value);
},
+ getMaximumValue: function () {
+ return this._maximumValue;
+ },
setValue:function (value) {
this.setValueWithSendingEvent(value, true);
@@ -158,13 +187,15 @@ cc.ControlStepper = cc.Control.extend({
},
setStepValue:function (stepValue) {
- if (stepValue <= 0) {
- cc.Assert(0, "Must be numerically greater than 0.");
- }
-
+ if (stepValue <= 0)
+ throw new Error("cc.ControlStepper.setMaximumValue(): stepValue should be numerically greater than 0.");
this._stepValue = stepValue;
},
+ getStepValue:function () {
+ return this._stepValue;
+ },
+
isContinuous:function () {
return this._continuous;
},
@@ -179,8 +210,8 @@ cc.ControlStepper = cc.Control.extend({
this._value = value;
if (!this._wraps) {
- this._minusLabel.setColor((value == this._minimumValue) ? cc.CONTROL_STEPPER_LABELCOLOR_DISABLED : cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
- this._plusLabel.setColor((value == this._maximumValue) ? cc.CONTROL_STEPPER_LABELCOLOR_DISABLED : cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
+ this._minusLabel.setColor((value === this._minimumValue) ? cc.CONTROL_STEPPER_LABELCOLOR_DISABLED : cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
+ this._plusLabel.setColor((value === this._maximumValue) ? cc.CONTROL_STEPPER_LABELCOLOR_DISABLED : cc.CONTROL_STEPPER_LABELCOLOR_ENABLED);
}
if (send) {
@@ -201,12 +232,12 @@ cc.ControlStepper = cc.Control.extend({
update:function (dt) {
this._autorepeatCount++;
- if ((this._autorepeatCount < cc.AUTOREPEAT_INCREASETIME_INCREMENT) && (this._autorepeatCount % 3) != 0)
+ if ((this._autorepeatCount < cc.AUTOREPEAT_INCREASETIME_INCREMENT) && (this._autorepeatCount % 3) !== 0)
return;
- if (this._touchedPart == cc.CONTROL_STEPPER_PARTMINUS) {
+ if (this._touchedPart === cc.CONTROL_STEPPER_PARTMINUS) {
this.setValueWithSendingEvent(this._value - this._stepValue, this._continuous);
- } else if (this._touchedPart == cc.CONTROL_STEPPER_PARTPLUS) {
+ } else if (this._touchedPart === cc.CONTROL_STEPPER_PARTPLUS) {
this.setValueWithSendingEvent(this._value + this._stepValue, this._continuous);
}
},
@@ -217,19 +248,19 @@ cc.ControlStepper = cc.Control.extend({
if (location.x < this._minusSprite.getContentSize().width
&& this._value > this._minimumValue) {
this._touchedPart = cc.CONTROL_STEPPER_PARTMINUS;
- this._minusSprite.setColor(cc.GRAY);
- this._plusSprite.setColor(cc.WHITE);
+ this._minusSprite.setColor(cc.color.GRAY);
+ this._plusSprite.setColor(cc.color.WHITE);
} else if (location.x >= this._minusSprite.getContentSize().width
&& this._value < this._maximumValue) {
this._touchedPart = cc.CONTROL_STEPPER_PARTPLUS;
- this._minusSprite.setColor(cc.WHITE);
- this._plusSprite.setColor(cc.GRAY);
+ this._minusSprite.setColor(cc.color.WHITE);
+ this._plusSprite.setColor(cc.color.GRAY);
} else {
this._touchedPart = cc.CONTROL_STEPPER_PARTNONE;
- this._minusSprite.setColor(cc.WHITE);
- this._plusSprite.setColor(cc.WHITE);
+ this._minusSprite.setColor(cc.color.WHITE);
+ this._plusSprite.setColor(cc.color.WHITE);
}
},
@@ -265,8 +296,8 @@ cc.ControlStepper = cc.Control.extend({
} else {
this._touchInsideFlag = false;
this._touchedPart = cc.CONTROL_STEPPER_PARTNONE;
- this._minusSprite.setColor(cc.WHITE);
- this._plusSprite.setColor(cc.WHITE);
+ this._minusSprite.setColor(cc.color.WHITE);
+ this._plusSprite.setColor(cc.color.WHITE);
if (this._autorepeat) {
this.stopAutorepeat();
}
@@ -274,8 +305,8 @@ cc.ControlStepper = cc.Control.extend({
},
onTouchEnded:function (touch, event) {
- this._minusSprite.setColor(cc.WHITE);
- this._plusSprite.setColor(cc.WHITE);
+ this._minusSprite.setColor(cc.color.WHITE);
+ this._plusSprite.setColor(cc.color.WHITE);
if (this._autorepeat) {
this.stopAutorepeat();
@@ -312,10 +343,48 @@ cc.ControlStepper = cc.Control.extend({
}
});
+var _p = cc.ControlStepper.prototype;
+
+// Extedned properties
+/** @expose */
+_p.wraps;
+cc.defineGetterSetter(_p, "wraps", _p.getWraps, _p.setWraps);
+/** @expose */
+_p.value;
+cc.defineGetterSetter(_p, "value", _p.getValue, _p.setValue);
+/** @expose */
+_p.minValue;
+cc.defineGetterSetter(_p, "minValue", _p.getMinimumValue, _p.setMinimumValue);
+/** @expose */
+_p.maxValue;
+cc.defineGetterSetter(_p, "maxValue", _p.getMaximumValue, _p.setMaximumValue);
+/** @expose */
+_p.stepValue;
+cc.defineGetterSetter(_p, "stepValue", _p.getStepValue, _p.setStepValue);
+/** @expose */
+_p.continuous;
+cc.defineGetterSetter(_p, "continuous", _p.isContinuous);
+/** @expose */
+_p.minusSprite;
+cc.defineGetterSetter(_p, "minusSprite", _p.getMinusSprite, _p.setMinusSprite);
+/** @expose */
+_p.plusSprite;
+cc.defineGetterSetter(_p, "plusSprite", _p.getPlusSprite, _p.setPlusSprite);
+/** @expose */
+_p.minusLabel;
+cc.defineGetterSetter(_p, "minusLabel", _p.getMinusLabel, _p.setMinusLabel);
+/** @expose */
+_p.plusLabel;
+cc.defineGetterSetter(_p, "plusLabel", _p.getPlusLabel, _p.setPlusLabel);
+
+_p = null;
+
+/**
+ * Creates a cc.ControlStepper
+ * @param {cc.Sprite} minusSprite
+ * @param {cc.Sprite} plusSprite
+ * @returns {ControlStepper}
+ */
cc.ControlStepper.create = function (minusSprite, plusSprite) {
- var pRet = new cc.ControlStepper();
- if (pRet && pRet.initWithMinusSpriteAndPlusSprite(minusSprite, plusSprite)) {
- return pRet;
- }
- return null;
+ return new cc.ControlStepper(minusSprite, plusSprite);
};
\ No newline at end of file
diff --git a/extensions/GUI/CCControlExtension/CCControlSwitch.js b/extensions/gui/control-extension/CCControlSwitch.js
similarity index 56%
rename from extensions/GUI/CCControlExtension/CCControlSwitch.js
rename to extensions/gui/control-extension/CCControlSwitch.js
index 5b52a2ba48..99b73684b1 100644
--- a/extensions/GUI/CCControlExtension/CCControlSwitch.js
+++ b/extensions/gui/control-extension/CCControlSwitch.js
@@ -1,6 +1,8 @@
/**
*
- * Copyright (c) 2010-2012 cocos2d-x.org
+ * Copyright (c) 2008-2010 Ricardo Quesada
+ * Copyright (c) 2011-2012 cocos2d-x.org
+ * Copyright (c) 2013-2014 Chukong Technologies Inc.
*
* Copyright 2011 Yannick Loriot. All rights reserved.
* http://yannickloriot.com
@@ -24,8 +26,12 @@
* THE SOFTWARE.
*/
-/** @class CCControlSwitch Switch control for Cocos2D. */
-cc.ControlSwitch = cc.Control.extend({
+/**
+ * CCControlSwitch: Switch control ui component
+ * @class
+ * @extends cc.Control
+ */
+cc.ControlSwitch = cc.Control.extend(/** @lends cc.ControlSwitch# */{
/** Sprite which represents the view. */
_switchSprite:null,
_initialTouchXPosition:0,
@@ -33,29 +39,33 @@ cc.ControlSwitch = cc.Control.extend({
_moved:false,
/** A Boolean value that determines the off/on state of the switch. */
_on:false,
-
- ctor:function () {
+ _className:"ControlSwitch",
+ ctor:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
cc.Control.prototype.ctor.call(this);
+
+ offLabel && this.initWithMaskSprite(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel);
},
/** Creates a switch with a mask sprite, on/off sprites for on/off states, a thumb sprite and an on/off labels. */
initWithMaskSprite:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
+ if(!maskSprite)
+ throw new Error("cc.ControlSwitch.initWithMaskSprite(): maskSprite should be non-null.");
+ if(!onSprite)
+ throw new Error("cc.ControlSwitch.initWithMaskSprite(): onSprite should be non-null.");
+ if(!offSprite)
+ throw new Error("cc.ControlSwitch.initWithMaskSprite(): offSprite should be non-null.");
+ if(!thumbSprite)
+ throw new Error("cc.ControlSwitch.initWithMaskSprite(): thumbSprite should be non-null.");
if (this.init()) {
- cc.Assert(maskSprite, "Mask must not be nil.");
- cc.Assert(onSprite, "onSprite must not be nil.");
- cc.Assert(offSprite, "offSprite must not be nil.");
- cc.Assert(thumbSprite, "thumbSprite must not be nil.");
-
- this.setTouchEnabled(true);
this._on = true;
this._switchSprite = new cc.ControlSwitchSprite();
this._switchSprite.initWithMaskSprite(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel);
- this._switchSprite.setPosition(cc.p(this._switchSprite.getContentSize().width / 2, this._switchSprite.getContentSize().height / 2));
+ this._switchSprite.setPosition(this._switchSprite.getContentSize().width / 2, this._switchSprite.getContentSize().height / 2);
this.addChild(this._switchSprite);
this.ignoreAnchorPointForPosition(false);
- this.setAnchorPoint(cc.p(0.5, 0.5));
+ this.setAnchorPoint(0.5, 0.5);
this.setContentSize(this._switchSprite.getContentSize());
return true;
}
@@ -67,7 +77,7 @@ cc.ControlSwitch = cc.Control.extend({
this._on = isOn;
var xPosition = (this._on) ? this._switchSprite.getOnPosition() : this._switchSprite.getOffPosition();
if(animated){
- this._switchSprite.runAction(cc.ActionTween.create(0.2, "sliderXPosition", this._switchSprite.getSliderXPosition(),xPosition));
+ this._switchSprite.runAction(new cc.ActionTween(0.2, "sliderXPosition", this._switchSprite.getSliderXPosition(),xPosition));
}else{
this._switchSprite.setSliderXPosition(xPosition);
}
@@ -106,7 +116,7 @@ cc.ControlSwitch = cc.Control.extend({
this._initialTouchXPosition = location.x - this._switchSprite.getSliderXPosition();
- this._switchSprite.getThumbSprite().setColor(cc.gray());
+ this._switchSprite.getThumbSprite().setColor(cc.color.GRAY);
this._switchSprite.needsLayout();
return true;
@@ -124,7 +134,7 @@ cc.ControlSwitch = cc.Control.extend({
onTouchEnded:function (touch, event) {
var location = this.locationFromTouch(touch);
- this._switchSprite.getThumbSprite().setColor(cc.white());
+ this._switchSprite.getThumbSprite().setColor(cc.color.WHITE);
if (this.hasMoved()) {
this.setOn(!(location.x < this._switchSprite.getContentSize().width / 2), true);
@@ -136,7 +146,7 @@ cc.ControlSwitch = cc.Control.extend({
onTouchCancelled:function (touch, event) {
var location = this.locationFromTouch(touch);
- this._switchSprite.getThumbSprite().setColor(cc.white());
+ this._switchSprite.getThumbSprite().setColor(cc.color.WHITE);
if (this.hasMoved()) {
this.setOn(!(location.x < this._switchSprite.getContentSize().width / 2), true);
@@ -146,38 +156,57 @@ cc.ControlSwitch = cc.Control.extend({
}
});
-/** Creates a switch with a mask sprite, on/off sprites for on/off states and a thumb sprite. */
+/** Creates a switch with a mask sprite, on/off sprites for on/off states and a thumb sprite.
+ * @deprecated
+ */
cc.ControlSwitch.create = function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
- var pRet = new cc.ControlSwitch();
- if (pRet && pRet.initWithMaskSprite(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel)) {
- return pRet;
- }
- return null;
+ return new cc.ControlSwitch(maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel);
};
+/**
+ * ControlSwitchSprite: Sprite switch control ui component
+ * @class
+ * @extends cc.Sprite
+ *
+ * @property {Number} sliderX - Slider's x position
+ * @property {cc.Point} onPos - The position of slider when switch is on
+ * @property {cc.Point} offPos - The position of slider when switch is off
+ * @property {cc.Texture2D} maskTexture - The texture of the mask
+ * @property {cc.Point} texturePos - The position of the texture
+ * @property {cc.Point} maskPos - The position of the mask
+ * @property {cc.Sprite} onSprite - The sprite of switch on
+ * @property {cc.Sprite} offSprite - The sprite of switch off
+ * @property {cc.Sprite} thumbSprite - The thumb sprite of the switch control
+ * @property {cc.LabelTTF} onLabel - The sprite of switch on
+ * @property {cc.LabelTTF} offLabel - The sprite of switch off
+ * @property {Number} onSideWidth - <@readonly> The width of the on side of the switch control
+ * @property {Number} offSideWidth - <@readonly> The width of the off side of the switch control
+ */
cc.ControlSwitchSprite = cc.Sprite.extend({
_sliderXPosition:0,
_onPosition:0,
_offPosition:0,
- _maskTexture:null,
_textureLocation:0,
_maskLocation:0,
+ _maskSize:null,
_onSprite:null,
_offSprite:null,
_thumbSprite:null,
_onLabel:null,
_offLabel:null,
+ _clipper:null,
+ _stencil:null,
+ _backRT:null,
ctor:function () {
cc.Sprite.prototype.ctor.call(this);
this._sliderXPosition = 0;
this._onPosition = 0;
this._offPosition = 0;
- this._maskTexture = null;
- this._textureLocation = 0;
this._maskLocation = 0;
+ this._maskSize = cc.size(0, 0);
this._onSprite = null;
this._offSprite = null;
this._thumbSprite = null;
@@ -186,7 +215,8 @@ cc.ControlSwitchSprite = cc.Sprite.extend({
},
initWithMaskSprite:function (maskSprite, onSprite, offSprite, thumbSprite, onLabel, offLabel) {
- if (cc.Sprite.prototype.initWithTexture.call(this,maskSprite.getTexture())) {
+ if (cc.Sprite.prototype.init.call(this)) {
+ this.setSpriteFrame(maskSprite.displayFrame());
// Sets the default values
this._onPosition = 0;
this._offPosition = -onSprite.getContentSize().width + thumbSprite.getContentSize().width / 2;
@@ -198,31 +228,24 @@ cc.ControlSwitchSprite = cc.Sprite.extend({
this.setOnLabel(onLabel);
this.setOffLabel(offLabel);
- this.addChild(this._thumbSprite);
-
// Set up the mask with the Mask shader
- this.setMaskTexture(maskSprite.getTexture());
- //TODO WebGL code
-
- /*var pProgram = new cc.GLProgram();
- pProgram.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_COLOR_VERT, cc.SHADEREX_SWITCHMASK_FRAG);
- this.setShaderProgram(pProgram);
-
- cc.CHECK_GL_ERROR_DEBUG();
- this.getShaderProgram().addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
- this.getShaderProgram().addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
- this.getShaderProgram().addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
- this.getShaderProgram().link();
- cc.CHECK_GL_ERROR_DEBUG();
-
- this.getShaderProgram().updateUniforms();
- cc.CHECK_GL_ERROR_DEBUG();*/
-
- //this._textureLocation_textureLocation = cc.renderContext.getUniformLocation(this.getShaderProgram().getProgram(), "u_texture");
- //this._maskLocation = cc.renderContext.getUniformLocation(this.getShaderProgram().getProgram(), "u_mask");
- //cc.CHECK_GL_ERROR_DEBUG();
+ this._stencil = maskSprite;
+ var maskSize = this._maskSize = this._stencil.getContentSize();
+ this._stencil.setPosition(0, 0);
+
+ // Init clipper for mask
+ this._clipper = new cc.ClippingNode();
+ this._clipper.setAnchorPoint(0.5, 0.5);
+ this._clipper.setPosition(maskSize.width / 2, maskSize.height / 2);
+ this._clipper.setStencil(this._stencil);
+ this.addChild(this._clipper);
+
+ this._clipper.addChild(onSprite);
+ this._clipper.addChild(offSprite);
+ this._clipper.addChild(onLabel);
+ this._clipper.addChild(offLabel);
- this.setContentSize(this._maskTexture.getContentSize());
+ this.addChild(this._thumbSprite);
this.needsLayout();
return true;
@@ -230,73 +253,33 @@ cc.ControlSwitchSprite = cc.Sprite.extend({
return false;
},
- draw:function () {
- //TODO WebGL code
- cc.NODE_DRAW_SETUP(this);
-
- /*ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);
- ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- this.getShaderProgram().setUniformForModelViewProjectionMatrix();
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture( GL_TEXTURE_2D, getTexture().getName());
- glUniform1i(this._textureLocation, 0);
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture( GL_TEXTURE_2D, this._maskTexture.getName() );
- glUniform1i(this._maskLocation, 1);
-
- var kQuadSize = 9;
- var offset = this._quad;
-
- // vertex
- var diff = offsetof( cc.V3F_C4B_T2F, vertices);
- glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
-
- // texCoods
- diff = offsetof( ccV3F_C4B_T2F, texCoords);
- glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
-
- // color
- diff = offsetof( ccV3F_C4B_T2F, colors);
- glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glActiveTexture(GL_TEXTURE0);*/
- },
-
needsLayout:function () {
- this._onSprite.setPosition(cc.p(this._onSprite.getContentSize().width / 2 + this._sliderXPosition,
- this._onSprite.getContentSize().height / 2));
- this._offSprite.setPosition(cc.p(this._onSprite.getContentSize().width + this._offSprite.getContentSize().width / 2 + this._sliderXPosition,
- this._offSprite.getContentSize().height / 2));
+ var maskSize = this._maskSize;
+ this._onSprite.setPosition(
+ this._onSprite.getContentSize().width / 2 + this._sliderXPosition - maskSize.width / 2,
+ this._onSprite.getContentSize().height / 2 - maskSize.height / 2
+ );
+ this._offSprite.setPosition(
+ this._onSprite.getContentSize().width + this._offSprite.getContentSize().width / 2 + this._sliderXPosition - maskSize.width / 2,
+ this._offSprite.getContentSize().height / 2 - maskSize.height / 2
+ );
if (this._onLabel) {
- this._onLabel.setPosition(cc.p(this._onSprite.getPosition().x - this._thumbSprite.getContentSize().width / 6,
- this._onSprite.getContentSize().height / 2));
+ this._onLabel.setPosition(
+ this._onSprite.getPositionX() - this._thumbSprite.getContentSize().width / 6,
+ this._onSprite.getContentSize().height / 2 - maskSize.height / 2
+ );
}
if (this._offLabel) {
- this._offLabel.setPosition(cc.p(this._offSprite.getPosition().x + this._thumbSprite.getContentSize().width / 6,
- this._offSprite.getContentSize().height / 2));
+ this._offLabel.setPosition(
+ this._offSprite.getPositionX() + this._thumbSprite.getContentSize().width / 6,
+ this._offSprite.getContentSize().height / 2 - maskSize.height / 2
+ );
}
- var locMaskSize = this._maskTexture.getContentSize();
- this._thumbSprite.setPosition(cc.p(this._onSprite.getContentSize().width + this._sliderXPosition,
- locMaskSize.height / 2));
- var rt = cc.RenderTexture.create(locMaskSize.width, locMaskSize.height);
-
- rt.begin();
- this._onSprite.visit();
- this._offSprite.visit();
-
- if (this._onLabel)
- this._onLabel.visit();
- if (this._offLabel)
- this._offLabel.visit();
-
- rt.end();
-
- this.setTexture(rt.getSprite().getTexture());
- this.setFlippedY(true);
+ this._thumbSprite.setPosition(
+ this._onSprite.getContentSize().width + this._sliderXPosition,
+ this._maskSize.height / 2
+ );
},
setSliderXPosition:function (sliderXPosition) {
@@ -316,17 +299,17 @@ cc.ControlSwitchSprite = cc.Sprite.extend({
return this._sliderXPosition;
},
- onSideWidth:function () {
+ _getOnSideWidth:function () {
return this._onSprite.getContentSize().width;
},
- offSideWidth:function () {
+ _getOffSideWidth:function () {
return this._offSprite.getContentSize().height;
},
updateTweenAction:function (value, key) {
- cc.log("key = " + key + ", value = " + value);
- this.setSliderXPosition(value);
+ if (key === "sliderXPosition")
+ this.setSliderXPosition(value);
},
setOnPosition:function (onPosition) {
@@ -344,10 +327,10 @@ cc.ControlSwitchSprite = cc.Sprite.extend({
},
setMaskTexture:function (maskTexture) {
- this._maskTexture = maskTexture;
+ this._stencil.setTexture(maskTexture);
},
getMaskTexture:function () {
- return this._maskTexture;
+ return this._stencil.getTexture();
},
setTextureLocation:function (textureLocation) {
@@ -398,4 +381,45 @@ cc.ControlSwitchSprite = cc.Sprite.extend({
getOffLabel:function () {
return this._offLabel;
}
-});
\ No newline at end of file
+});
+
+var _p = cc.ControlSwitchSprite.prototype;
+
+/** @expose */
+_p.sliderX;
+cc.defineGetterSetter(_p, "sliderX", _p.getSliderXPosition, _p.setSliderXPosition);
+/** @expose */
+_p.onPos;
+cc.defineGetterSetter(_p, "onPos", _p.getOnPosition, _p.setOnPosition);
+/** @expose */
+_p.offPos;
+cc.defineGetterSetter(_p, "offPos", _p.getOffPosition, _p.setOffPosition);
+/** @expose */
+_p.maskTexture;
+cc.defineGetterSetter(_p, "maskTexture", _p.getMaskTexture, _p.setMaskTexture);
+/** @expose */
+_p.maskPos;
+cc.defineGetterSetter(_p, "maskPos", _p.getMaskLocation, _p.setMaskLocation);
+/** @expose */
+_p.onSprite;
+cc.defineGetterSetter(_p, "onSprite", _p.getOnSprite, _p.setOnSprite);
+/** @expose */
+_p.offSprite;
+cc.defineGetterSetter(_p, "offSprite", _p.getOffSprite, _p.setOffSprite);
+/** @expose */
+_p.thumbSprite;
+cc.defineGetterSetter(_p, "thumbSprite", _p.getThumbSprite, _p.setThumbSprite);
+/** @expose */
+_p.onLabel;
+cc.defineGetterSetter(_p, "onLabel", _p.getOnLabel, _p.setOnLabel);
+/** @expose */
+_p.offLabel;
+cc.defineGetterSetter(_p, "offLabel", _p.getOffLabel, _p.setOffLabel);
+/** @expose */
+_p.onSideWidth;
+cc.defineGetterSetter(_p, "onSideWidth", _p._getOnSideWidth);
+/** @expose */
+_p.offSideWidth;
+cc.defineGetterSetter(_p, "offSideWidth", _p._getOffSideWidth);
+
+_p = null;
diff --git a/extensions/GUI/CCControlExtension/CCControlUtils.js b/extensions/gui/control-extension/CCControlUtils.js
similarity index 93%
rename from extensions/GUI/CCControlExtension/CCControlUtils.js
rename to extensions/gui/control-extension/CCControlUtils.js
index c31fdf1db6..5e803bd56a 100644
--- a/extensions/GUI/CCControlExtension/CCControlUtils.js
+++ b/extensions/gui/control-extension/CCControlUtils.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright 2012 Stewart Hamilton-Arrandale.
http://creativewax.co.uk
@@ -28,6 +30,14 @@
THE SOFTWARE.
****************************************************************************/
+/**
+ * An RGBA color class, its value present as percent
+ * @param {Number} r
+ * @param {Number} g
+ * @param {Number} b
+ * @param {Number} a
+ * @constructor
+ */
cc.RGBA = function(r,g,b,a){
this.r = r ; // percent
this.g = g ; // percent
@@ -44,7 +54,7 @@ cc.HSV = function(h,s,v){
cc.ControlUtils = {};
cc.ControlUtils.addSpriteToTargetWithPosAndAnchor = function(spriteName,target,pos,anchor){
- var sprite =cc.Sprite.createWithSpriteFrameName(spriteName);
+ var sprite = new cc.Sprite("#" + spriteName);
if (!sprite)
return null;
diff --git a/extensions/GUI/CCControlExtension/CCInvocation.js b/extensions/gui/control-extension/CCInvocation.js
similarity index 86%
rename from extensions/GUI/CCControlExtension/CCInvocation.js
rename to extensions/gui/control-extension/CCInvocation.js
index 2088a3ed1a..82b0189a9d 100644
--- a/extensions/GUI/CCControlExtension/CCInvocation.js
+++ b/extensions/gui/control-extension/CCInvocation.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,7 +24,12 @@
THE SOFTWARE.
****************************************************************************/
-cc.Invocation = cc.Class.extend({
+/**
+ * An Invocation class
+ * @class
+ * @extends cc.Class
+ */
+cc.Invocation = cc.Class.extend(/** @lends cc.Invocation# */{
_action:null,
_target:null,
_controlEvent:null,
@@ -47,7 +54,7 @@ cc.Invocation = cc.Class.extend({
invoke:function(sender){
if (this._target && this._action) {
- if (typeof(this._action) == "string") {
+ if (cc.isString(this._action)) {
this._target[this._action](sender, this._controlEvent);
} else{
this._action.call(this._target, sender, this._controlEvent);
diff --git a/extensions/GUI/CCControlExtension/CCMenuPassive.js b/extensions/gui/control-extension/CCMenuPassive.js
similarity index 80%
rename from extensions/GUI/CCControlExtension/CCMenuPassive.js
rename to extensions/gui/control-extension/CCMenuPassive.js
index a608ecd72a..82a3fd32fe 100644
--- a/extensions/GUI/CCControlExtension/CCMenuPassive.js
+++ b/extensions/gui/control-extension/CCMenuPassive.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
http://www.cocos2d-x.org
@@ -22,45 +24,62 @@
THE SOFTWARE.
****************************************************************************/
-cc.Spacer = cc.Layer.extend({});
+/**
+ * The Spacer class
+ * @class
+ * @extends cc.Layer
+ */
+cc.Spacer = cc.Layer.extend(/** @lends cc.Spacer */{});
cc.Spacer.verticalSpacer = function (space) {
var pRet = new cc.Spacer();
pRet.init();
- pRet.setContentSize(cc.size(0, space));
+ pRet.setContentSize(0, space);
return pRet;
};
cc.Spacer.horizontalSpacer = function (space) {
var pRet = new cc.Spacer();
pRet.init();
- pRet.setContentSize(cc.size(space, 0));
+ pRet.setContentSize(space, 0);
return pRet;
};
-cc.MenuPassive = cc.Layer.extend({
- RGBAProtocol:true,
+/**
+ * MenuPassive: The menu passive ui component
+ * @class
+ * @extends cc.Layer
+ */
+cc.MenuPassive = cc.Layer.extend(/** @lends cc.MenuPassive# */{
_color:null,
_opacity:0,
+ _className:"MenuPassive",
ctor:function () {
},
/** Color: conforms with CCRGBAProtocol protocol */
getColor:function () {
- return this._color;
+ var locColor = this._color;
+ return cc.color(locColor.r, locColor.g, locColor.b, locColor.a);
},
setColor:function (color) {
- this._color = color;
+ var locColor = this._color;
+ locColor.r = color.r;
+ locColor.g = color.g;
+ locColor.b = color.b;
if (this._children && this._children.length > 0) {
for (var i = 0; i < this._children.length; i++) {
- if (this._children[i] && this._children[i].RGBAProtocol) {
+ if (this._children[i]) {
this._children[i].setColor(color);
}
}
}
+ if (color.a !== undefined && !color.a_undefined) {
+ this.setOpacity(color.a);
+ }
},
/** Opacity: conforms with CCRGBAProtocol protocol */
@@ -73,11 +92,13 @@ cc.MenuPassive = cc.Layer.extend({
if (this._children && this._children.length > 0) {
for (var i = 0; i < this._children.length; i++) {
- if (this._children[i] && this._children[i].RGBAProtocol) {
+ if (this._children[i]) {
this._children[i].setOpacity(opacity);
}
}
}
+
+ this._color.a = opacity;
},
/** initializes a CCMenu with it's items */
@@ -86,14 +107,14 @@ cc.MenuPassive = cc.Layer.extend({
//this.m_bIsTouchEnabled = false;
// menu in the center of the screen
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
// Set the default anchor point
this.ignoreAnchorPointForPosition(true);
- this.setAnchorPoint(cc.p(0.5, 0.5));
+ this.setAnchorPoint(0.5, 0.5);
this.setContentSize(winSize);
- this.setPosition(cc.p(winSize.width / 2, winSize.height / 2));
+ this.setPosition(winSize.width / 2, winSize.height / 2);
var z = 0;
if (item) {
@@ -136,12 +157,12 @@ cc.MenuPassive = cc.Layer.extend({
for (i = 0; i < this._children.length; i++) {
if (this._children[i]) {
width = Math.max(width, this._children[i].getContentSize().width);
- this._children[i].setPosition(cc.p(0, y - this._children[i].getContentSize().height * this._children[i].getScaleY() / 2.0));
+ this._children[i].setPosition(0, y - this._children[i].getContentSize().height * this._children[i].getScaleY() / 2.0);
y -= this._children[i].getContentSize().height * this._children[i].getScaleY() + padding;
}
}
}
- this.setContentSize(cc.size(width, height));
+ this.setContentSize(width, height);
},
/** align items horizontally */
@@ -169,12 +190,12 @@ cc.MenuPassive = cc.Layer.extend({
for (i = 0; i < this._children.length; i++) {
if (this._children[i]) {
height = Math.max(height, this._children[i].getContentSize().height);
- this._children[i].setPosition(cc.p(x + this._children[i].getContentSize().width * this._children[i].getScaleX() / 2.0, 0));
+ this._children[i].setPosition(x + this._children[i].getContentSize().width * this._children[i].getScaleX() / 2.0, 0);
x += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding;
}
}
}
- this.setContentSize(cc.size(width, height));
+ this.setContentSize(width, height);
},
/** align items in rows of columns */
@@ -195,11 +216,17 @@ cc.MenuPassive = cc.Layer.extend({
if (this._children && this._children.length > 0) {
for (i = 0; i < this._children.length; i++) {
if (this._children[i]) {
- cc.Assert(row < rows.size(), "");
+ if(row >= rows.length){
+ cc.log("cc.MenuPassive.alignItemsInColumns(): invalid row index");
+ continue;
+ }
rowColumns = rows[row];
// can not have zero columns on a row
- cc.Assert(rowColumns, "");
+ if(!rowColumns) {
+ cc.log("cc.MenuPassive.alignItemsInColumns(): can not have zero columns on a row");
+ continue;
+ }
tmp = this._children[i].getContentSize().height;
rowHeight = 0 | ((rowHeight >= tmp || (tmp == null)) ? rowHeight : tmp);
@@ -217,9 +244,9 @@ cc.MenuPassive = cc.Layer.extend({
}
// check if too many rows/columns for available menu items
- cc.Assert(!columnsOccupied, "");
+ //cc.assert(!columnsOccupied, ""); //?
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
row = 0;
rowHeight = 0;
@@ -230,7 +257,7 @@ cc.MenuPassive = cc.Layer.extend({
if (this._children && this._children.length > 0) {
for (i = 0; i < this._children.length; i++) {
if (this._children[i]) {
- if (rowColumns == 0) {
+ if (rowColumns === 0) {
rowColumns = rows[row];
w = winSize.width / (1 + rowColumns);
x = w;
@@ -239,8 +266,8 @@ cc.MenuPassive = cc.Layer.extend({
tmp = this._children[i].getContentSize().height;
rowHeight = 0 | ((rowHeight >= tmp || (tmp == null)) ? rowHeight : tmp);
- this._children[i].setPosition(cc.p(x - winSize.width / 2,
- y - this._children[i].getContentSize().height / 2));
+ this._children[i].setPosition(x - winSize.width / 2,
+ y - this._children[i].getContentSize().height / 2);
x += w;
++columnsOccupied;
@@ -281,11 +308,17 @@ cc.MenuPassive = cc.Layer.extend({
for (i = 0; i < this._children.length; i++) {
if (this._children[i]) {
// check if too many menu items for the amount of rows/columns
- cc.Assert(column < columns.size(), "");
+ if(column >= columns.length){
+ cc.log("cc.MenuPassive.alignItemsInRows(): invalid row index");
+ continue;
+ }
columnRows = columns[column];
// can't have zero rows on a column
- cc.Assert(columnRows, "");
+ if(!columnRows) {
+ cc.log("cc.MenuPassive.alignItemsInColumns(): can't have zero rows on a column");
+ continue;
+ }
// columnWidth = fmaxf(columnWidth, [item contentSize].width);
tmp = this._children[i].getContentSize().width;
@@ -309,9 +342,9 @@ cc.MenuPassive = cc.Layer.extend({
}
// check if too many rows/columns for available menu items.
- cc.Assert(!rowsOccupied, "");
+ //cc.assert(!rowsOccupied, ""); //?
- var winSize = cc.Director.getInstance().getWinSize();
+ var winSize = cc.director.getWinSize();
column = 0;
columnWidth = 0;
@@ -330,7 +363,7 @@ cc.MenuPassive = cc.Layer.extend({
tmp = this._children[i].getContentSize().width;
columnWidth = 0 | ((columnWidth >= tmp || (tmp == null)) ? columnWidth : tmp);
- this._children[i].setPosition(cc.p(x + columnWidths[column] / 2, y - winSize.height / 2));
+ this._children[i].setPosition(x + columnWidths[column] / 2, y - winSize.height / 2);
y -= this._children[i].getContentSize().height + 10;
++rowsOccupied;
@@ -357,7 +390,7 @@ cc.MenuPassive = cc.Layer.extend({
/** creates an empty CCMenu */
cc.MenuPassive.create = function (item) {
- if (arguments.length == 0) {
+ if (!item) {
item = null;
}
diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/gui/scrollview/CCScrollView.js
similarity index 63%
rename from extensions/GUI/CCScrollView/CCScrollView.js
rename to extensions/gui/scrollview/CCScrollView.js
index a5975284ac..bedba0ac04 100644
--- a/extensions/GUI/CCScrollView/CCScrollView.js
+++ b/extensions/gui/scrollview/CCScrollView.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2010-2013 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2010 Sangwoo Im
http://www.cocos2d-x.org
@@ -23,6 +25,9 @@
THE SOFTWARE.
****************************************************************************/
+/**
+ * @ignore
+ */
cc.SCROLLVIEW_DIRECTION_NONE = -1;
cc.SCROLLVIEW_DIRECTION_HORIZONTAL = 0;
@@ -35,73 +40,95 @@ var SCROLL_DEACCEL_RATE = 0.95;
var SCROLL_DEACCEL_DIST = 1.0;
var BOUNCE_DURATION = 0.15;
var INSET_RATIO = 0.2;
-var MOVE_INCH = 7.0/160.0;
+var MOVE_INCH = 7.0 / 160.0;
+var BOUNCE_BACK_FACTOR = 0.35;
-cc.convertDistanceFromPointToInch = function(pointDis){
- var eglViewer = cc.EGLView.getInstance();
- var factor = (eglViewer.getScaleX() + eglViewer.getScaleY())/2;
+cc.convertDistanceFromPointToInch = function (pointDis) {
+ var eglViewer = cc.view;
+ var factor = (eglViewer.getScaleX() + eglViewer.getScaleY()) / 2;
return (pointDis * factor) / 160; // CCDevice::getDPI() default value
};
cc.ScrollViewDelegate = cc.Class.extend({
- scrollViewDidScroll:function (view) {
+ scrollViewDidScroll: function (view) {
},
- scrollViewDidZoom:function (view) {
+ scrollViewDidZoom: function (view) {
}
});
/**
* ScrollView support for cocos2d -x.
* It provides scroll view functionalities to cocos2d projects natively.
+ * @class
+ * @extends cc.Layer
+ *
+ * @property {cc.Point} minOffset - <@readonly> The current container's minimum offset
+ * @property {cc.Point} maxOffset - <@readonly> The current container's maximum offset
+ * @property {Boolean} bounceable - Indicate whether the scroll view is bounceable
+ * @property {cc.Size} viewSize - The size of the scroll view
+ * @property {cc.Layer} container - The inside container of the scroll view
+ * @property {Number} direction - The direction allowed to scroll: cc.SCROLLVIEW_DIRECTION_BOTH by default, or cc.SCROLLVIEW_DIRECTION_NONE | cc.SCROLLVIEW_DIRECTION_HORIZONTAL | cc.SCROLLVIEW_DIRECTION_VERTICAL
+ * @property {cc.ScrollViewDelegate} delegate - The inside container of the scroll view
+ * @property {Boolean} clippingToBounds - Indicate whether the scroll view clips its children
*/
-cc.ScrollView = cc.Layer.extend({
- _zoomScale:0,
- _minZoomScale:0,
- _maxZoomScale:0,
- _delegate:null,
- _direction:cc.SCROLLVIEW_DIRECTION_BOTH,
- _dragging:false,
- _contentOffset:null,
- _container:null,
- _touchMoved:false,
- _maxInset:null,
- _minInset:null,
- _bounceable:false,
- _clippingToBounds:false,
- _scrollDistance:null,
- _touchPoint:null,
- _touchLength:0,
- _touches:null,
- _viewSize:null,
- _minScale:0,
- _maxScale:0,
+cc.ScrollView = cc.Layer.extend(/** @lends cc.ScrollView# */{
+ _zoomScale: 0,
+ _minZoomScale: 0,
+ _maxZoomScale: 0,
+ _delegate: null,
+ _direction: cc.SCROLLVIEW_DIRECTION_BOTH,
+ _dragging: false,
+ _contentOffset: null,
+ _container: null,
+ _touchMoved: false,
+ _maxInset: null,
+ _minInset: null,
+ _bounceable: false,
+ _clippingToBounds: false,
+ _scrollDistance: null,
+ _touchPoint: null,
+ _touchLength: 0,
+ _touches: null,
+ _viewSize: null,
+ _minScale: 0,
+ _maxScale: 0,
//scissor rect for parent, just for restoring GL_SCISSOR_BOX
- _parentScissorRect:null,
- _scissorRestored:false,
+ _parentScissorRect: null,
+ _scissorRestored: false,
// cache object
- _tmpViewRect:null,
+ _tmpViewRect: null,
+ _touchListener: null,
+ _className: "ScrollView",
- ctor:function () {
+ /**
+ * @contructor
+ * @param size
+ * @param container
+ * @returns {ScrollView}
+ */
+ ctor: function (size, container) {
cc.Layer.prototype.ctor.call(this);
- this._contentOffset = new cc.Point(0,0);
- this._maxInset = new cc.Point(0, 0);
- this._minInset = new cc.Point(0, 0);
- this._scrollDistance = new cc.Point(0, 0);
- this._touchPoint = new cc.Point(0, 0);
+ this._contentOffset = cc.p(0, 0);
+ this._maxInset = cc.p(0, 0);
+ this._minInset = cc.p(0, 0);
+ this._scrollDistance = cc.p(0, 0);
+ this._touchPoint = cc.p(0, 0);
this._touches = [];
- this._viewSize = new cc.Size(0, 0);
- this._parentScissorRect = new cc.Rect(0,0,0,0);
- this._tmpViewRect = new cc.Rect(0,0,0,0);
- },
+ this._viewSize = cc.size(0, 0);
+ this._parentScissorRect = new cc.Rect(0, 0, 0, 0);
+ this._tmpViewRect = new cc.Rect(0, 0, 0, 0);
+
+ if (container != undefined)
+ this.initWithViewSize(size, container);
+ else
+ this.initWithViewSize(cc.size(200, 200), null);
- init:function () {
- return this.initWithViewSize(cc.size(200, 200), null);
},
- registerWithTouchDispatcher:function () {
- cc.registerTargetedDelegate(this.getTouchPriority(), false, this);
+ init: function () {
+ return this.initWithViewSize(cc.size(200, 200), null);
},
/**
@@ -110,17 +137,15 @@ cc.ScrollView = cc.Layer.extend({
* @param {cc.Node} container
* @return {Boolean}
*/
- initWithViewSize:function (size, container) {
- var pZero = cc.p(0,0);
+ initWithViewSize: function (size, container) {
+ var pZero = cc.p(0, 0);
if (cc.Layer.prototype.init.call(this)) {
- this._container = container;
-
- if (!this._container) {
- this._container = cc.Layer.create();
- this._container.ignoreAnchorPointForPosition(false);
- this._container.setAnchorPoint(pZero);
+ if (!container && !this._container) {
+ container = new cc.Layer();
+ }
+ if (container) {
+ this.setContainer(container);
}
-
this.setViewSize(size);
this.setTouchEnabled(true);
@@ -134,13 +159,44 @@ cc.ScrollView = cc.Layer.extend({
this._container.setPosition(pZero);
this._touchLength = 0.0;
- this.addChild(this._container);
this._minScale = this._maxScale = 1.0;
return true;
}
return false;
},
+ visit: function (parent) {
+ var cmd = this._renderCmd, parentCmd = parent ? parent._renderCmd : null;
+
+ // quick return if not visible
+ if (!this._visible) {
+ cmd._propagateFlagsDown(parentCmd);
+ return;
+ }
+
+ var renderer = cc.renderer;
+ cmd.visit(parentCmd);
+
+ if (this._clippingToBounds) {
+ renderer.pushRenderCommand(cmd.startCmd);
+ }
+
+ var i, children = this._children, len = children.length;
+ if (len > 0) {
+ if (this._reorderChildDirty) {
+ this.sortAllChildren();
+ }
+ for (i = 0; i < len; i++) {
+ children[i].visit(this);
+ }
+ }
+
+ if (this._clippingToBounds) {
+ renderer.pushRenderCommand(cmd.endCmd);
+ }
+ cmd._dirtyFlag = 0;
+ },
+
/**
* Sets a new content offset. It ignores max/min offset. It just sets what's given. (just like UIKit's UIScrollView)
*
@@ -168,8 +224,9 @@ cc.ScrollView = cc.Layer.extend({
},
- getContentOffset:function () {
- return this._container.getPosition();
+ getContentOffset: function () {
+ var locPos = this._container.getPosition();
+ return cc.p(locPos.x, locPos.y);
},
/**
@@ -179,10 +236,10 @@ cc.ScrollView = cc.Layer.extend({
* @param {cc.Point} offset new offset
* @param {Number} dt animation duration
*/
- setContentOffsetInDuration:function (offset, dt) {
- var scroll = cc.MoveTo.create(dt, offset);
- var expire = cc.CallFunc.create(this._stoppedAnimatedScroll, this);
- this._container.runAction(cc.Sequence.create(scroll, expire));
+ setContentOffsetInDuration: function (offset, dt) {
+ var scroll = cc.moveTo(dt, offset);
+ var expire = cc.callFunc(this._stoppedAnimatedScroll, this);
+ this._container.runAction(cc.sequence(scroll, expire));
this.schedule(this._performedAnimatedScroll);
},
@@ -199,11 +256,11 @@ cc.ScrollView = cc.Layer.extend({
}
var locContainer = this._container;
- if (locContainer.getScale() != scale) {
+ if (locContainer.getScale() !== scale) {
var oldCenter, newCenter;
var center;
- if (this._touchLength == 0.0) {
+ if (this._touchLength === 0.0) {
var locViewSize = this._viewSize;
center = cc.p(locViewSize.width * 0.5, locViewSize.height * 0.5);
center = this.convertToWorldSpace(center);
@@ -221,7 +278,7 @@ cc.ScrollView = cc.Layer.extend({
}
},
- getZoomScale:function () {
+ getZoomScale: function () {
return this._container.getScale();
},
@@ -231,11 +288,11 @@ cc.ScrollView = cc.Layer.extend({
* @param {Number} s a new scale value
* @param {Number} dt animation duration
*/
- setZoomScaleInDuration:function (s, dt) {
+ setZoomScaleInDuration: function (s, dt) {
if (dt > 0) {
var locScale = this._container.getScale();
- if (locScale != s) {
- var scaleAction = cc.ActionTween.create(dt, "zoomScale", locScale, s);
+ if (locScale !== s) {
+ var scaleAction = cc.actionTween(dt, "zoomScale", locScale, s);
this.runAction(scaleAction);
}
} else {
@@ -247,7 +304,7 @@ cc.ScrollView = cc.Layer.extend({
* Returns the current container's minimum offset. You may want this while you animate scrolling by yourself
* @return {cc.Point} Returns the current container's minimum offset.
*/
- minContainerOffset:function () {
+ minContainerOffset: function () {
var locContainer = this._container;
var locContentSize = locContainer.getContentSize(), locViewSize = this._viewSize;
return cc.p(locViewSize.width - locContentSize.width * locContainer.getScaleX(),
@@ -258,7 +315,7 @@ cc.ScrollView = cc.Layer.extend({
* Returns the current container's maximum offset. You may want this while you animate scrolling by yourself
* @return {cc.Point} Returns the current container's maximum offset.
*/
- maxContainerOffset:function () {
+ maxContainerOffset: function () {
return cc.p(0.0, 0.0);
},
@@ -267,7 +324,7 @@ cc.ScrollView = cc.Layer.extend({
* @param {cc.Node} node
* @return {Boolean} YES if it is in visible bounds
*/
- isNodeVisible:function (node) {
+ isNodeVisible: function (node) {
var offset = this.getContentOffset();
var size = this.getViewSize();
var scale = this.getZoomScale();
@@ -280,36 +337,37 @@ cc.ScrollView = cc.Layer.extend({
/**
* Provided to make scroll view compatible with SWLayer's pause method
*/
- pause:function (sender) {
- this._container.pauseSchedulerAndActions();
+ pause: function (sender) {
+ this._container.pause();
var selChildren = this._container.getChildren();
for (var i = 0; i < selChildren.length; i++) {
- selChildren[i].pauseSchedulerAndActions();
+ selChildren[i].pause();
}
+ this._super();
},
/**
* Provided to make scroll view compatible with SWLayer's resume method
*/
- resume:function (sender) {
+ resume: function (sender) {
var selChildren = this._container.getChildren();
for (var i = 0, len = selChildren.length; i < len; i++) {
- selChildren[i].resumeSchedulerAndActions();
+ selChildren[i].resume();
}
-
- this._container.resumeSchedulerAndActions();
+ this._container.resume();
+ this._super();
},
- isDragging:function () {
+ isDragging: function () {
return this._dragging;
},
- isTouchMoved:function () {
+ isTouchMoved: function () {
return this._touchMoved;
},
- isBounceable:function () {
+ isBounceable: function () {
return this._bounceable;
},
- setBounceable:function (bounceable) {
+ setBounceable: function (bounceable) {
this._bounceable = bounceable;
},
@@ -320,20 +378,20 @@ cc.ScrollView = cc.Layer.extend({
* Hence, this scroll view will use a separate size property.
*
*/
- getViewSize:function () {
+ getViewSize: function () {
return this._viewSize;
},
- setViewSize:function (size) {
+ setViewSize: function (size) {
this._viewSize = size;
- cc.Node.prototype.setContentSize.call(this,size);
+ cc.Node.prototype.setContentSize.call(this, size);
},
- getContainer:function () {
+ getContainer: function () {
return this._container;
},
- setContainer:function (container) {
+ setContainer: function (container) {
// Make sure that 'm_pContainer' has a non-NULL value since there are
// lots of logic that use 'm_pContainer'.
if (!container)
@@ -343,7 +401,7 @@ cc.ScrollView = cc.Layer.extend({
this._container = container;
container.ignoreAnchorPointForPosition(false);
- container.setAnchorPoint(cc.p(0.0, 0.0));
+ container.setAnchorPoint(0, 0);
this.addChild(container);
this.setViewSize(this._viewSize);
@@ -352,25 +410,27 @@ cc.ScrollView = cc.Layer.extend({
/**
* direction allowed to scroll. CCScrollViewDirectionBoth by default.
*/
- getDirection:function () {
+ getDirection: function () {
return this._direction;
},
- setDirection:function (direction) {
+ setDirection: function (direction) {
this._direction = direction;
},
- getDelegate:function () {
+ getDelegate: function () {
return this._delegate;
},
- setDelegate:function (delegate) {
+ setDelegate: function (delegate) {
this._delegate = delegate;
},
/** override functions */
// optional
- onTouchBegan:function (touch, event) {
- if (!this.isVisible())
- return false;
+ onTouchBegan: function (touch, event) {
+ for (var c = this; c != null; c = c.parent) {
+ if (!c.isVisible())
+ return false;
+ }
//var frameOriginal = this.getParent().convertToWorldSpace(this.getPosition());
//var frame = cc.rect(frameOriginal.x, frameOriginal.y, this._viewSize.width, this._viewSize.height);
var frame = this._getViewRect();
@@ -382,7 +442,6 @@ cc.ScrollView = cc.Layer.extend({
if (locTouches.length > 2 || this._touchMoved || !cc.rectContainsPoint(frame, locPoint))
return false;
- //if (!cc.ArrayContainsObject(this._touches, touch)) {
locTouches.push(touch);
//}
@@ -393,7 +452,7 @@ cc.ScrollView = cc.Layer.extend({
this._scrollDistance.x = 0;
this._scrollDistance.y = 0;
this._touchLength = 0.0;
- } else if (locTouches.length == 2) {
+ } else if (locTouches.length === 2) {
this._touchPoint = cc.pMidpoint(this.convertTouchToNodeSpace(locTouches[0]),
this.convertTouchToNodeSpace(locTouches[1]));
this._touchLength = cc.pDistance(locContainer.convertTouchToNodeSpace(locTouches[0]),
@@ -403,11 +462,12 @@ cc.ScrollView = cc.Layer.extend({
return true;
},
- onTouchMoved:function (touch, event) {
+ onTouchMoved: function (touch, event) {
if (!this.isVisible())
return;
- //if (cc.ArrayContainsObject(this._touches, touch)) {
+ this.setNodeDirty();
+
if (this._touches.length === 1 && this._dragging) { // scrolling
this._touchMoved = true;
//var frameOriginal = this.getParent().convertToWorldSpace(this.getPosition());
@@ -418,20 +478,36 @@ cc.ScrollView = cc.Layer.extend({
var newPoint = this.convertTouchToNodeSpace(touch);
var moveDistance = cc.pSub(newPoint, this._touchPoint);
- var dis = 0.0, locDirection = this._direction;
- if (locDirection === cc.SCROLLVIEW_DIRECTION_VERTICAL)
+ var dis = 0.0, locDirection = this._direction, pos;
+ if (locDirection === cc.SCROLLVIEW_DIRECTION_VERTICAL) {
dis = moveDistance.y;
- else if (locDirection === cc.SCROLLVIEW_DIRECTION_HORIZONTAL)
+ pos = this._container.getPositionY();
+ if (!(this.minContainerOffset().y <= pos && pos <= this.maxContainerOffset().y))
+ moveDistance.y *= BOUNCE_BACK_FACTOR;
+ } else if (locDirection === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) {
dis = moveDistance.x;
- else
+ pos = this._container.getPositionX();
+ if (!(this.minContainerOffset().x <= pos && pos <= this.maxContainerOffset().x))
+ moveDistance.x *= BOUNCE_BACK_FACTOR;
+ } else {
dis = Math.sqrt(moveDistance.x * moveDistance.x + moveDistance.y * moveDistance.y);
- if (!this._touchMoved && Math.abs(cc.convertDistanceFromPointToInch(dis)) < MOVE_INCH ){
+ pos = this._container.getPositionY();
+ var _minOffset = this.minContainerOffset(), _maxOffset = this.maxContainerOffset();
+ if (!(_minOffset.y <= pos && pos <= _maxOffset.y))
+ moveDistance.y *= BOUNCE_BACK_FACTOR;
+
+ pos = this._container.getPositionX();
+ if (!(_minOffset.x <= pos && pos <= _maxOffset.x))
+ moveDistance.x *= BOUNCE_BACK_FACTOR;
+ }
+
+ if (!this._touchMoved && Math.abs(cc.convertDistanceFromPointToInch(dis)) < MOVE_INCH) {
//CCLOG("Invalid movement, distance = [%f, %f], disInch = %f", moveDistance.x, moveDistance.y);
return;
}
- if (!this._touchMoved){
+ if (!this._touchMoved) {
moveDistance.x = 0;
moveDistance.y = 0;
}
@@ -439,7 +515,7 @@ cc.ScrollView = cc.Layer.extend({
this._touchPoint = newPoint;
this._touchMoved = true;
- if (cc.rectContainsPoint(frame, this.convertToWorldSpace(newPoint))) {
+ if (this._dragging) {
switch (locDirection) {
case cc.SCROLLVIEW_DIRECTION_VERTICAL:
moveDistance.x = 0.0;
@@ -465,11 +541,11 @@ cc.ScrollView = cc.Layer.extend({
}
},
- onTouchEnded:function (touch, event) {
+ onTouchEnded: function (touch, event) {
if (!this.isVisible())
return;
- if (this._touches.length == 1 && this._touchMoved)
+ if (this._touches.length === 1 && this._touchMoved)
this.schedule(this._deaccelerateScrolling);
this._touches.length = 0;
@@ -477,7 +553,7 @@ cc.ScrollView = cc.Layer.extend({
this._touchMoved = false;
},
- onTouchCancelled:function (touch, event) {
+ onTouchCancelled: function (touch, event) {
if (!this.isVisible())
return;
@@ -486,19 +562,36 @@ cc.ScrollView = cc.Layer.extend({
this._touchMoved = false;
},
- setContentSize: function (size) {
- if (this.getContainer() != null) {
- this.getContainer().setContentSize(size);
+ setContentSize: function (size, height) {
+ if (this.getContainer() !== null) {
+ if (height === undefined)
+ this.getContainer().setContentSize(size);
+ else
+ this.getContainer().setContentSize(size, height);
+ this.updateInset();
+ }
+ },
+ _setWidth: function (value) {
+ var container = this.getContainer();
+ if (container !== null) {
+ container._setWidth(value);
+ this.updateInset();
+ }
+ },
+ _setHeight: function (value) {
+ var container = this.getContainer();
+ if (container !== null) {
+ container._setHeight(value);
this.updateInset();
}
},
- getContentSize:function () {
+ getContentSize: function () {
return this._container.getContentSize();
},
- updateInset:function () {
- if (this.getContainer() != null) {
+ updateInset: function () {
+ if (this.getContainer() !== null) {
var locViewSize = this._viewSize;
var tempOffset = this.maxContainerOffset();
this._maxInset.x = tempOffset.x + locViewSize.width * INSET_RATIO;
@@ -512,111 +605,56 @@ cc.ScrollView = cc.Layer.extend({
/**
* Determines whether it clips its children or not.
*/
- isClippingToBounds:function () {
+ isClippingToBounds: function () {
return this._clippingToBounds;
},
- setClippingToBounds:function (clippingToBounds) {
+ setClippingToBounds: function (clippingToBounds) {
this._clippingToBounds = clippingToBounds;
},
- visit:function (ctx) {
- // quick return if not visible
- if (!this.isVisible())
- return;
-
- var context = ctx || cc.renderContext;
- var i, locChildren = this._children, selChild, childrenLen;
- if (cc.renderContextType === cc.CANVAS) {
- context.save();
- this.transform(context);
- this._beforeDraw(context);
-
- if (locChildren && locChildren.length > 0) {
- childrenLen = locChildren.length;
- this.sortAllChildren();
- // draw children zOrder < 0
- for (i = 0; i < childrenLen; i++) {
- selChild = locChildren[i];
- if (selChild && selChild._zOrder < 0)
- selChild.visit(context);
- else
- break;
- }
-
- this.draw(context); // self draw
-
- // draw children zOrder >= 0
- for (; i < childrenLen; i++)
- locChildren[i].visit(context);
- } else{
- this.draw(context); // self draw
- }
-
- this._afterDraw();
-
- context.restore();
- } else {
- cc.kmGLPushMatrix();
- var locGrid = this._grid;
- if (locGrid && locGrid.isActive()) {
- locGrid.beforeDraw();
- this.transformAncestors();
- }
-
- this.transform(context);
- this._beforeDraw(context);
- if (locChildren && locChildren.length > 0) {
- childrenLen = locChildren.length;
- // draw children zOrder < 0
- for (i = 0; i < childrenLen; i++) {
- selChild = locChildren[i];
- if (selChild && selChild._zOrder < 0)
- selChild.visit();
- else
- break;
- }
-
- // this draw
- this.draw(context);
-
- // draw children zOrder >= 0
- for (; i < childrenLen; i++)
- locChildren[i].visit();
- } else{
- this.draw(context);
- }
-
- this._afterDraw(context);
- if (locGrid && locGrid.isActive())
- locGrid.afterDraw(this);
-
- cc.kmGLPopMatrix();
- }
- },
-
- addChild:function (child, zOrder, tag) {
+ addChild: function (child, zOrder, tag) {
if (!child)
throw new Error("child must not nil!");
- zOrder = zOrder || child.getZOrder();
+ zOrder = zOrder || child.getLocalZOrder();
tag = tag || child.getTag();
- child.ignoreAnchorPointForPosition(false);
- child.setAnchorPoint(cc.p(0.0, 0.0));
- if (this._container != child) {
+ //child.ignoreAnchorPointForPosition(false);
+ //child.setAnchorPoint(0, 0);
+ if (this._container !== child) {
this._container.addChild(child, zOrder, tag);
} else {
cc.Layer.prototype.addChild.call(this, child, zOrder, tag);
}
},
- setTouchEnabled:function (e) {
- cc.Layer.prototype.setTouchEnabled.call(this, e);
+ isTouchEnabled: function () {
+ return this._touchListener !== null;
+ },
+
+ setTouchEnabled: function (e) {
+ if (this._touchListener)
+ cc.eventManager.removeListener(this._touchListener);
+ this._touchListener = null;
if (!e) {
this._dragging = false;
this._touchMoved = false;
this._touches.length = 0;
+ } else {
+ var listener = cc.EventListener.create({
+ event: cc.EventListener.TOUCH_ONE_BY_ONE
+ });
+ if (this.onTouchBegan)
+ listener.onTouchBegan = this.onTouchBegan.bind(this);
+ if (this.onTouchMoved)
+ listener.onTouchMoved = this.onTouchMoved.bind(this);
+ if (this.onTouchEnded)
+ listener.onTouchEnded = this.onTouchEnded.bind(this);
+ if (this.onTouchCancelled)
+ listener.onTouchCancelled = this.onTouchCancelled.bind(this);
+ this._touchListener = listener;
+ cc.eventManager.addListener(listener, this);
}
},
@@ -626,7 +664,7 @@ cc.ScrollView = cc.Layer.extend({
* @param size view size
* @return initialized scroll view object
*/
- _initWithViewSize:function (size) {
+ _initWithViewSize: function (size) {
return null;
},
@@ -635,7 +673,7 @@ cc.ScrollView = cc.Layer.extend({
*
* @param animated If YES, relocation is animated
*/
- _relocateContainer:function (animated) {
+ _relocateContainer: function (animated) {
var min = this.minContainerOffset();
var max = this.maxContainerOffset();
var locDirection = this._direction;
@@ -648,12 +686,12 @@ cc.ScrollView = cc.Layer.extend({
newX = Math.min(newX, max.x);
}
- if (locDirection == cc.SCROLLVIEW_DIRECTION_BOTH || locDirection == cc.SCROLLVIEW_DIRECTION_VERTICAL) {
+ if (locDirection === cc.SCROLLVIEW_DIRECTION_BOTH || locDirection === cc.SCROLLVIEW_DIRECTION_VERTICAL) {
newY = Math.min(newY, max.y);
newY = Math.max(newY, min.y);
}
- if (newY != oldPoint.y || newX != oldPoint.x) {
+ if (newY !== oldPoint.y || newX !== oldPoint.x) {
this.setContentOffset(cc.p(newX, newY), animated);
}
},
@@ -663,7 +701,7 @@ cc.ScrollView = cc.Layer.extend({
*
* @param {Number} dt delta
*/
- _deaccelerateScrolling:function (dt) {
+ _deaccelerateScrolling: function (dt) {
if (this._dragging) {
this.unschedule(this._deaccelerateScrolling);
return;
@@ -672,7 +710,7 @@ cc.ScrollView = cc.Layer.extend({
var maxInset, minInset;
var oldPosition = this._container.getPosition();
var locScrollDistance = this._scrollDistance;
- this._container.setPosition(oldPosition.x + locScrollDistance.x , oldPosition.y + locScrollDistance.y);
+ this._container.setPosition(oldPosition.x + locScrollDistance.x, oldPosition.y + locScrollDistance.y);
if (this._bounceable) {
maxInset = this._maxInset;
minInset = this._minInset;
@@ -682,19 +720,9 @@ cc.ScrollView = cc.Layer.extend({
}
//check to see if offset lies within the inset bounds
- /*var newX = Math.min(this._container.getPosition().x, maxInset.x);
- newX = Math.max(newX, minInset.x);
- var newY = Math.min(this._container.getPosition().y, maxInset.y);
- newY = Math.max(newY, minInset.y);*/
- oldPosition.x = this._container.getPositionX();
- oldPosition.y = this._container.getPositionY();
- var newX = oldPosition.x;
- var newY = oldPosition.y;
-
- //this._scrollDistance = cc.pSub(this._scrollDistance, cc.p(newX - this._container.getPosition().x, newY - this._container.getPosition().y));
- //= this._scrollDistance = cc.pSub(this._scrollDistance, cc.p(0, 0)); = do nothing
-
- //this._scrollDistance = cc.pMult(this._scrollDistance, SCROLL_DEACCEL_RATE);
+ var newX = this._container.getPositionX();
+ var newY = this._container.getPositionY();
+
locScrollDistance.x = locScrollDistance.x * SCROLL_DEACCEL_RATE;
locScrollDistance.y = locScrollDistance.y * SCROLL_DEACCEL_RATE;
@@ -704,8 +732,8 @@ cc.ScrollView = cc.Layer.extend({
Math.abs(locScrollDistance.y) <= SCROLL_DEACCEL_DIST) ||
newY > maxInset.y || newY < minInset.y ||
newX > maxInset.x || newX < minInset.x ||
- newX == maxInset.x || newX == minInset.x ||
- newY == maxInset.y || newY == minInset.y) {
+ newX === maxInset.x || newX === minInset.x ||
+ newY === maxInset.y || newY === minInset.y) {
this.unschedule(this._deaccelerateScrolling);
this._relocateContainer(true);
}
@@ -713,7 +741,7 @@ cc.ScrollView = cc.Layer.extend({
/**
* This method makes sure auto scrolling causes delegate to invoke its method
*/
- _performedAnimatedScroll:function (dt) {
+ _performedAnimatedScroll: function (dt) {
if (this._dragging) {
this.unschedule(this._performedAnimatedScroll);
return;
@@ -725,7 +753,7 @@ cc.ScrollView = cc.Layer.extend({
/**
* Expire animated scroll delegate calls
*/
- _stoppedAnimatedScroll:function (node) {
+ _stoppedAnimatedScroll: function (node) {
this.unschedule(this._performedAnimatedScroll);
// After the animation stopped, "scrollViewDidScroll" should be invoked, this could fix the bug of lack of tableview cells.
if (this._delegate && this._delegate.scrollViewDidScroll) {
@@ -733,73 +761,14 @@ cc.ScrollView = cc.Layer.extend({
}
},
- /**
- * clip this view so that outside of the visible bounds can be hidden.
- */
- _beforeDraw:function (context) {
- if (this._clippingToBounds) {
- this._scissorRestored = false;
- var frame = this._getViewRect(), locEGLViewer = cc.EGLView.getInstance();
-
- var scaleX = this.getScaleX();
- var scaleY = this.getScaleY();
-
- var ctx = context || cc.renderContext;
- if (cc.renderContextType === cc.CANVAS) {
- var getWidth = (this._viewSize.width * scaleX) * locEGLViewer.getScaleX();
- var getHeight = (this._viewSize.height * scaleY) * locEGLViewer.getScaleY();
- var startX = 0;
- var startY = 0;
-
- ctx.beginPath();
- ctx.rect(startX, startY, getWidth, -getHeight);
- ctx.clip();
- ctx.closePath();
- } else {
- var EGLViewer = cc.EGLView.getInstance();
- if(EGLViewer.isScissorEnabled()){
- this._scissorRestored = true;
- this._parentScissorRect = EGLViewer.getScissorRect();
- //set the intersection of m_tParentScissorRect and frame as the new scissor rect
- if (cc.rectIntersection(frame, this._parentScissorRect)) {
- var locPSRect = this._parentScissorRect;
- var x = Math.max(frame.x, locPSRect.x);
- var y = Math.max(frame.y, locPSRect.y);
- var xx = Math.min(frame.x + frame.width, locPSRect.x + locPSRect.width);
- var yy = Math.min(frame.y + frame.height, locPSRect.y + locPSRect.height);
- EGLViewer.setScissorInPoints(x, y, xx - x, yy - y);
- }
- }else{
- ctx.enable(ctx.SCISSOR_TEST);
- //clip
- EGLViewer.setScissorInPoints(frame.x, frame.y, frame.width, frame.height);
- }
- }
- }
- },
- /**
- * retract what's done in beforeDraw so that there's no side effect to
- * other nodes.
- */
- _afterDraw:function (context) {
- if (this._clippingToBounds && cc.renderContextType === cc.WEBGL) {
- if (this._scissorRestored) { //restore the parent's scissor rect
- var rect = this._parentScissorRect;
- cc.EGLView.getInstance().setScissorInPoints(rect.x, rect.y, rect.width, rect.height)
- }else{
- var ctx = context || cc.renderContext;
- ctx.disable(ctx.SCISSOR_TEST);
- }
- }
- },
/**
* Zoom handling
*/
- _handleZoom:function () {
+ _handleZoom: function () {
},
- _getViewRect:function(){
- var screenPos = this.convertToWorldSpace(cc.PointZero());
+ _getViewRect: function () {
+ var screenPos = this.convertToWorldSpace(cc.p(0, 0));
var locViewSize = this._viewSize;
var scaleX = this.getScaleX();
@@ -828,24 +797,54 @@ cc.ScrollView = cc.Layer.extend({
locViewRect.width = locViewSize.width * scaleX;
locViewRect.height = locViewSize.height * scaleY;
return locViewRect;
+ },
+
+ _createRenderCmd: function () {
+ if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) {
+ return new cc.ScrollView.CanvasRenderCmd(this);
+ } else {
+ return new cc.ScrollView.WebGLRenderCmd(this);
+ }
}
});
+var _p = cc.ScrollView.prototype;
+
+// Extended properties
+/** @expose */
+_p.minOffset;
+cc.defineGetterSetter(_p, "minOffset", _p.minContainerOffset);
+/** @expose */
+_p.maxOffset;
+cc.defineGetterSetter(_p, "maxOffset", _p.maxContainerOffset);
+/** @expose */
+_p.bounceable;
+cc.defineGetterSetter(_p, "bounceable", _p.isBounceable, _p.setBounceable);
+/** @expose */
+_p.viewSize;
+cc.defineGetterSetter(_p, "viewSize", _p.getViewSize, _p.setViewSize);
+/** @expose */
+_p.container;
+cc.defineGetterSetter(_p, "container", _p.getContainer, _p.setContainer);
+/** @expose */
+_p.direction;
+cc.defineGetterSetter(_p, "direction", _p.getDirection, _p.setDirection);
+/** @expose */
+_p.delegate;
+cc.defineGetterSetter(_p, "delegate", _p.getDelegate, _p.setDelegate);
+/** @expose */
+_p.clippingToBounds;
+cc.defineGetterSetter(_p, "clippingToBounds", _p.isClippingToBounds, _p.setClippingToBounds);
+
+_p = null;
+
/**
* Returns an autoreleased scroll view object.
- *
+ * @deprecated
* @param {cc.Size} size view size
* @param {cc.Node} container parent object
* @return {cc.ScrollView} scroll view object
*/
cc.ScrollView.create = function (size, container) {
- var pRet = new cc.ScrollView();
- if (arguments.length == 2) {
- if (pRet && pRet.initWithViewSize(size, container))
- return pRet;
- } else {
- if (pRet && pRet.init())
- return pRet;
- }
- return null;
-};
\ No newline at end of file
+ return new cc.ScrollView(size, container);
+};
diff --git a/extensions/gui/scrollview/CCScrollViewCanvasRenderCmd.js b/extensions/gui/scrollview/CCScrollViewCanvasRenderCmd.js
new file mode 100644
index 0000000000..0cc063f846
--- /dev/null
+++ b/extensions/gui/scrollview/CCScrollViewCanvasRenderCmd.js
@@ -0,0 +1,64 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.ScrollView.CanvasRenderCmd = function (renderable) {
+ this._layerCmdCtor(renderable);
+ this._needDraw = false;
+
+ this.startCmd = new cc.CustomRenderCmd(this, this._startCmd);
+ this.startCmd._canUseDirtyRegion = true;
+ this.endCmd = new cc.CustomRenderCmd(this, this._endCmd);
+ this.endCmd._canUseDirtyRegion = true;
+ };
+
+ var proto = cc.ScrollView.CanvasRenderCmd.prototype = Object.create(cc.Layer.CanvasRenderCmd.prototype);
+ proto.constructor = cc.ScrollView.CanvasRenderCmd;
+
+ proto._startCmd = function (ctx, scaleX, scaleY) {
+ var node = this._node;
+ var wrapper = ctx || cc._renderContext, context = wrapper.getContext();
+ wrapper.save();
+
+ if (node._clippingToBounds) {
+ this._scissorRestored = false;
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+
+ var locScaleX = node.getScaleX(), locScaleY = node.getScaleY();
+
+ var getWidth = (node._viewSize.width * locScaleX);
+ var getHeight = (node._viewSize.height * locScaleY);
+
+ context.beginPath();
+ context.rect(0, 0, getWidth, -getHeight);
+ context.closePath();
+ context.clip();
+ }
+ };
+
+ proto._endCmd = function (wrapper) {
+ wrapper = wrapper || cc._renderContext;
+ wrapper.restore();
+ };
+})();
diff --git a/extensions/gui/scrollview/CCScrollViewWebGLRenderCmd.js b/extensions/gui/scrollview/CCScrollViewWebGLRenderCmd.js
new file mode 100644
index 0000000000..3d837db14f
--- /dev/null
+++ b/extensions/gui/scrollview/CCScrollViewWebGLRenderCmd.js
@@ -0,0 +1,71 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+ cc.ScrollView.WebGLRenderCmd = function (renderable) {
+ this._layerCmdCtor(renderable);
+ this._needDraw = false;
+
+ this.startCmd = new cc.CustomRenderCmd(this, this._startCmd);
+ this.endCmd = new cc.CustomRenderCmd(this, this._endCmd);
+ };
+
+ var proto = cc.ScrollView.WebGLRenderCmd.prototype = Object.create(cc.Layer.WebGLRenderCmd.prototype);
+ proto.constructor = cc.ScrollView.WebGLRenderCmd;
+
+ proto._startCmd = function () {
+ var node = this._node;
+ var EGLViewer = cc.view;
+ var frame = node._getViewRect();
+ if (EGLViewer.isScissorEnabled()) {
+ node._scissorRestored = true;
+ node._parentScissorRect = EGLViewer.getScissorRect();
+ //set the intersection of m_tParentScissorRect and frame as the new scissor rect
+ if (cc.rectIntersection(frame, node._parentScissorRect)) {
+ var locPSRect = node._parentScissorRect;
+ var x = Math.max(frame.x, locPSRect.x);
+ var y = Math.max(frame.y, locPSRect.y);
+ var xx = Math.min(frame.x + frame.width, locPSRect.x + locPSRect.width);
+ var yy = Math.min(frame.y + frame.height, locPSRect.y + locPSRect.height);
+ EGLViewer.setScissorInPoints(x, y, xx - x, yy - y);
+ }
+ } else {
+ var ctx = cc._renderContext;
+ ctx.enable(ctx.SCISSOR_TEST);
+ //clip
+ EGLViewer.setScissorInPoints(frame.x, frame.y, frame.width, frame.height);
+ }
+ };
+
+ proto._endCmd = function () {
+ var node = this._node;
+ if (node._scissorRestored) { //restore the parent's scissor rect
+ var rect = node._parentScissorRect;
+ cc.view.setScissorInPoints(rect.x, rect.y, rect.width, rect.height);
+ } else {
+ var ctx = cc._renderContext;
+ ctx.disable(ctx.SCISSOR_TEST);
+ }
+ };
+})();
diff --git a/extensions/GUI/CCScrollView/CCSorting.js b/extensions/gui/scrollview/CCSorting.js
similarity index 76%
rename from extensions/GUI/CCScrollView/CCSorting.js
rename to extensions/gui/scrollview/CCSorting.js
index 205cfa8fe0..cda5fba4da 100644
--- a/extensions/GUI/CCScrollView/CCSorting.js
+++ b/extensions/gui/scrollview/CCSorting.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2010 Sangwoo Im
http://www.cocos2d-x.org
@@ -23,7 +25,12 @@
THE SOFTWARE.
****************************************************************************/
-cc.SortableObject = cc.Class.extend({
+/**
+ * The sortable object interface
+ * @class
+ * @extends cc.Class
+ */
+cc.SortableObject = cc.Class.extend(/** @lends cc.SortableObject */{
setObjectID:function (objectId) {
},
getObjectID:function () {
@@ -31,7 +38,12 @@ cc.SortableObject = cc.Class.extend({
}
});
-cc.SortedObject = cc.SortableObject.extend({
+/**
+ * The SortedObject class
+ * @class
+ * @extends cc.SortableObject
+ */
+cc.SortedObject = cc.SortableObject.extend(/** @lends cc.SortedObject */{
_objectID:0,
ctor:function () {
@@ -51,13 +63,18 @@ var _compareObject = function (val1, val2) {
return (val1.getObjectID() - val2.getObjectID());
};
-cc.ArrayForObjectSorting = cc.Class.extend({
+/**
+ * Array for object sorting utils
+ * @class
+ * @extend cc.Class
+ */
+cc.ArrayForObjectSorting = cc.Class.extend(/** @lends cc.ArrayForObjectSorting# */{
_saveObjectArr:null,
ctor:function () {
this._saveObjectArr = [];
},
- /*!
+ /**
* Inserts a given object into array.
*
* Inserts a given object into array with key and value that are used in
@@ -66,10 +83,12 @@ cc.ArrayForObjectSorting = cc.Class.extend({
* If the compare message does not result NSComparisonResult, sorting behavior
* is not defined. It ignores duplicate entries and inserts next to it.
*
- * @param object to insert
+ * @function
+ * @param {Object} addObject Object to insert
*/
insertSortedObject:function (addObject) {
- cc.Assert(addObject instanceof cc.Class, "Invalid parameter.");
+ if(!addObject)
+ throw new Error("cc.ArrayForObjectSorting.insertSortedObject(): addObject should be non-null.");
var idx = this.indexOfSortedObject(addObject);
this.insertObject(addObject, idx);
},
@@ -80,17 +99,18 @@ cc.ArrayForObjectSorting = cc.Class.extend({
* Removes an object with given key and value. If no object is found in array
* with the key and value, no action is taken.
*
- * @param value to remove
+ * @function
+ * @param {Object} delObject Object to remove
*/
removeSortedObject:function (delObject) {
- if (this.count() == 0) {
+ if (this.count() === 0) {
return;
}
var idx = this.indexOfSortedObject(delObject);
- if (idx < this.count() && idx != cc.INVALID_INDEX) {
+ if (idx < this.count() && idx !== cc.INVALID_INDEX) {
var foundObj = this.objectAtIndex(idx);
- if (foundObj.getObjectID() == delObject.getObjectID()) {
+ if (foundObj.getObjectID() === delObject.getObjectID()) {
this.removeObjectAtIndex(idx);
}
}
@@ -103,14 +123,15 @@ cc.ArrayForObjectSorting = cc.Class.extend({
* keep consistency of being sorted. If it is changed externally, it must be
* sorted completely again.
*
- * @param value to set
- * @param object the object which has the value
+ * @function
+ * @param {Number} tag Tag to set
+ * @param {Object} setObject The object which would be set
*/
setObjectID_ofSortedObject:function (tag, setObject) {
var idx = this.indexOfSortedObject(setObject);
- if (idx < this.count() && idx != cc.INVALID_INDEX) {
+ if (idx < this.count() && idx !== cc.INVALID_INDEX) {
var foundObj = this.objectAtIndex(idx);
- if (foundObj.getObjectID() == setObject.getObjectID()) {
+ if (foundObj.getObjectID() === setObject.getObjectID()) {
this.removeObjectAtIndex(idx);
foundObj.setObjectID(tag);
this.insertSortedObject(foundObj);
@@ -119,16 +140,16 @@ cc.ArrayForObjectSorting = cc.Class.extend({
},
objectWithObjectID:function (tag) {
- if (this.count() == 0) {
+ if (this.count() === 0) {
return null;
}
var foundObj = new cc.SortedObject();
foundObj.setObjectID(tag);
var idx = this.indexOfSortedObject(foundObj);
- if (idx < this.count() && idx != cc.INVALID_INDEX) {
+ if (idx < this.count() && idx !== cc.INVALID_INDEX) {
foundObj = this.objectAtIndex(idx);
- if (foundObj.getObjectID() != tag)
+ if (foundObj.getObjectID() !== tag)
foundObj = null;
}
return foundObj;
@@ -140,8 +161,9 @@ cc.ArrayForObjectSorting = cc.Class.extend({
* Returns an object with given key and value. If no object is found,
* it returns nil.
*
- * @param value to locate object
- * @return object found or nil.
+ * @function
+ * @param {Number} tag Tag to locate object
+ * @return {Object|null}
*/
getObjectWithObjectID:function (tag) {
return null;
@@ -155,8 +177,9 @@ cc.ArrayForObjectSorting = cc.Class.extend({
* would have been located. If object must be located at the end of array,
* it returns the length of the array, which is out of bound.
*
- * @param value to locate object
- * @return index of an object found
+ * @function
+ * @param {Number} idxObj Id to locate object
+ * @return {Number} index of an object found
*/
indexOfSortedObject:function (idxObj) {
var idx = 0;
@@ -170,7 +193,7 @@ cc.ArrayForObjectSorting = cc.Class.extend({
for (var i = 0; i < locObjectArr.length; i++) {
var pSortableObj = locObjectArr[i];
var curObjectID = pSortableObj.getObjectID();
- if ((uOfSortObjectID == curObjectID) ||
+ if ((uOfSortObjectID === curObjectID) ||
(uOfSortObjectID >= uPrevObjectID && uOfSortObjectID < curObjectID)) {
break;
}
@@ -190,7 +213,7 @@ cc.ArrayForObjectSorting = cc.Class.extend({
lastObject:function () {
var locObjectArr = this._saveObjectArr;
- if (locObjectArr.length == 0)
+ if (locObjectArr.length === 0)
return null;
return locObjectArr[locObjectArr.length - 1];
},
@@ -205,12 +228,12 @@ cc.ArrayForObjectSorting = cc.Class.extend({
},
removeObjectAtIndex:function (idx) {
- cc.ArrayRemoveObjectAtIndex(this._saveObjectArr, idx);
+ this._saveObjectArr.splice(idx, 1);
this._saveObjectArr.sort(_compareObject);
},
insertObject:function (addObj, idx) {
- this._saveObjectArr = cc.ArrayAppendObjectToIndex(this._saveObjectArr, addObj, idx);
+ this._saveObjectArr.splice(idx, 0, addObj);
this._saveObjectArr.sort(_compareObject);
}
});
diff --git a/extensions/GUI/CCScrollView/CCTableView.js b/extensions/gui/scrollview/CCTableView.js
similarity index 68%
rename from extensions/GUI/CCScrollView/CCTableView.js
rename to extensions/gui/scrollview/CCTableView.js
index caf910a2a0..a197ada84a 100644
--- a/extensions/GUI/CCScrollView/CCTableView.js
+++ b/extensions/gui/scrollview/CCTableView.js
@@ -1,5 +1,7 @@
/****************************************************************************
- Copyright (c) 2012 cocos2d-x.org
+ Copyright (c) 2008-2010 Ricardo Quesada
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
Copyright (c) 2010 Sangwoo Im
http://www.cocos2d-x.org
@@ -23,51 +25,76 @@
THE SOFTWARE.
****************************************************************************/
+/**
+ * The constant value of the fill style from top to bottom for cc.TableView
+ * @constant
+ * @type {number}
+ */
cc.TABLEVIEW_FILL_TOPDOWN = 0;
+
+/**
+ * The constant value of the fill style from bottom to top for cc.TableView
+ * @constant
+ * @type {number}
+ */
cc.TABLEVIEW_FILL_BOTTOMUP = 1;
/**
* Abstract class for SWTableView cell node
+ * @class
+ * @abstract
+ * @extends cc.Node
+ *
+ * @property {Number} objectId - The index used internally by SWTableView and its subclasses
*/
-cc.TableViewCell = cc.Node.extend({
- _idx:0,
+cc.TableViewCell = cc.Node.extend(/** @lends cc.TableViewCell# */{
+ _idx: 0,
+ _className: "TableViewCell",
/**
* The index used internally by SWTableView and its subclasses
*/
- getIdx:function () {
+ getIdx: function () {
return this._idx;
},
- setIdx:function (idx) {
+ setIdx: function (idx) {
this._idx = idx;
},
/**
* Cleans up any resources linked to this cell and resets idx property.
*/
- reset:function () {
+ reset: function () {
this._idx = cc.INVALID_INDEX;
},
- setObjectID:function (idx) {
+ setObjectID: function (idx) {
this._idx = idx;
},
- getObjectID:function () {
+ getObjectID: function () {
return this._idx;
}
});
+var _p = cc.TableViewCell.prototype;
+
+/** @expose */
+_p.objectId;
+cc.defineGetterSetter(_p, "objectId", _p.getObjectID, _p.setObjectID);
+
+_p = null;
+
/**
* Sole purpose of this delegate is to single touch event in this version.
*/
-cc.TableViewDelegate = cc.ScrollViewDelegate.extend({
+cc.TableViewDelegate = cc.ScrollViewDelegate.extend(/** @lends cc.TableViewDelegate# */{
/**
* Delegate to respond touch event
*
* @param {cc.TableView} table table contains the given cell
* @param {cc.TableViewCell} cell cell that is touched
*/
- tableCellTouched:function (table, cell) {
+ tableCellTouched: function (table, cell) {
},
/**
@@ -76,7 +103,7 @@ cc.TableViewDelegate = cc.ScrollViewDelegate.extend({
* @param {cc.TableView} table table contains the given cell
* @param {cc.TableViewCell} cell cell that is pressed
*/
- tableCellHighlight:function(table, cell){
+ tableCellHighlight: function (table, cell) {
},
/**
@@ -85,7 +112,7 @@ cc.TableViewDelegate = cc.ScrollViewDelegate.extend({
* @param {cc.TableView} table table contains the given cell
* @param {cc.TableViewCell} cell cell that is pressed
*/
- tableCellUnhighlight:function(table, cell){
+ tableCellUnhighlight: function (table, cell) {
},
@@ -98,7 +125,7 @@ cc.TableViewDelegate = cc.ScrollViewDelegate.extend({
* @param table table contains the given cell
* @param cell cell that is pressed
*/
- tableCellWillRecycle:function(table, cell){
+ tableCellWillRecycle: function (table, cell) {
}
});
@@ -106,14 +133,14 @@ cc.TableViewDelegate = cc.ScrollViewDelegate.extend({
/**
* Data source that governs table backend data.
*/
-cc.TableViewDataSource = cc.Class.extend({
+cc.TableViewDataSource = cc.Class.extend(/** @lends cc.TableViewDataSource# */{
/**
* cell size for a given index
* @param {cc.TableView} table table to hold the instances of Class
* @param {Number} idx the index of a cell to get a size
* @return {cc.Size} size of a cell at given index
*/
- tableCellSizeForIndex:function(table, idx){
+ tableCellSizeForIndex: function (table, idx) {
return this.cellSizeForTable(table);
},
/**
@@ -122,8 +149,8 @@ cc.TableViewDataSource = cc.Class.extend({
* @param {cc.TableView} table table to hold the instances of Class
* @return {cc.Size} cell size
*/
- cellSizeForTable:function (table) {
- return cc.SIZE_ZERO;
+ cellSizeForTable: function (table) {
+ return cc.size(0, 0);
},
/**
@@ -132,7 +159,7 @@ cc.TableViewDataSource = cc.Class.extend({
* @param idx index to search for a cell
* @return {cc.TableView} cell found at idx
*/
- tableCellAtIndex:function (table, idx) {
+ tableCellAtIndex: function (table, idx) {
return null;
},
@@ -141,34 +168,51 @@ cc.TableViewDataSource = cc.Class.extend({
* @param {cc.TableView} table table to hold the instances of Class
* @return {Number} number of cells
*/
- numberOfCellsInTableView:function (table) {
+ numberOfCellsInTableView: function (table) {
return 0;
}
});
/**
* UITableView counterpart for cocos2d for iphone.
- *
* this is a very basic, minimal implementation to bring UITableView-like component into cocos2d world.
*
+ * @class
+ * @extends cc.ScrollView
+ *
+ * @property {cc.TableViewDataSource} dataSource - The data source of the table view
+ * @property {cc.TableViewDelegate} delegate - The event delegate of the table view
+ * @property {Number} verticalFillOrder - The index to determine how cell is ordered and filled in the view
+ *
*/
-cc.TableView = cc.ScrollView.extend({
- _vOrdering:null,
- _indices:null,
- _cellsFreed:null,
- _dataSource:null,
- _tableViewDelegate:null,
- _oldDirection:null,
- _cellsPositions:null, //vector with all cell positions
- _touchedCell:null,
-
- ctor:function () {
+cc.TableView = cc.ScrollView.extend(/** @lends cc.TableView# */{
+ _vOrdering: null,
+ _indices: null,
+ _cellsFreed: null,
+ _dataSource: null,
+ _tableViewDelegate: null,
+ _oldDirection: null,
+ _cellsPositions: null, //vector with all cell positions
+ _touchedCell: null,
+
+ /**
+ * The
+ * @param dataSource
+ * @param size
+ * @param container
+ */
+ ctor: function (dataSource, size, container) {
cc.ScrollView.prototype.ctor.call(this);
this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE;
this._cellsPositions = [];
+
+ this.initWithViewSize(size, container);
+ this.setDataSource(dataSource);
+ this._updateCellPositions();
+ this._updateContentSize();
},
- __indexFromOffset:function (offset) {
+ __indexFromOffset: function (offset) {
var low = 0;
var high = this._dataSource.numberOfCellsInTableView(this) - 1;
var search;
@@ -182,16 +226,16 @@ cc.TableView = cc.ScrollView.extend({
}
var locCellsPositions = this._cellsPositions;
- while (high >= low){
- var index = 0|(low + (high - low) / 2);
+ while (high >= low) {
+ var index = 0 | (low + (high - low) / 2);
var cellStart = locCellsPositions[index];
var cellEnd = locCellsPositions[index + 1];
- if (search >= cellStart && search <= cellEnd){
+ if (search >= cellStart && search <= cellEnd) {
return index;
- } else if (search < cellStart){
+ } else if (search < cellStart) {
high = index - 1;
- }else {
+ } else {
low = index + 1;
}
}
@@ -201,7 +245,7 @@ cc.TableView = cc.ScrollView.extend({
return -1;
},
- _indexFromOffset:function (offset) {
+ _indexFromOffset: function (offset) {
var locOffset = {x: offset.x, y: offset.y};
var locDataSource = this._dataSource;
var maxIdx = locDataSource.numberOfCellsInTableView(this) - 1;
@@ -210,7 +254,7 @@ cc.TableView = cc.ScrollView.extend({
locOffset.y = this.getContainer().getContentSize().height - locOffset.y;
var index = this.__indexFromOffset(locOffset);
- if (index != -1) {
+ if (index !== -1) {
index = Math.max(0, index);
if (index > maxIdx)
index = cc.INVALID_INDEX;
@@ -218,7 +262,7 @@ cc.TableView = cc.ScrollView.extend({
return index;
},
- __offsetFromIndex:function (index) {
+ __offsetFromIndex: function (index) {
var offset;
switch (this.getDirection()) {
case cc.SCROLLVIEW_DIRECTION_HORIZONTAL:
@@ -232,7 +276,7 @@ cc.TableView = cc.ScrollView.extend({
return offset;
},
- _offsetFromIndex:function (index) {
+ _offsetFromIndex: function (index) {
var offset = this.__offsetFromIndex(index);
var cellSize = this._dataSource.tableCellSizeForIndex(this, index);
@@ -242,14 +286,14 @@ cc.TableView = cc.ScrollView.extend({
return offset;
},
- _updateCellPositions:function(){
+ _updateCellPositions: function () {
var cellsCount = this._dataSource.numberOfCellsInTableView(this);
var locCellsPositions = this._cellsPositions;
- if (cellsCount > 0){
+ if (cellsCount > 0) {
var currentPos = 0;
var cellSize, locDataSource = this._dataSource;
- for (var i=0; i < cellsCount; i++) {
+ for (var i = 0; i < cellsCount; i++) {
locCellsPositions[i] = currentPos;
cellSize = locDataSource.tableCellSizeForIndex(this, i);
switch (this.getDirection()) {
@@ -265,12 +309,12 @@ cc.TableView = cc.ScrollView.extend({
}
},
- _updateContentSize:function () {
- var size = cc.SizeZero();
+ _updateContentSize: function () {
+ var size = cc.size(0, 0);
var cellsCount = this._dataSource.numberOfCellsInTableView(this);
- if(cellsCount > 0){
+ if (cellsCount > 0) {
var maxPosition = this._cellsPositions[cellsCount];
switch (this.getDirection()) {
case cc.SCROLLVIEW_DIRECTION_HORIZONTAL:
@@ -284,8 +328,8 @@ cc.TableView = cc.ScrollView.extend({
this.setContentSize(size);
- if (this._oldDirection != this._direction) {
- if (this._direction == cc.SCROLLVIEW_DIRECTION_HORIZONTAL) {
+ if (this._oldDirection !== this._direction) {
+ if (this._direction === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) {
this.setContentOffset(cc.p(0, 0));
} else {
this.setContentOffset(cc.p(0, this.minContainerOffset().y));
@@ -294,77 +338,82 @@ cc.TableView = cc.ScrollView.extend({
}
},
- _moveCellOutOfSight:function (cell) {
- if(this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle)
+ _moveCellOutOfSight: function (cell) {
+ if (this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle)
this._tableViewDelegate.tableCellWillRecycle(this, cell);
this._cellsFreed.addObject(cell);
this._cellsUsed.removeSortedObject(cell);
- //cc.ArrayRemoveObjectAtIndex(this._indices,cell.getIdx());
- //this._indices.erase(cell.getIdx());
- this._indices.removeObject(cell.getIdx());
+ cc.arrayRemoveObject(this._indices, cell.getIdx());
cell.reset();
- if (cell.getParent() == this.getContainer()) {
+ if (cell.getParent() === this.getContainer()) {
this.getContainer().removeChild(cell, true);
}
},
- _setIndexForCell:function (index, cell) {
- cell.setAnchorPoint(cc.p(0.0, 0.0));
+ _setIndexForCell: function (index, cell) {
+ cell.setAnchorPoint(0, 0);
cell.setPosition(this._offsetFromIndex(index));
cell.setIdx(index);
},
- _addCellIfNecessary:function (cell) {
- if (cell.getParent() != this.getContainer()) {
+ _addCellIfNecessary: function (cell) {
+ if (cell.getParent() !== this.getContainer()) {
this.getContainer().addChild(cell);
}
this._cellsUsed.insertSortedObject(cell);
- this._indices.addObject(cell.getIdx());
+ var locIndices = this._indices, addIdx = cell.getIdx();
+ if (locIndices.indexOf(addIdx) === -1) {
+ locIndices.push(addIdx);
+ //sort
+ locIndices.sort(function (a, b) {
+ return a - b;
+ });
+ }
},
/**
* data source
*/
- getDataSource:function () {
+ getDataSource: function () {
return this._dataSource;
},
- setDataSource:function (source) {
+ setDataSource: function (source) {
this._dataSource = source;
},
/**
* delegate
*/
- getDelegate:function () {
+ getDelegate: function () {
return this._tableViewDelegate;
},
- setDelegate:function (delegate) {
+ setDelegate: function (delegate) {
this._tableViewDelegate = delegate;
},
/**
* determines how cell is ordered and filled in the view.
*/
- setVerticalFillOrder:function (fillOrder) {
- if (this._vOrdering != fillOrder) {
+ setVerticalFillOrder: function (fillOrder) {
+ if (this._vOrdering !== fillOrder) {
this._vOrdering = fillOrder;
if (this._cellsUsed.count() > 0) {
this.reloadData();
}
}
},
- getVerticalFillOrder:function () {
+ getVerticalFillOrder: function () {
return this._vOrdering;
},
- initWithViewSize:function (size, container) {
+ initWithViewSize: function (size, container) {
if (cc.ScrollView.prototype.initWithViewSize.call(this, size, container)) {
this._cellsUsed = new cc.ArrayForObjectSorting();
this._cellsFreed = new cc.ArrayForObjectSorting();
- this._indices = new cc.Set();
+ this._indices = [];
this._tableViewDelegate = null;
this._vOrdering = cc.TABLEVIEW_FILL_BOTTOMUP;
this.setDirection(cc.SCROLLVIEW_DIRECTION_VERTICAL);
@@ -380,8 +429,8 @@ cc.TableView = cc.ScrollView.extend({
*
* @param idx index to find a cell
*/
- updateCellAtIndex:function (idx) {
- if (idx == cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
+ updateCellAtIndex: function (idx) {
+ if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
return;
var cell = this.cellAtIndex(idx);
@@ -398,8 +447,8 @@ cc.TableView = cc.ScrollView.extend({
*
* @param idx location to insert
*/
- insertCellAtIndex:function (idx) {
- if (idx == cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
+ insertCellAtIndex: function (idx) {
+ if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
return;
var newIdx, locCellsUsed = this._cellsUsed;
@@ -426,8 +475,8 @@ cc.TableView = cc.ScrollView.extend({
*
* @param idx index to find a cell
*/
- removeCellAtIndex:function (idx) {
- if (idx == cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
+ removeCellAtIndex: function (idx) {
+ if (idx === cc.INVALID_INDEX || idx > this._dataSource.numberOfCellsInTableView(this) - 1)
return;
var cell = this.cellAtIndex(idx);
@@ -439,10 +488,8 @@ cc.TableView = cc.ScrollView.extend({
//remove first
this._moveCellOutOfSight(cell);
-
- this._indices.removeObject(idx);
+ cc.arrayRemoveObject(this._indices, idx);
this._updateCellPositions();
- //cc.ArrayRemoveObjectAtIndex(this._indices,idx);
for (var i = locCellsUsed.count() - 1; i > newIdx; i--) {
cell = locCellsUsed.objectAtIndex(i);
@@ -453,28 +500,30 @@ cc.TableView = cc.ScrollView.extend({
/**
* reloads data from data source. the view will be refreshed.
*/
- reloadData:function () {
+ reloadData: function () {
this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE;
var locCellsUsed = this._cellsUsed, locCellsFreed = this._cellsFreed, locContainer = this.getContainer();
for (var i = 0, len = locCellsUsed.count(); i < len; i++) {
var cell = locCellsUsed.objectAtIndex(i);
- if(this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle)
+ if (this._tableViewDelegate && this._tableViewDelegate.tableCellWillRecycle)
this._tableViewDelegate.tableCellWillRecycle(this, cell);
locCellsFreed.addObject(cell);
cell.reset();
- if (cell.getParent() == locContainer)
+ if (cell.getParent() === locContainer)
locContainer.removeChild(cell, true);
}
- this._indices = new cc.Set();
+ this._indices = [];
this._cellsUsed = new cc.ArrayForObjectSorting();
this._updateCellPositions();
this._updateContentSize();
if (this._dataSource.numberOfCellsInTableView(this) > 0)
this.scrollViewDidScroll(this);
+
+ this.setNodeDirty();
},
/**
@@ -482,7 +531,7 @@ cc.TableView = cc.ScrollView.extend({
*
* @return {TableViewCell} free cell
*/
- dequeueCell:function () {
+ dequeueCell: function () {
if (this._cellsFreed.count() === 0) {
return null;
} else {
@@ -498,42 +547,40 @@ cc.TableView = cc.ScrollView.extend({
* @param idx index
* @return {cc.TableViewCell} a cell at a given index
*/
- cellAtIndex:function (idx) {
- var found = null;
-
- if (this._indices.containsObject(idx))
- found = this._cellsUsed.objectWithObjectID(idx);
-
- return found;
+ cellAtIndex: function (idx) {
+ var i = this._indices.indexOf(idx);
+ if (i === -1)
+ return null;
+ return this._cellsUsed.objectWithObjectID(idx);
},
- scrollViewDidScroll:function (view) {
+ scrollViewDidScroll: function (view) {
var locDataSource = this._dataSource;
var countOfItems = locDataSource.numberOfCellsInTableView(this);
if (0 === countOfItems)
return;
- if (this._tableViewDelegate != null && this._tableViewDelegate.scrollViewDidScroll)
+ if (this._tableViewDelegate !== null && this._tableViewDelegate.scrollViewDidScroll)
this._tableViewDelegate.scrollViewDidScroll(this);
- var idx = 0, locViewSize = this._viewSize, locContainer = this.getContainer();
+ var idx = 0, locViewSize = this._viewSize, locContainer = this.getContainer();
var offset = this.getContentOffset();
offset.x *= -1;
offset.y *= -1;
- var maxIdx = Math.max(countOfItems-1, 0);
+ var maxIdx = Math.max(countOfItems - 1, 0);
if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN)
- offset.y = offset.y + locViewSize.height/locContainer.getScaleY();
+ offset.y = offset.y + locViewSize.height / locContainer.getScaleY();
var startIdx = this._indexFromOffset(offset);
if (startIdx === cc.INVALID_INDEX)
startIdx = countOfItems - 1;
if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN)
- offset.y -= locViewSize.height/locContainer.getScaleY();
+ offset.y -= locViewSize.height / locContainer.getScaleY();
else
- offset.y += locViewSize.height/locContainer.getScaleY();
- offset.x += locViewSize.width/locContainer.getScaleX();
+ offset.y += locViewSize.height / locContainer.getScaleY();
+ offset.x += locViewSize.width / locContainer.getScaleX();
var endIdx = this._indexFromOffset(offset);
if (endIdx === cc.INVALID_INDEX)
@@ -568,27 +615,30 @@ cc.TableView = cc.ScrollView.extend({
var locIndices = this._indices;
for (var i = startIdx; i <= endIdx; i++) {
- if (locIndices.containsObject(i))
+ if (locIndices.indexOf(i) !== -1)
continue;
this.updateCellAtIndex(i);
}
},
- scrollViewDidZoom:function (view) {
+ scrollViewDidZoom: function (view) {
},
- onTouchEnded:function (touch, event) {
+ onTouchEnded: function (touch, event) {
if (!this.isVisible())
return;
- if (this._touchedCell){
+ if (this._touchedCell) {
var bb = this.getBoundingBox();
- bb.origin = this._parent.convertToWorldSpace(bb.origin);
+ var tmpOrigin = cc.p(bb.x, bb.y);
+ tmpOrigin = this._parent.convertToWorldSpace(tmpOrigin);
+ bb.x = tmpOrigin.x;
+ bb.y = tmpOrigin.y;
var locTableViewDelegate = this._tableViewDelegate;
- if (cc.rectContainsPoint(bb, touch.getLocation()) && locTableViewDelegate != null){
- if(locTableViewDelegate.tableCellUnhighlight)
+ if (cc.rectContainsPoint(bb, touch.getLocation()) && locTableViewDelegate !== null) {
+ if (locTableViewDelegate.tableCellUnhighlight)
locTableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
- if(locTableViewDelegate.tableCellTouched)
+ if (locTableViewDelegate.tableCellTouched)
locTableViewDelegate.tableCellTouched(this, this._touchedCell);
}
this._touchedCell = null;
@@ -596,13 +646,15 @@ cc.TableView = cc.ScrollView.extend({
cc.ScrollView.prototype.onTouchEnded.call(this, touch, event);
},
- onTouchBegan:function(touch, event){
- if (!this.isVisible())
- return false;
+ onTouchBegan: function (touch, event) {
+ for (var c = this; c != null; c = c.parent) {
+ if (!c.isVisible())
+ return false;
+ }
var touchResult = cc.ScrollView.prototype.onTouchBegan.call(this, touch, event);
- if(this._touches.length === 1) {
+ if (this._touches.length === 1) {
var index, point;
point = this.getContainer().convertTouchToNodeSpace(touch);
@@ -611,12 +663,12 @@ cc.TableView = cc.ScrollView.extend({
if (index === cc.INVALID_INDEX)
this._touchedCell = null;
else
- this._touchedCell = this.cellAtIndex(index);
+ this._touchedCell = this.cellAtIndex(index);
- if (this._touchedCell && this._tableViewDelegate != null && this._tableViewDelegate.tableCellHighlight)
+ if (this._touchedCell && this._tableViewDelegate !== null && this._tableViewDelegate.tableCellHighlight)
this._tableViewDelegate.tableCellHighlight(this, this._touchedCell);
- } else if(this._touchedCell) {
- if(this._tableViewDelegate != null && this._tableViewDelegate.tableCellUnhighlight)
+ } else if (this._touchedCell) {
+ if (this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight)
this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
this._touchedCell = null;
}
@@ -624,40 +676,49 @@ cc.TableView = cc.ScrollView.extend({
return touchResult;
},
- onTouchMoved: function(touch, event){
+ onTouchMoved: function (touch, event) {
cc.ScrollView.prototype.onTouchMoved.call(this, touch, event);
if (this._touchedCell && this.isTouchMoved()) {
- if(this._tableViewDelegate != null && this._tableViewDelegate.tableCellUnhighlight)
+ if (this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight)
this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
this._touchedCell = null;
}
},
- onTouchCancelled: function(touch, event){
+ onTouchCancelled: function (touch, event) {
cc.ScrollView.prototype.onTouchCancelled.call(this, touch, event);
if (this._touchedCell) {
- if(this._tableViewDelegate != null && this._tableViewDelegate.tableCellUnhighlight)
+ if (this._tableViewDelegate !== null && this._tableViewDelegate.tableCellUnhighlight)
this._tableViewDelegate.tableCellUnhighlight(this, this._touchedCell);
this._touchedCell = null;
}
}
});
+var _p = cc.TableView.prototype;
+
+/** @expose */
+_p.dataSource;
+cc.defineGetterSetter(_p, "dataSource", _p.getDataSource, _p.setDataSource);
+/** @expose */
+_p.delegate;
+cc.defineGetterSetter(_p, "delegate", _p.getDelegate, _p.setDelegate);
+/** @expose */
+_p.verticalFillOrder;
+cc.defineGetterSetter(_p, "verticalFillOrder", _p.getVerticalFillOrder, _p.setVerticalFillOrder);
+
+_p = null;
+
/**
* An initialized table view object
- *
+ * @deprecated
* @param {cc.TableViewDataSource} dataSource data source;
* @param {cc.Size} size view size
* @param {cc.Node} [container] parent object for cells
* @return {cc.TableView} table view
*/
cc.TableView.create = function (dataSource, size, container) {
- var table = new cc.TableView();
- table.initWithViewSize(size, container);
- table.setDataSource(dataSource);
- table._updateCellPositions();
- table._updateContentSize();
- return table;
+ return new cc.TableView(dataSource, size, container);
};
diff --git a/extensions/runtime/CCLoaderLayer.js b/extensions/runtime/CCLoaderLayer.js
new file mode 100644
index 0000000000..5877918da5
--- /dev/null
+++ b/extensions/runtime/CCLoaderLayer.js
@@ -0,0 +1,988 @@
+/****************************************************************************
+ Copyright (c) 2014-2015 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+(function () {
+
+var INT_MAX = Number.MAX_VALUE;
+var GROUP_JSON_PATH = "group.json";
+
+cc.LoaderLayer = cc.Layer.extend({
+ _backgroundSprite: null,
+ _progressBackgroundSprite: null,
+ _progressBarSprite: null,
+ _logoSprite: null,
+ _titleSprite: null,
+ _groupname: null,
+ _callback: null,
+ _selector: null,
+ _preloadCount: 0,
+ _isPreloadFromFailed: false,
+ _progressOriginalWidth: 0,
+ _isLandScape: false,
+ _scaleFactor: null,
+
+ ctor: function (config) {
+ this._super();
+ if (config) {
+ cc.LoaderLayer.setConfig(config);
+ }
+ },
+ onEnter: function () {
+ this._super();
+ this.initView();
+ var config = cc.LoaderLayer._finalConfig;
+ if (config.onEnter) {
+ config.onEnter(this);
+ }
+ },
+ onExit: function () {
+ this._super();
+ var config = cc.LoaderLayer._finalConfig;
+ if (config.logo.action) {
+ config.logo.action.release();
+ }
+ if(config.title.action){
+ config.title.action.release();
+ }
+ if (config.onExit) {
+ config.onExit(this);
+ }
+ },
+ initView: function () {
+ var config = cc.LoaderLayer._finalConfig;
+ this._contentLayer = new cc.Layer();
+ this._isLandScape = cc.winSize.width > cc.winSize.height;
+ this._scaleFactor = !cc.LoaderLayer._useDefaultSource ? 1 : cc.winSize.width > cc.winSize.height ? cc.winSize.width / 720 : cc.winSize.width / 480;
+
+ //background
+ this.backgroundSprite = new cc.Sprite(config.background.res);
+ this.addChild(this.backgroundSprite);
+ this.backgroundSprite.x = 0, this.backgroundSprite.y = 0, this.backgroundSprite.anchorX = 0, this.backgroundSprite.anchorY = 0;
+ if (cc.LoaderLayer._useDefaultSource) {
+ this.backgroundSprite.scaleX = cc.winSize.width / this.backgroundSprite.width;
+ this.backgroundSprite.scaleY = cc.winSize.height / this.backgroundSprite.height;
+ }
+
+ //title
+ if (config.title.show) {
+ this.titleSprite = new cc.Sprite(config.title.res);
+ var defaultTitlePosition = cc.pAdd(cc.visibleRect.center, cc.p(0, this._scaleFactor < 1 ? 0 : this._isLandScape ? -80 : 30));
+ this.titleSprite.setPosition(config.title.position ? config.title.position : defaultTitlePosition);
+ this._contentLayer.addChild(this.titleSprite);
+ if (config.title.action) {
+ this.titleSprite.runAction(config.title.action);
+ }
+ }
+
+ //logo
+ if (config.logo.show) {
+ this.logoSprite = new cc.Sprite(config.logo.res);
+ var defaultLogoPosition = cc.pAdd(cc.visibleRect.top, cc.p(0, this._scaleFactor < 1 ? 0 : -this.logoSprite.height / 2 - (this._isLandScape ? 56 : 76)));
+ this.logoSprite.setPosition(config.logo.position ? config.logo.position : defaultLogoPosition);
+ this._contentLayer.addChild(this.logoSprite);
+ if (config.logo.action) {
+ this.logoSprite.runAction(config.logo.action);
+ }
+ }
+
+ //progressbar
+ if (config.progressBar.show) {
+ this.progressBarSprite = new cc.Sprite(config.progressBar.res);
+ this._progressOriginalWidth = this.progressBarSprite.width;
+ this.progressBackgroundSprite = new cc.Sprite(config.progressBar.barBackgroundRes);
+ this.progressBarSprite.anchorX = 0;
+ this.progressBarSprite.anchorY = 0;
+ if (cc.LoaderLayer._isDefaultProgress) {
+ this._barPoint = new cc.Sprite(config.progressBar.barPoint);
+ this.progressBarSprite.addChild(this._barPoint);
+ }
+ if (config.progressBar.barBackgroundRes == null) {
+ this.progressBackgroundSprite.setTextureRect(cc.rect(0, 0, this.progressBarSprite.width, this.progressBarSprite.height));
+ }
+ if (config.progressBar.offset == null) {
+ var deltaProgressWithX = (this.progressBackgroundSprite.width - this.progressBarSprite.width) / 2;
+ var deltaProgressWithY = (this.progressBackgroundSprite.height - this.progressBarSprite.height) / 2;
+ config.progressBar.offset = cc.p(deltaProgressWithX, deltaProgressWithY);
+ }
+ this.progressBarSprite.setPosition(config.progressBar.offset);
+ this.progressBackgroundSprite.addChild(this.progressBarSprite);
+ var defaultProgressPosition = cc.pAdd(cc.visibleRect.bottom, cc.p(0, this.progressBarSprite.height / 2 + this._isLandScape ? 60 : 80));
+ this.progressBackgroundSprite.setPosition(config.progressBar.position ? config.progressBar.position : defaultProgressPosition);
+ this._contentLayer.addChild(this.progressBackgroundSprite);
+ this._setProgress(0);
+ }
+
+ //tips
+ if (config.tips.show) {
+ this.tipsLabel = new cc.LabelTTF("100%", "Arial", config.tips.fontSize);
+ this.tipsLabel.setColor(config.tips.color ? config.tips.color : cc.color(255, 255, 255));
+ this.tipsLabel.setPosition(config.tips.position ? config.tips.position : this.progressBackgroundSprite ? cc.p(this.progressBackgroundSprite.x, this.progressBackgroundSprite.y + this.progressBackgroundSprite.height / 2 + 20) : cc.pAdd(cc.visibleRect.bottom, cc.p(0, 100)));
+ this._contentLayer.addChild(this.tipsLabel);
+ }
+ this.addChild(this._contentLayer);
+ if (this._scaleFactor < 1) {
+ this._contentLayer.setScale(this._scaleFactor);
+ this._contentLayer.setPosition(cc.pAdd(this._contentLayer.getPosition(), cc.p(0, -50)));
+ }
+
+ },
+ _setProgress: function (percent) {
+ if (this.progressBarSprite) {
+ percent < 1 ? percent : 1;
+ var width = percent * this._progressOriginalWidth;
+ this.progressBarSprite.setTextureRect(cc.rect(0, 0, width, this.progressBarSprite.height));
+ if (cc.LoaderLayer._isDefaultProgress) {
+ this._barPoint.setPosition(cc.p(this.progressBarSprite.width, this.progressBarSprite.height / 2));
+ }
+ }
+ },
+ setTipsString: function (str) {
+ if (this.tipsLabel != null) {
+ this.tipsLabel.setString(str);
+ }
+ },
+ getProgressBar: function () {
+ return this.progressBarSprite;
+ },
+ getTipsLabel: function () {
+ return this.tipsLabel;
+ },
+ getLogoSprite: function () {
+ return this.logoSprite;
+ },
+ getTitleSprite: function () {
+ return this.titleSprite;
+ },
+ updateGroup: function (groupname, callback, target) {
+ this._groupname = groupname;
+ this._callback = callback;
+ this._selector = target;
+ },
+ _resetLoadingLabel: function () {
+ this.setTipsString("");
+ this._setProgress(0);
+ },
+ _preloadSource: function () {
+ cc.log("cc.LoaderLayer is preloading resource group: " + this._groupname);
+ this._resetLoadingLabel();
+ if (cc.sys.isNative) {
+ cc.Loader.preload(this._groupname, this._preload_native, this);
+ } else {
+ this._preload_html5();
+ }
+ },
+ _preload_html5: function () {
+ var res = "";
+ var groupIndex = [];
+ var config = cc.LoaderLayer._finalConfig;
+ var groups = cc.LoaderLayer.groups;
+ if (cc.isString(this._groupname)) {
+ if (this._groupname.indexOf(".") != -1) {
+ res = [this._groupname];
+ } else {
+ res = groups[this._groupname];
+ }
+ } else if (cc.isArray(this._groupname)) {
+ res = [];
+ for (var i = 0; i < this._groupname.length; i++) {
+ var group = groups[this._groupname[i]];
+ var files = group && group.files;
+ var preCount = i > 0 ? groupIndex[i - 1] : 0;
+ groupIndex.push(preCount + files ? files.length : 0);
+ res = res.concat(files);
+ }
+ }
+ var self = this;
+ //var progressFunction = self.config.progressCallback ? self.config.progressCallback : null;
+ cc.loader.load(res, function (result, count, loadedCount) {
+ var checkGroupName = function (loadedCount) {
+ for (var i = 0; i < groupIndex.length; i++) {
+ if (groupIndex[i] >= loadedCount) {
+ return self._groupname[i];
+ }
+ }
+ };
+ var groupName = checkGroupName(loadedCount);
+ var status = {
+ groupName: groupName,
+ isCompleted: false,
+ percent: (loadedCount / count * 100) | 0,//(float),
+ stage: 1, //(1 download,2 unzip)
+ isFailed: false
+ }
+ if (status.percent != 0) {
+ self._setProgress(status.percent / 100);
+ }
+ config.tips.tipsProgress(status, self);
+ }, function () {
+ self.removeFromParent();
+ self._preloadCount--;
+ if (self._callback) {
+ if (self._selector) {
+ self._callback(self._selector, true);
+ } else {
+ self._callback(true);
+ }
+ }
+ });
+ },
+ _preload_native: function (status) {
+ cc.log(JSON.stringify(status));
+ var config = cc.LoaderLayer._finalConfig;
+ if (status.percent) {
+ this._setProgress(status.percent / 100);
+ }
+ if (config.tips.tipsProgress) {
+ config.tips.tipsProgress(status, this);
+ }
+ if (status.isCompleted || status.isFailed) {
+ this._preloadCount--;
+
+ if (status.isCompleted) {
+ cc.log("preload finish!");
+ this._isPreloadFromFailed = false;
+ }
+ if (status.isFailed) {
+ cc.log("preload failed!");
+ this._isPreloadFromFailed = true;
+ }
+
+ // Remove loading layer from scene after loading was done.
+ if (this._preloadCount == 0 && !this._isPreloadFromFailed) {
+ this.removeFromParent();
+ if (cc.LoaderLayer._useDefaultSource) {
+ var _config = cc.runtime.config.design_resolution || {width: 480, height: 720, policy: "SHOW_ALL"};
+ cc.view.setDesignResolutionSize(_config.width, _config.height, cc.ResolutionPolicy[_config.policy]);
+ }
+ }
+
+ // Callback must be invoked after removeFromParent.
+ this._callback.call(this._target, status);
+ }
+ },
+ _addToScene: function () {
+ if (this._preloadCount == 0 && !this._isPreloadFromFailed) {
+ if (cc.sys.isNative && cc.LoaderLayer._useDefaultSource) {
+ var config = cc.runtime.config.design_resolution;
+ var isLandscape = false;
+ var isLargeThanResource = false;
+ if (config) {
+ var orientation = cc.runtime.config.orientation;
+ cc.log("_addToScene orientation is " + orientation);
+ if (orientation == "landscape") {
+ isLandscape = true;
+ isLargeThanResource = config.width > 720 || config.height > 480;
+ } else {
+ isLargeThanResource = config.width > 480 || config.height > 720;
+ }
+ }
+ cc.log("isLargeThanResource is " + isLargeThanResource);
+ cc.view.setDesignResolutionSize(isLargeThanResource ? config.width : isLandscape ? 720 : 480, isLargeThanResource ? config.height : isLandscape ? 480 : 720, cc.ResolutionPolicy["FIXED_HEIGHT"]);
+ }
+ cc.director.getRunningScene().addChild(this, INT_MAX - 1);
+ }
+ this._preloadCount++;
+ }
+});
+cc.LoaderLayer._config = {//default setting for loaderlayer
+ background: {
+ res: "res_engine/preload_bg.jpg"
+ },
+ title: {
+ show: true,
+ res: "res_engine/preload_title.png",
+ position: null,
+ action: null
+ },
+ logo: {
+ res: "res_engine/preload_logo.png",
+ show: true,
+ position: null
+ },
+ progressBar: {
+ show: true,
+ res: "res_engine/progress_bar.png",
+ offset: null,
+ position: null,
+ barBackgroundRes: "res_engine/progress_bg.png",
+ barPoint: "res_engine/progress_light.png",
+ barShadow: "res_engine/shadow.png"
+ },
+ tips: {
+ show: true,
+ fontSize: 22,
+ position: null,
+ color: null,
+ tipsProgress: function (status, loaderlayer) {
+ if(loaderlayer.getTipsLabel()){
+ var statusStr = "æ£åœ¨";
+ if (status.stage == cc.network.preloadstatus.DOWNLOAD) {
+ statusStr += "下载";
+ } else if (status.stage == cc.network.preloadstatus.UNZIP) {
+ statusStr += "解压";
+ }
+ if (status.groupName) {
+ statusStr += status.groupName;
+ }
+ statusStr += "进度:" + status.percent.toFixed(2) + "%";
+ loaderlayer.getTipsLabel().setString(statusStr);
+ }
+ }
+ },
+ progressCallback: function (progress) {
+
+ },
+ onEnter: function (layer) {
+ cc.log("LoaderLayer onEnter");
+ },
+ onExit: function (layer) {
+ cc.log("LoaderLayer onExit");
+ }
+}
+
+var res_engine_loaded = false;
+
+cc.LoaderLayer.preload = function (groupname, callback, target) {
+ var loaderLayer = new cc.LoaderLayer();
+ var preloadCb = function (status) {
+ if (status.isFailed) {
+ var tips, conirmfunc, cancelfunc;
+ switch (status.errorCode) {
+ case "err_no_space":
+ {
+ tips = "空间ä¸è¶³ï¼Œè¯·æ¸…ç†ç£ç›˜ç©ºé—´";
+ conirmfunc = function () {
+ callPreload();
+ };
+ cancelfunc = function () {
+ cc.director.end();
+ };
+ break;
+ }
+ case "err_verify":
+ {
+ tips = "æ ¡éªŒå¤±è´¥ï¼Œæ˜¯å¦é‡æ–°ä¸‹è½½ï¼Ÿ";
+ conirmfunc = function () {
+ callPreload();
+ }
+ cancelfunc = function () {
+ cc.director.end();
+ }
+ break;
+ }
+ case "err_network":
+ {
+ tips = "网络异常是å¦é‡æ–°ä¸‹è½½";
+ conirmfunc = function () {
+ callPreload();
+ }
+ cancelfunc = function () {
+ cc.director.end();
+ }
+ break;
+ }
+ default :
+ {
+ conirmfunc = cancelfunc = function () {
+
+ }
+ }
+ }
+ cc._NetworkErrorDialog._show(status.errorCode, tips, conirmfunc, cancelfunc);
+ } else {
+ if (callback) {
+ if (target) {
+ callback.call(target, !status.isFailed);
+ } else {
+ callback(!status.isFailed)
+ }
+ }
+ }
+ }
+ var callPreload = function () {
+ loaderLayer.updateGroup(groupname, preloadCb, target);
+ loaderLayer._addToScene();
+ loaderLayer._preloadSource();
+ };
+
+ if (res_engine_loaded) {
+ callPreload();
+ return;
+ }
+
+ if (!cc.director.getRunningScene()) {
+ cc.director.runScene(new cc.Scene());
+ }
+
+ // Res engine not loaded, load them
+ cc.loader.load([
+ GROUP_JSON_PATH,
+ cc.LoaderLayer._finalConfig.background.res,
+ cc.LoaderLayer._finalConfig.title.res,
+ cc.LoaderLayer._finalConfig.logo.res,
+ cc.LoaderLayer._finalConfig.progressBar.res,
+ cc.LoaderLayer._finalConfig.progressBar.barBackgroundRes,
+ cc.LoaderLayer._finalConfig.progressBar.barPoint,
+ cc.LoaderLayer._finalConfig.progressBar.barShadow,
+ cc.Dialog._finalConfig.background.res,
+ cc.Dialog._finalConfig.confirmBtn.normalRes,
+ cc.Dialog._finalConfig.confirmBtn.pressRes,
+ cc.Dialog._finalConfig.cancelBtn.normalRes,
+ cc.Dialog._finalConfig.cancelBtn.pressRes
+ ],
+ function (result, count, loadedCount) {
+ var percent = (loadedCount / count * 100) | 0;
+ percent = Math.min(percent, 100);
+ cc.log("Preloading engine resources... " + percent + "%");
+ }, function () {
+ var groups = cc.loader.getRes(GROUP_JSON_PATH);
+ if (groups) {
+ cc.LoaderLayer.groups = groups;
+ }
+ else {
+ cc.warn("Group versions haven't been loaded, you can also set group data with 'cc.LoaderLayer.groups'");
+ }
+ res_engine_loaded = true;
+ callPreload();
+ });
+};
+
+cc.LoaderLayer._useDefaultSource = true;
+cc.LoaderLayer._isDefaultProgress = true;
+cc.LoaderLayer._finalConfig = cc.LoaderLayer._config;
+cc.LoaderLayer.groups = {};
+cc.LoaderLayer.setUseDefaultSource = function (status) {
+ cc.LoaderLayer._useDefaultSource = status;
+};
+cc.LoaderLayer.setConfig = function (config) {
+ if(config.title && config.title.action){
+ config.title.action.retain();
+ }
+ if(config.logo && config.logo.action){
+ config.logo.action.retain();
+ }
+ this._initData(config);
+};
+cc.LoaderLayer._initData = function (uConfig) {
+ this._finalConfig = cc.clone(this._config);
+ var config = this._finalConfig;
+ if (uConfig != null) {
+ if (uConfig.background && uConfig.background.res) {
+ config.background.res = uConfig.background.res;
+ }
+ if (uConfig.title) {
+ var uTitle = uConfig.title;
+ var title = config.title;
+ title.show = typeof uTitle.show != "undefined" ? uTitle.show : title.show;
+ title.res = uTitle.res ? uTitle.res : title.res;
+ title.position = uTitle.position ? uTitle.position : title.position;
+ title.action = uTitle.action ? uTitle.action : title.action;
+ if (title.action) {
+ title.action = uTitle.action;
+ title.action.retain();
+ }
+ }
+ if (uConfig.logo) {
+ var uLogo = uConfig.logo;
+ var logo = config.logo;
+ logo.show = typeof uLogo.show != "undefined" ? uLogo.show : logo.show;
+ logo.res = uLogo.res ? uLogo.res : logo.res;
+ logo.position = uLogo.position ? uLogo.position : logo.position;
+ if (typeof uLogo.action != "undefined") {
+ logo.action = uLogo.action;
+ if (logo.action) {
+ logo.action.retain();
+ }
+ }
+ }
+ if (uConfig.progressBar) {
+ var uProgress = uConfig.progressBar;
+ var progress = config.progressBar;
+ progress.show = typeof uProgress.show != "undefined" ? uProgress.show : progress.show;
+ if (uProgress.res) {
+ progress.res = uProgress.res;
+ this._isDefaultProgress = false;
+ }
+ progress.offset = uProgress.offset ? uProgress.offset : progress.offset;
+ progress.position = uProgress.position ? uProgress.position : progress.position;
+ progress.barBackgroundRes = uProgress.barBackgroundRes ? uProgress.barBackgroundRes : progress.barBackgroundRes;
+ }
+ if (uConfig.tips) {
+ var uTips = uConfig.tips;
+ var tips = config.tips;
+ tips.show = typeof uTips.show != "undefined" ? uTips.show : tips.show;
+ tips.res = uTips.res ? uTips.res : tips.res;
+ tips.offset = uTips.offset ? uTips.offset : tips.offset;
+ tips.fontSize = uTips.fontSize ? uTips.fontSize : tips.fontSize;
+ tips.position = uTips.position ? uTips.position : tips.position;
+ tips.color = uTips.color ? uTips.color : tips.color;
+ if (uConfig.tips.tipsProgress && typeof uConfig.tips.tipsProgress == "function") {
+ tips.tipsProgress = uConfig.tips.tipsProgress;
+ }
+ }
+ if (typeof uConfig.onEnter == "function") {
+ config.onEnter = uConfig.onEnter;
+ }
+ if (typeof uConfig.onExit == "function") {
+ config.onExit = uConfig.onExit;
+ }
+ }
+
+ if (typeof config.logo.action == "undefined" && this._useDefaultSource) {
+ config.logo.action = cc.sequence(
+ cc.spawn(cc.moveBy(0.4, cc.p(0, 40)).easing(cc.easeIn(0.5)), cc.scaleTo(0.4, 0.95, 1.05).easing(cc.easeIn(0.5))),
+ cc.delayTime(0.08),
+ cc.spawn(cc.moveBy(0.4, cc.p(0, -40)).easing(cc.easeOut(0.5)), cc.scaleTo(0.4, 1.05, 0.95).easing(cc.easeOut(0.5)))
+ ).repeatForever();
+ config.logo.action.retain();
+ }
+ if (!config.tips.color) {
+ config.tips.color = cc.color(255, 255, 255);
+ }
+};
+
+cc.Dialog = cc.Layer.extend({
+ _defaultConfig: null,
+ backgroundSprite: null,
+ _menuItemConfirm: null,
+ _menuItemCancel: null,
+ _messageLabel: null,
+ _eventListener: null,
+ _scaleFactor: null,
+
+ ctor: function (config) {
+ this._super();
+ this.setConfig(config);
+ },
+ setConfig: function (config) {
+ this.removeAllChildren();
+ if (config) {
+ cc.Dialog.setConfig(config);
+ }
+ },
+ initView: function () {
+ var useDefaultSource = cc.Dialog._useDefaultSource;
+ var winSize = cc.director.getWinSize();
+ this._scaleFactor = !useDefaultSource ? 1 : winSize.width > winSize.height ? winSize.width / 720 : winSize.width / 480;
+ var config = cc.Dialog._finalConfig;
+
+ //bg
+ this.backgroundSprite = new cc.Scale9Sprite(config.background.res);
+ this._setScale(this.backgroundSprite);
+ if (this._scaleFactor < 1) {
+ this.backgroundSprite.setScale(this._scaleFactor);
+ }
+ this.backgroundSprite.setPosition(config.position ? config.position : cc.p(winSize.width / 2, winSize.height / 2));
+
+ //menu
+ this.menuItemConfirm = this._createMenuItemSprite(config.confirmBtn, this._confirmCallback);
+ this.menuItemCancel = this._createMenuItemSprite(config.cancelBtn, this._cancelCallback);
+ this.menuItemCancel.setPosition(config.cancelBtn.position ? config.cancelBtn.position : cc.p(this.backgroundSprite.width / 2 - this.menuItemCancel.width / 2 - 20, this.menuItemCancel.height + 20));
+ this.menuItemConfirm.setPosition(config.confirmBtn.position ? config.confirmBtn.position : cc.p(this.backgroundSprite.width / 2 + this.menuItemConfirm.width / 2 + 20, this.menuItemConfirm.height + 20));
+ var menu = new cc.Menu(this.menuItemConfirm, this.menuItemCancel);
+ menu.setPosition(cc.p(0, 0));
+ this.backgroundSprite.addChild(menu);
+
+ //message
+ var fontSize = config.messageLabel.fontSize ? config.messageLabel.fontSize : this._scaleFactor > 1 ? 16 * this._scaleFactor : 16;
+ this.messageLabel = new cc.LabelTTF(config.messageLabel.text, "Arial", fontSize);
+ this.messageLabel.setDimensions(config.messageLabel.dimensions ? config.messageLabel.dimensions : cc.size(this.backgroundSprite.width - 30, this.backgroundSprite.height - this.menuItemConfirm.y - 10));
+ this.messageLabel.setColor(config.messageLabel.color ? config.messageLabel.color : cc.color(255, 255, 255));
+ this.messageLabel.setPosition(config.messageLabel.position ? config.messageLabel.position : cc.p(this.backgroundSprite.width / 2, this.backgroundSprite.height - this.messageLabel.height / 2 - 20));
+ this.backgroundSprite.addChild(this.messageLabel);
+ if (!config.action) {
+ var action = cc.sequence(cc.EaseIn.create(cc.scaleTo(0.1, this.backgroundSprite.scale + 0.02), 0.4), cc.EaseOut.create(cc.scaleTo(0.1, this.backgroundSprite.scale), 0.3));
+ this.backgroundSprite.runAction(action);
+ } else {
+ this.backgroundSprite.runAction(config.action);
+ }
+ this.addChild(this.backgroundSprite);
+
+ },
+ _createMenuItemSprite: function (res, callback) {
+ var spriteNormal = new cc.Scale9Sprite(res.normalRes);
+ var spritePress = new cc.Scale9Sprite(res.pressRes);
+ this._setScale(spriteNormal);
+ this._setScale(spritePress);
+ var fontSize = res.fontSize ? res.fontSize : this._scaleFactor > 1 ? 16 * this._scaleFactor : 16;
+ var menuLabel = new cc.LabelTTF(res.text, "Arial", fontSize);
+ menuLabel.setColor(res.textColor);
+ var menuItem = new cc.MenuItemSprite(spriteNormal, spritePress, callback, this);
+ menuLabel.setPosition(cc.p(menuItem.width / 2, menuItem.height / 2));
+ menuItem.addChild(menuLabel);
+ return menuItem;
+ },
+ _setScale: function (s9Sprite) {
+ if (this._scaleFactor > 1) {
+ s9Sprite.setContentSize(cc.size(this._scaleFactor * s9Sprite.width, this._scaleFactor * s9Sprite.height));
+ }
+ },
+ _confirmCallback: function () {
+ var config = cc.Dialog._finalConfig;
+ if (config.confirmBtn.callback) {
+ if (config.target) {
+ config.confirmBtn.callback.call(config.target, this);
+ } else {
+ config.confirmBtn.callback(this);
+ }
+ }
+ this.removeFromParent();
+ },
+ _cancelCallback: function () {
+ var config = cc.Dialog._finalConfig;
+ if (config.cancelBtn.callback) {
+ if (config.target) {
+ config.cancelBtn.callback.call(config.target, this);
+ } else {
+ config.cancelBtn.callback(this);
+ }
+ }
+ this.removeFromParent();
+ },
+ onEnter: function () {
+ this._super();
+ var config = cc.Dialog._finalConfig;
+ this.initView();
+ config.onEnter(this);
+ var self = this;
+ self._eventListener = cc.EventListener.create({
+ event: cc.EventListener.TOUCH_ONE_BY_ONE,
+ swallowTouches: true,
+ onTouchBegan: function (touch, event) {
+ return true;
+ }
+ });
+ cc.eventManager.addListener(self._eventListener, self);
+ },
+ onExit: function () {
+ this._super();
+ var config = cc.Dialog._finalConfig;
+ config.onExit(this);
+ this.removeAllChildren();
+ cc.Dialog._dialog = null;
+ cc.eventManager.removeListener(this._eventListener);
+ }
+});
+
+cc.Dialog._dialog = null;
+cc.Dialog._clearDialog = function () {
+ if (cc.Dialog._dialog != null) {
+ cc.Dialog._dialog.removeFromParent();
+ cc.Dialog._dialog = null;
+ }
+}
+
+cc.Dialog.show = function (tips, confirmCb, cancelCb) {
+ if (cc.Dialog._dialog != null) {
+ cc.log("other dialog is on the screen,this dialog can't show now");
+ return;
+ }
+
+ var conf;
+ if (typeof tips == "string") {
+ conf = {
+ messageLabel: {
+ text: tips
+ },
+ confirmBtn: {
+ callback: confirmCb
+ },
+ cancelBtn: {
+ callback: cancelCb
+ }
+ }
+ } else if (typeof tips == "object") {
+ conf = tips;
+ } else {
+ cc.log("tips is invalid");
+ return;
+ }
+
+ cc.Dialog._dialog = new cc.Dialog(conf);
+ if (cc.director.getRunningScene()) {
+ cc.director.getRunningScene().addChild(cc.Dialog._dialog, INT_MAX);
+ } else {
+ cc.log("Current scene is null we can't show dialog");
+ }
+};
+cc.Dialog._useDefaultSource = true;
+cc.Dialog.setUseDefaultSource = function (status) {
+ cc.Dialog._useDefaultSource = status;
+}
+cc.Dialog._defaultConfig = {
+ position: null,
+ target: null,
+ action: null,
+ background: {
+ res: "res_engine/dialog_bg.png"
+ },
+ confirmBtn: {
+ normalRes: "res_engine/dialog_confirm_normal.png",
+ pressRes: "res_engine/dialog_confirm_press.png",
+ text: "确定",
+ textColor: null,
+ fontSize: null,
+ position: null,
+ callback: function () {
+ cc.log("this is confirm callback");
+ }
+ },
+ cancelBtn: {
+ normalRes: "res_engine/dialog_cancel_normal.png",
+ pressRes: "res_engine/dialog_cancel_press.png",
+ text: "å–æ¶ˆ",
+ textColor: null,
+ position: null,
+ fontSize: null,
+ callback: function () {
+ cc.log("this is cancel callback");
+ }
+ },
+ messageLabel: {
+ text: "",
+ color: null,
+ dimensions: null,
+ fontSize: null,
+ position: null
+ },
+ onEnter: function (dialog) {
+ cc.log("dialog call onEnter");
+ },
+ onExit: function (dialog) {
+ cc.log("dialog call onExit");
+ }
+};
+cc.Dialog._finalConfig = cc.Dialog._defaultConfig;
+cc.Dialog.setConfig = function (config) {
+ this._initData(config);
+};
+cc.Dialog._initData = function (uConfig) {
+ this._finalConfig = cc.clone(this._defaultConfig);
+ var config = this._finalConfig;
+ if (uConfig != null) {
+ if (uConfig.position) {
+ config.position = uConfig.position;
+ }
+ if (uConfig.action) {
+ config.action = uConfig.action;
+ }
+ if (uConfig.background && uConfig.background.res) {
+ config.background = uConfig.background;
+ }
+ if (uConfig.confirmBtn) {
+ var uConfirmBtn = uConfig.confirmBtn;
+ var confirmBtn = config.confirmBtn;
+ confirmBtn.normalRes = uConfirmBtn.normalRes ? uConfirmBtn.normalRes : confirmBtn.normalRes;
+ confirmBtn.pressRes = uConfirmBtn.pressRes ? uConfirmBtn.pressRes : confirmBtn.pressRes;
+ confirmBtn.text = typeof uConfirmBtn.text != "undefined" ? uConfirmBtn.text : confirmBtn.text;
+ confirmBtn.textColor = uConfirmBtn.textColor ? uConfirmBtn.textColor : confirmBtn.textColor;
+ confirmBtn.fontSize = uConfirmBtn.fontSize ? uConfirmBtn.fontSize : confirmBtn.fontSize;
+ confirmBtn.position = uConfirmBtn.position ? uConfirmBtn.position : confirmBtn.position;
+ confirmBtn.callback = uConfirmBtn.callback ? uConfirmBtn.callback : confirmBtn.callback;
+ }
+ if (uConfig.cancelBtn) {
+ var uCancelBtn = uConfig.cancelBtn;
+ var cancelBtn = config.cancelBtn;
+ cancelBtn.normalRes = uCancelBtn.normalRes ? uCancelBtn.normalRes : cancelBtn.normalRes;
+ cancelBtn.pressRes = uCancelBtn.pressRes ? uCancelBtn.pressRes : cancelBtn.pressRes;
+ cancelBtn.text = typeof uCancelBtn.text != "undefined" ? uCancelBtn.text : cancelBtn.text;
+ cancelBtn.textColor = uCancelBtn.textColor ? uCancelBtn.textColor : cancelBtn.textColor;
+ cancelBtn.fontSize = uCancelBtn.fontSize ? uCancelBtn.fontSize : cancelBtn.fontSize;
+ cancelBtn.position = uCancelBtn.position ? uCancelBtn.position : cancelBtn.position;
+ cancelBtn.callback = uCancelBtn.callback ? uCancelBtn.callback : cancelBtn.callback;
+ }
+ if (uConfig.messageLabel) {
+ var uMessageLabel = uConfig.messageLabel;
+ var messageLabel = config.messageLabel;
+ messageLabel.text = typeof uMessageLabel.text != "undefined" ? uMessageLabel.text : messageLabel.text;
+ messageLabel.color = uMessageLabel.color ? uMessageLabel.color : messageLabel.color;
+ messageLabel.fontSize = uMessageLabel.fontSize ? uMessageLabel.fontSize : messageLabel.fontSize;
+ messageLabel.position = uMessageLabel.position ? uMessageLabel.position : messageLabel.position;
+ messageLabel.dimensions = uMessageLabel.dimensions ? uMessageLabel.dimensions : messageLabel.dimensions;
+ }
+ if (uConfig.target) {
+ config.target = uConfig.target;
+ }
+ if (typeof uConfig.onEnter == "function") {
+ config.onEnter = uConfig.onEnter;
+ }
+ if (typeof uConfig.onExit == "function") {
+ config.onExit = uConfig.onExit;
+ }
+ }
+
+ if (!config.cancelBtn.textColor) {
+ config.cancelBtn.textColor = cc.color(255, 255, 255);
+ }
+ if (!config.confirmBtn.textColor) {
+ config.confirmBtn.textColor = cc.color(255, 255, 255);
+ }
+};
+
+cc._NetworkErrorDialog = function () {
+ cc.Dialog._clearDialog();
+ cc.Dialog._dialog = new cc.Dialog(cc._NetworkErrorDialog._config);
+ return cc.Dialog._dialog;
+}
+cc._NetworkErrorDialog._config = {
+ networkError: {},
+ spaceError: {},
+ verifyError: {}
+};
+cc._NetworkErrorDialog._show = function (type, tips, confirmCb, cancelCb) {
+ var networkDialog = cc._NetworkErrorDialog();
+ var config;
+ switch (type) {
+ case "err_network":
+ {
+ config = cc._NetworkErrorDialog._config.networkError;
+ break;
+ }
+ case "err_no_space":
+ {
+ config = cc._NetworkErrorDialog._config.spaceError;
+ break;
+ }
+ case "err_verify":
+ {
+ config = cc._NetworkErrorDialog._config.verifyError;
+ break;
+ }
+ default:
+ {
+ cc.log("type is not found");
+ return;
+ }
+ }
+ if (!networkDialog.getParent()) {
+
+ config.confirmBtn = config.confirmBtn || {};
+ config.confirmBtn.callback = function () {
+ if (confirmCb)
+ confirmCb();
+ }
+
+ config.cancelBtn = config.cancelBtn || {};
+ config.cancelBtn.callback = function () {
+ if (cancelCb)
+ cancelCb();
+ }
+
+ config.messageLabel = config.messageLabel || {};
+ if (typeof config.messageLabel.text == "undefined") {
+ config.messageLabel.text = tips;
+ }
+
+ networkDialog.setConfig(config);
+ if (cc.director.getRunningScene()) {
+ cc.director.getRunningScene().addChild(networkDialog, INT_MAX);
+ } else {
+ cc.log("Current scene is null we can't show dialog");
+ }
+ }
+}
+
+cc._NetworkErrorDialog._setConfig = function (key, config) {
+ if (key && config) {
+ switch (key) {
+ case "err_network":
+ {
+ cc._NetworkErrorDialog._config.networkError = config;
+ break;
+ }
+ case "err_no_space":
+ {
+ cc._NetworkErrorDialog._config.spaceError = config;
+ break;
+ }
+ case "err_verify":
+ {
+ cc._NetworkErrorDialog._config.verifyError = config;
+ break;
+ }
+ }
+ }
+}
+
+cc.runtime = cc.runtime || {};
+
+cc.runtime.setOption = function (promptype, config) {
+ if (config) {
+ switch (promptype) {
+ case "network_error_dialog":
+ {
+ cc._NetworkErrorDialog._setConfig("err_network", config);
+ break;
+ }
+ case "no_space_error_dialog":
+ {
+ cc._NetworkErrorDialog._setConfig("err_no_space", config);
+ break;
+ }
+ case "verify_error_dialog":
+ {
+ cc._NetworkErrorDialog._setConfig("err_verify", config);
+ break;
+ }
+ default :
+ {
+ cc.log("promptype not found please check your promptype");
+ }
+ }
+ } else {
+ cc.log("config is null please check your config");
+ }
+}
+
+/**
+ * only use in JSB get network type
+ * @type {{}|*|cc.network}
+ */
+cc.network = cc.network || {};
+cc.network.type = {
+ NO_NETWORK: -1,
+ MOBILE: 0,
+ WIFI: 1
+}
+cc.network.preloadstatus = {
+ DOWNLOAD: 1,
+ UNZIP: 2
+}
+cc.runtime.network = cc.network;
+
+})();
+
+cc.LoaderScene._preload = cc.LoaderScene.preload;
+cc.LoaderScene.preload = function (arr, cb, target) {
+ // No extension
+ var isGroups = (arr[0] && arr[0].indexOf('.') === -1);
+ if (isGroups) {
+ if (arr.indexOf('boot') === -1) {
+ arr.splice(0, 0, 'boot');
+ }
+ cc.LoaderLayer.preload(arr, cb, target);
+ }
+ else {
+ cc.LoaderScene._preload(arr, cb, target);
+ }
+}
diff --git a/extensions/spine/CCSkeleton.js b/extensions/spine/CCSkeleton.js
new file mode 100644
index 0000000000..97a99f4edb
--- /dev/null
+++ b/extensions/spine/CCSkeleton.js
@@ -0,0 +1,381 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2014 Shengxiang Chen (Nero Chan)
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The main namespace of Spine, all classes, functions, properties and constants of Spine are defined in this namespace
+ * @namespace
+ * @name sp
+ */
+var sp = sp || {};
+
+var spine = sp.spine;
+
+/**
+ *
+ * The skeleton of Spine.
+ * Skeleton has a reference to a SkeletonData and stores the state for skeleton instance,
+ * which consists of the current pose's bone SRT, slot colors, and which slot attachments are visible.
+ * Multiple skeletons can use the same SkeletonData (which includes all animations, skins, and attachments).
+ *
+ * @class
+ * @extends cc.Node
+ */
+sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{
+ _skeleton: null,
+ _rootBone: null,
+ _timeScale: 1,
+ _debugSlots: false,
+ _debugBones: false,
+ _premultipliedAlpha: false,
+ _ownsSkeletonData: null,
+ _atlas: null,
+
+ /**
+ * The constructor of sp.Skeleton. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
+ */
+ ctor:function(skeletonDataFile, atlasFile, scale){
+ cc.Node.prototype.ctor.call(this);
+
+ if(arguments.length === 0)
+ this.init();
+ else
+ this.initWithArgs(skeletonDataFile, atlasFile, scale);
+ },
+
+ _createRenderCmd:function () {
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new sp.Skeleton.CanvasRenderCmd(this);
+ else
+ return new sp.Skeleton.WebGLRenderCmd(this);
+ },
+
+ /**
+ * Initializes a sp.Skeleton. please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
+ */
+ init: function () {
+ cc.Node.prototype.init.call(this);
+ this._premultipliedAlpha = (cc._renderType === cc.game.RENDER_TYPE_WEBGL && cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA);
+ },
+
+ onEnter: function () {
+ cc.Node.prototype.onEnter.call(this);
+ this.scheduleUpdate();
+ },
+
+ onExit: function () {
+ this.unscheduleUpdate();
+ cc.Node.prototype.onExit.call(this);
+ },
+
+ /**
+ * Sets whether open debug slots.
+ * @param {boolean} enable true to open, false to close.
+ */
+ setDebugSolots:function(enable){
+ this._debugSlots = enable;
+ },
+
+ /**
+ * Sets whether open debug bones.
+ * @param {boolean} enable
+ */
+ setDebugBones:function(enable){
+ this._debugBones = enable;
+ },
+
+ /**
+ * Sets whether open debug slots.
+ * @param {boolean} enabled true to open, false to close.
+ */
+ setDebugSlotsEnabled: function(enabled) {
+ this._debugSlots = enabled;
+ },
+
+ /**
+ * Gets whether open debug slots.
+ * @returns {boolean} true to open, false to close.
+ */
+ getDebugSlotsEnabled: function() {
+ return this._debugSlots;
+ },
+
+ /**
+ * Sets whether open debug bones.
+ * @param {boolean} enabled
+ */
+ setDebugBonesEnabled: function(enabled) {
+ this._debugBones = enabled;
+ },
+
+ /**
+ * Gets whether open debug bones.
+ * @returns {boolean} true to open, false to close.
+ */
+ getDebugBonesEnabled: function() {
+ return this._debugBones;
+ },
+
+ /**
+ * Sets the time scale of sp.Skeleton.
+ * @param {Number} scale
+ */
+ setTimeScale:function(scale){
+ this._timeScale = scale;
+ },
+
+ getTimeScale: function(){
+ return this._timeScale;
+ },
+
+ /**
+ * Initializes sp.Skeleton with Data.
+ * @param {sp.spine.SkeletonData|String} skeletonDataFile
+ * @param {String|spine.Atlas|spine.SkeletonData} atlasFile atlas filename or atlas data or owns SkeletonData
+ * @param {Number} [scale] scale can be specified on the JSON or binary loader which will scale the bone positions, image sizes, and animation translations.
+ */
+ initWithArgs: function (skeletonDataFile, atlasFile, scale) {
+ var argSkeletonFile = skeletonDataFile, argAtlasFile = atlasFile,
+ skeletonData, atlas, ownsSkeletonData;
+
+ if (cc.isString(argSkeletonFile)) {
+ if (cc.isString(argAtlasFile)) {
+ var data = cc.loader.getRes(argAtlasFile);
+ sp._atlasLoader.setAtlasFile(argAtlasFile);
+ atlas = new spine.TextureAtlas(data, sp._atlasLoader.load.bind(sp._atlasLoader));
+ } else {
+ atlas = atlasFile;
+ }
+ scale = scale || 1 / cc.director.getContentScaleFactor();
+
+ var attachmentLoader = new spine.AtlasAttachmentLoader(atlas);
+ var skeletonJsonReader = new spine.SkeletonJson(attachmentLoader);
+ skeletonJsonReader.scale = scale;
+
+ var skeletonJson = cc.loader.getRes(argSkeletonFile);
+ skeletonData = skeletonJsonReader.readSkeletonData(skeletonJson);
+ atlas.dispose(skeletonJsonReader);
+ ownsSkeletonData = true;
+ } else {
+ skeletonData = skeletonDataFile;
+ ownsSkeletonData = atlasFile;
+ }
+ this.setSkeletonData(skeletonData, ownsSkeletonData);
+ this.init();
+ },
+
+ /**
+ * Returns the bounding box of sp.Skeleton.
+ * @returns {cc.Rect}
+ */
+ getBoundingBox: function () {
+ var minX = cc.FLT_MAX, minY = cc.FLT_MAX, maxX = cc.FLT_MIN, maxY = cc.FLT_MIN;
+ var scaleX = this.getScaleX(), scaleY = this.getScaleY(), vertices,
+ slots = this._skeleton.slots, VERTEX = spine.RegionAttachment;
+
+ for (var i = 0, slotCount = slots.length; i < slotCount; ++i) {
+ var slot = slots[i];
+ var attachment = slot.attachment;
+ if (!attachment || !(attachment instanceof spine.RegionAttachment))
+ continue;
+ vertices = spine.Utils.setArraySize(new Array(), 8, 0);
+ attachment.computeWorldVertices(slot.bone, vertices, 0, 2);
+ minX = Math.min(minX, vertices[VERTEX.OX1] * scaleX, vertices[VERTEX.OX4] * scaleX, vertices[VERTEX.OX2] * scaleX, vertices[VERTEX.OX3] * scaleX);
+ minY = Math.min(minY, vertices[VERTEX.OY1] * scaleY, vertices[VERTEX.OY4] * scaleY, vertices[VERTEX.OY2] * scaleY, vertices[VERTEX.OY3] * scaleY);
+ maxX = Math.max(maxX, vertices[VERTEX.OX1] * scaleX, vertices[VERTEX.OX4] * scaleX, vertices[VERTEX.OX2] * scaleX, vertices[VERTEX.OX3] * scaleX);
+ maxY = Math.max(maxY, vertices[VERTEX.OY1] * scaleY, vertices[VERTEX.OY4] * scaleY, vertices[VERTEX.OY2] * scaleY, vertices[VERTEX.OY3] * scaleY);
+ }
+ var position = this.getPosition();
+ return cc.rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
+ },
+
+ /**
+ * Computes the world SRT from the local SRT for each bone.
+ */
+ updateWorldTransform: function () {
+ this._skeleton.updateWorldTransform();
+ },
+
+ /**
+ * Sets the bones and slots to the setup pose.
+ */
+ setToSetupPose: function () {
+ this._skeleton.setToSetupPose();
+ },
+
+ /**
+ * Sets the bones to the setup pose, using the values from the `BoneData` list in the `SkeletonData`.
+ */
+ setBonesToSetupPose: function () {
+ this._skeleton.setBonesToSetupPose();
+ },
+
+ /**
+ * Sets the slots to the setup pose, using the values from the `SlotData` list in the `SkeletonData`.
+ */
+ setSlotsToSetupPose: function () {
+ this._skeleton.setSlotsToSetupPose();
+ },
+
+ /**
+ * Finds a bone by name. This does a string comparison for every bone.
+ * @param {String} boneName
+ * @returns {sp.spine.Bone}
+ */
+ findBone: function (boneName) {
+ return this._skeleton.findBone(boneName);
+ },
+
+ /**
+ * Finds a slot by name. This does a string comparison for every slot.
+ * @param {String} slotName
+ * @returns {sp.spine.Slot}
+ */
+ findSlot: function (slotName) {
+ return this._skeleton.findSlot(slotName);
+ },
+
+ /**
+ * Finds a skin by name and makes it the active skin. This does a string comparison for every skin. Note that setting the skin does not change which attachments are visible.
+ * @param {string} skinName
+ * @returns {sp.spine.Skin}
+ */
+ setSkin: function (skinName) {
+ return this._skeleton.setSkinByName(skinName);
+ },
+
+ /**
+ * Returns the attachment for the slot and attachment name. The skeleton looks first in its skin, then in the skeleton data’s default skin.
+ * @param {String} slotName
+ * @param {String} attachmentName
+ * @returns {sp.spine.Attachment}
+ */
+ getAttachment: function (slotName, attachmentName) {
+ return this._skeleton.getAttachmentByName(slotName, attachmentName);
+ },
+
+ /**
+ * Sets the attachment for the slot and attachment name. The skeleton looks first in its skin, then in the skeleton data’s default skin.
+ * @param {String} slotName
+ * @param {String} attachmentName
+ */
+ setAttachment: function (slotName, attachmentName) {
+ this._skeleton.setAttachment(slotName, attachmentName);
+ },
+
+ /**
+ * Sets the premultiplied alpha value to sp.Skeleton.
+ * @param {Number} alpha
+ */
+ setPremultipliedAlpha: function (premultiplied) {
+ this._premultipliedAlpha = premultiplied;
+ },
+
+ /**
+ * Returns whether to enable premultiplied alpha.
+ * @returns {boolean}
+ */
+ isPremultipliedAlpha: function () {
+ return this._premultipliedAlpha;
+ },
+
+ /**
+ * Sets skeleton data to sp.Skeleton.
+ * @param {sp.spine.SkeletonData} skeletonData
+ * @param {sp.spine.SkeletonData} ownsSkeletonData
+ */
+ setSkeletonData: function (skeletonData, ownsSkeletonData) {
+ if(skeletonData.width != null && skeletonData.height != null)
+ this.setContentSize(skeletonData.width / cc.director.getContentScaleFactor(), skeletonData.height / cc.director.getContentScaleFactor());
+
+ this._skeleton = new spine.Skeleton(skeletonData);
+ this._skeleton.updateWorldTransform();
+ this._rootBone = this._skeleton.getRootBone();
+ this._ownsSkeletonData = ownsSkeletonData;
+
+ this._renderCmd._createChildFormSkeletonData();
+ },
+
+ /**
+ * Return the renderer of attachment.
+ * @param {sp.spine.RegionAttachment|sp.spine.BoundingBoxAttachment} regionAttachment
+ * @returns {sp.spine.TextureAtlasRegion}
+ */
+ getTextureAtlas: function (regionAttachment) {
+ return regionAttachment.region;
+ },
+
+ /**
+ * Returns the blendFunc of sp.Skeleton.
+ * @returns {cc.BlendFunc}
+ */
+ getBlendFunc: function () {
+ var slot = this._skeleton.drawOrder[0];
+ if (slot) {
+ var blend = this._renderCmd._getBlendFunc(slot.data.blendMode, this._premultipliedAlpha);
+ return blend;
+ }
+ else {
+ return {};
+ }
+ },
+
+ /**
+ * Sets the blendFunc of sp.Skeleton, it won't have any effect for skeleton, skeleton is using slot's data to determine the blend function.
+ * @param {cc.BlendFunc|Number} src
+ * @param {Number} [dst]
+ */
+ setBlendFunc: function (src, dst) {
+ return;
+ },
+
+ /**
+ * Update will be called automatically every frame if "scheduleUpdate" is called when the node is "live".
+ * @param {Number} dt Delta time since last update
+ */
+ update: function (dt) {
+ this._skeleton.update(dt);
+ }
+});
+
+cc.defineGetterSetter(sp.Skeleton.prototype, "opacityModifyRGB", sp.Skeleton.prototype.isOpacityModifyRGB);
+
+// For renderer webgl to identify skeleton's default texture and blend function
+cc.defineGetterSetter(sp.Skeleton.prototype, "_blendFunc", sp.Skeleton.prototype.getBlendFunc);
+cc.defineGetterSetter(sp.Skeleton.prototype, '_texture', function () {
+ return this._renderCmd._currTexture;
+});
+
+/**
+ * Creates a skeleton object.
+ * @deprecated since v3.0, please use new sp.Skeleton(skeletonDataFile, atlasFile, scale) instead.
+ * @param {spine.SkeletonData|String} skeletonDataFile
+ * @param {String|spine.Atlas|spine.SkeletonData} atlasFile atlas filename or atlas data or owns SkeletonData
+ * @param {Number} [scale] scale can be specified on the JSON or binary loader which will scale the bone positions, image sizes, and animation translations.
+ * @returns {sp.Skeleton}
+ */
+sp.Skeleton.create = function (skeletonDataFile, atlasFile/* or atlas*/, scale) {
+ return new sp.Skeleton(skeletonDataFile, atlasFile, scale);
+};
diff --git a/extensions/spine/CCSkeletonAnimation.js b/extensions/spine/CCSkeletonAnimation.js
new file mode 100644
index 0000000000..17f0f25675
--- /dev/null
+++ b/extensions/spine/CCSkeletonAnimation.js
@@ -0,0 +1,351 @@
+/****************************************************************************
+ Copyright (c) 2011-2012 cocos2d-x.org
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+ Copyright (c) 2014 Shengxiang Chen (Nero Chan)
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+sp._atlasLoader = {
+ spAtlasFile:null,
+ setAtlasFile:function(spAtlasFile){
+ this.spAtlasFile = spAtlasFile;
+ },
+ load:function(line){
+ var texturePath = cc.path.join(cc.path.dirname(this.spAtlasFile), line);
+ var texture = cc.textureCache.addImage(texturePath);
+ var tex = new sp.SkeletonTexture({ width: texture.getPixelsWide(), height: texture.getPixelsHigh() });
+ tex.setRealTexture(texture);
+ return tex;
+ },
+ unload:function(obj){
+ }
+};
+
+/**
+ * The event type of spine skeleton animation. It contains event types: START(0), END(1), COMPLETE(2), EVENT(3).
+ * @constant
+ * @type {{START: number, END: number, COMPLETE: number, EVENT: number}}
+ */
+sp.ANIMATION_EVENT_TYPE = {
+ START: 0,
+ INTERRUPT: 1,
+ END: 2,
+ DISPOSE: 3,
+ COMPLETE: 4,
+ EVENT: 5
+};
+
+sp.TrackEntryListeners = function (startListener, endListener, completeListener, eventListener, interruptListener, disposeListener) {
+ this.startListener = startListener || null;
+ this.endListener = endListener || null;
+ this.completeListener = completeListener || null;
+ this.eventListener = eventListener || null;
+ this.interruptListener = interruptListener || null;
+ this.disposeListener = disposeListener || null;
+ this.callback = null;
+ this.callbackTarget = null;
+ this.skeletonNode = null;
+};
+
+var proto = sp.TrackEntryListeners.prototype;
+proto.start = function(trackEntry) {
+ if (this.startListener) {
+ this.startListener(trackEntry);
+ }
+ if (this.callback) {
+ this.callback.call(this.callbackTarget, this.skeletonNode, trackEntry, sp.ANIMATION_EVENT_TYPE.START, null, 0);
+ }
+};
+
+proto.interrupt = function(trackEntry) {
+ if (this.interruptListener) {
+ this.interruptListener(trackEntry);
+ }
+ if (this.callback) {
+ this.callback.call(this.callbackTarget, this.skeletonNode, trackEntry, sp.ANIMATION_EVENT_TYPE.INTERRUPT, null, 0);
+ }
+};
+
+proto.end = function (trackEntry) {
+ if (this.endListener) {
+ this.endListener(trackEntry);
+ }
+ if (this.callback) {
+ this.callback.call(this.callbackTarget, this.skeletonNode, trackEntry, sp.ANIMATION_EVENT_TYPE.END, null, 0);
+ }
+};
+
+proto.dispose = function (trackEntry) {
+ if (this.disposeListener) {
+ this.disposeListener(trackEntry);
+ }
+ if (this.callback) {
+ this.callback.call(this.callbackTarget, this.skeletonNode, trackEntry, sp.ANIMATION_EVENT_TYPE.DISPOSE, null, 0);
+ }
+};
+
+proto.complete = function (trackEntry) {
+ var loopCount = Math.floor(trackEntry.trackTime / trackEntry.animationEnd);
+ if (this.completeListener) {
+ this.completeListener(trackEntry, loopCount);
+ }
+ if (this.callback) {
+ this.callback.call(this.callbackTarget, this.skeletonNode, trackEntry, sp.ANIMATION_EVENT_TYPE.COMPLETE, null, loopCount);
+ }
+};
+
+proto.event = function (trackEntry, event) {
+ if (this.eventListener) {
+ this.eventListener(trackEntry, event);
+ }
+ if (this.callback) {
+ this.callback.call(this.callbackTarget, this.skeletonNode, trackEntry, sp.ANIMATION_EVENT_TYPE.EVENT, event, 0);
+ }
+};
+
+sp.TrackEntryListeners.getListeners = function(entry){
+ if(!entry.listener){
+ entry.listener = new sp.TrackEntryListeners();
+ }
+ return entry.listener;
+};
+
+/**
+ * The skeleton animation of spine. It updates animation's state and skeleton's world transform.
+ * @class
+ * @extends sp.Skeleton
+ * @example
+ * var spineBoy = new sp.SkeletonAnimation('res/skeletons/spineboy.json', 'res/skeletons/spineboy.atlas');
+ * this.addChild(spineBoy, 4);
+ */
+sp.SkeletonAnimation = sp.Skeleton.extend(/** @lends sp.SkeletonAnimation# */{
+ _state: null,
+
+ _ownsAnimationStateData: false,
+ _listener: null,
+
+ /**
+ * Initializes a sp.SkeletonAnimation. please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
+ * @override
+ */
+ init: function () {
+ sp.Skeleton.prototype.init.call(this);
+ this._ownsAnimationStateData = true;
+ this.setAnimationStateData(new spine.AnimationStateData(this._skeleton.data));
+ },
+
+ /**
+ * Sets animation state data to sp.SkeletonAnimation.
+ * @param {sp.spine.AnimationStateData} stateData
+ */
+ setAnimationStateData: function (stateData) {
+ var state = new spine.AnimationState(stateData);
+ this._listener = new sp.TrackEntryListeners();
+ state.rendererObject = this;
+ state.addListener(this._listener);
+ this._state = state;
+ },
+
+ /**
+ * Mix applies all keyframe values, interpolated for the specified time and mixed with the current values.
+ * @param {String} fromAnimation
+ * @param {String} toAnimation
+ * @param {Number} duration
+ */
+ setMix: function (fromAnimation, toAnimation, duration) {
+ this._state.data.setMixWith(fromAnimation, toAnimation, duration);
+ },
+
+ /**
+ * Sets event listener of sp.SkeletonAnimation.
+ * @param {Object} target
+ * @param {Function} callback
+ */
+ setAnimationListener: function (target, callback) {
+ this._listener.callbackTarget = target;
+ this._listener.callback = callback;
+ this._listener.skeletonNode = this;
+ },
+
+ /**
+ * Set the current animation. Any queued animations are cleared.
+ * @param {Number} trackIndex
+ * @param {String} name
+ * @param {Boolean} loop
+ * @returns {sp.spine.TrackEntry|null}
+ */
+ setAnimation: function (trackIndex, name, loop) {
+ var animation = this._skeleton.data.findAnimation(name);
+ if (!animation) {
+ cc.log("Spine: Animation not found: " + name);
+ return null;
+ }
+ return this._state.setAnimationWith(trackIndex, animation, loop);
+ },
+
+ /**
+ * Adds an animation to be played delay seconds after the current or last queued animation.
+ * @param {Number} trackIndex
+ * @param {String} name
+ * @param {Boolean} loop
+ * @param {Number} [delay=0]
+ * @returns {sp.spine.TrackEntry|null}
+ */
+ addAnimation: function (trackIndex, name, loop, delay) {
+ delay = delay == null ? 0 : delay;
+ var animation = this._skeleton.data.findAnimation(name);
+ if (!animation) {
+ cc.log("Spine: Animation not found:" + name);
+ return null;
+ }
+ return this._state.addAnimationWith(trackIndex, animation, loop, delay);
+ },
+
+ /**
+ * Find animation with specified name
+ * @param {String} name
+ * @returns {sp.spine.Animation|null}
+ */
+ findAnimation: function (name) {
+ return this._skeleton.data.findAnimation(name);
+ },
+
+ /**
+ * Returns track entry by trackIndex.
+ * @param trackIndex
+ * @returns {sp.spine.TrackEntry|null}
+ */
+ getCurrent: function (trackIndex) {
+ return this._state.getCurrent(trackIndex);
+ },
+
+ /**
+ * Clears all tracks of animation state.
+ */
+ clearTracks: function () {
+ this._state.clearTracks();
+ },
+
+ /**
+ * Clears track of animation state by trackIndex.
+ * @param {Number} trackIndex
+ */
+ clearTrack: function (trackIndex) {
+ this._state.clearTrack(trackIndex);
+ },
+
+ /**
+ * Update will be called automatically every frame if "scheduleUpdate" is called when the node is "live".
+ * It updates animation's state and skeleton's world transform.
+ * @param {Number} dt Delta time since last update
+ * @override
+ */
+ update: function (dt) {
+ this._super(dt);
+ dt *= this._timeScale;
+ this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty);
+ this._state.update(dt);
+ this._state.apply(this._skeleton);
+ this._skeleton.updateWorldTransform();
+ this._renderCmd._updateChild();
+ },
+
+ /**
+ * Set the start event listener.
+ * @param {function} listener
+ */
+ setStartListener: function(listener){
+ this._listener.startListener = listener;
+ },
+
+ /**
+ * Set the interrupt listener
+ * @param {function} listener
+ */
+ setInterruptListener: function(listener) {
+ this._listener.interruptListener = listener;
+ },
+
+ /**
+ * Set the end event listener.
+ * @param {function} listener
+ */
+ setEndListener: function(listener) {
+ this._listener.endListener = listener;
+ },
+
+ /**
+ * Set the dispose listener
+ * @param {function} listener
+ */
+ setDisposeListener: function(listener) {
+ this._listener.disposeListener = listener;
+ },
+
+ setCompleteListener: function(listener) {
+ this._listener.completeListener = listener;
+ },
+
+ setEventListener: function(listener){
+ this._listener.eventListener = listener;
+ },
+
+ setTrackStartListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).startListener = listener;
+ },
+
+ setTrackInterruptListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).interruptListener = listener;
+ },
+
+ setTrackEndListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).endListener = listener;
+ },
+
+ setTrackDisposeListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).disposeListener = listener;
+ },
+
+ setTrackCompleteListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).completeListener = listener;
+ },
+
+ setTrackEventListener: function(entry, listener){
+ sp.TrackEntryListeners.getListeners(entry).eventListener = listener;
+ },
+
+ getState: function(){
+ return this._state;
+ }
+});
+
+/**
+ * Creates a skeleton animation object.
+ * @deprecated since v3.0, please use new sp.SkeletonAnimation(skeletonDataFile, atlasFile, scale) instead.
+ * @param {spine.SkeletonData|String} skeletonDataFile
+ * @param {String|spine.Atlas|spine.SkeletonData} atlasFile atlas filename or atlas data or owns SkeletonData
+ * @param {Number} [scale] scale can be specified on the JSON or binary loader which will scale the bone positions, image sizes, and animation translations.
+ * @returns {sp.Skeleton}
+ */
+sp.SkeletonAnimation.createWithJsonFile = sp.SkeletonAnimation.create = function (skeletonDataFile, atlasFile/* or atlas*/, scale) {
+ return new sp.SkeletonAnimation(skeletonDataFile, atlasFile, scale);
+};
diff --git a/extensions/spine/CCSkeletonCanvasRenderCmd.js b/extensions/spine/CCSkeletonCanvasRenderCmd.js
new file mode 100644
index 0000000000..f31924ec19
--- /dev/null
+++ b/extensions/spine/CCSkeletonCanvasRenderCmd.js
@@ -0,0 +1,247 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+
+var spine = sp.spine;
+
+sp.Skeleton.CanvasRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+};
+
+var proto = sp.Skeleton.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
+proto.constructor = sp.Skeleton.CanvasRenderCmd;
+
+proto.rendering = function (wrapper, scaleX, scaleY) {
+ var node = this._node, i, n, slot, slotNode;
+ wrapper = wrapper || cc._renderContext;
+
+ var locSkeleton = node._skeleton, drawOrder = locSkeleton.drawOrder;
+ for (i = 0, n = drawOrder.length; i < n; i++) {
+ slot = drawOrder[i];
+ slotNode = slot._slotNode;
+ if (slotNode._visible && slotNode._renderCmd && slot.currentSprite) {
+ slotNode._renderCmd.transform(this, true);
+ slot.currentSprite._renderCmd.rendering(wrapper, scaleX, scaleY);
+ slotNode._renderCmd._dirtyFlag = slot.currentSprite._renderCmd._dirtyFlag = 0;
+ }
+ }
+
+ if (!node._debugSlots && !node._debugBones)
+ return;
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ wrapper.setGlobalAlpha(1);
+ var attachment, drawingUtil = cc._drawingUtil;
+ if (node._debugSlots) {
+ // Slots.
+ drawingUtil.setDrawColor(0, 0, 255, 255);
+ drawingUtil.setLineWidth(1);
+
+ var points = [];
+ for (i = 0, n = locSkeleton.slots.length; i < n; i++) {
+ slot = locSkeleton.drawOrder[i];
+ if (!slot.attachment || !(slot.attachment instanceof spine.RegionAttachment))
+ continue;
+ attachment = slot.attachment;
+ this._updateRegionAttachmentSlot(attachment, slot, points);
+ drawingUtil.drawPoly(points, 4, true);
+ }
+ }
+
+ if (node._debugBones) {
+ // Bone lengths.
+ var bone;
+ drawingUtil.setLineWidth(2);
+ drawingUtil.setDrawColor(255, 0, 0, 255);
+
+ for (i = 0, n = locSkeleton.bones.length; i < n; i++) {
+ bone = locSkeleton.bones[i];
+ var x = bone.data.length * bone.a + bone.worldX;
+ var y = bone.data.length * bone.c + bone.worldY;
+ drawingUtil.drawLine(
+ {x: bone.worldX, y: bone.worldY},
+ {x: x, y: y});
+ }
+
+ // Bone origins.
+ var pointSize = 4;
+ drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue.
+
+ for (i = 0, n = locSkeleton.bones.length; i < n; i++) {
+ bone = locSkeleton.bones[i];
+ drawingUtil.drawPoint({x: bone.worldX, y: bone.worldY}, pointSize);
+ if (i === 0)
+ drawingUtil.setDrawColor(0, 255, 0, 255);
+ }
+ }
+};
+
+proto.updateStatus = function() {
+ this.originUpdateStatus();
+ this._updateCurrentRegions();
+ this._regionFlag = cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble;
+ this._dirtyFlag &= ~cc.Node._dirtyFlags.contentDirty;
+};
+
+proto.getLocalBB = function() {
+ return this._node.getBoundingBox();
+};
+
+proto._updateRegionAttachmentSlot = function (attachment, slot, points) {
+ if (!points)
+ return;
+
+ var vertices = spine.Utils.setArraySize(new Array(), 8, 0);
+ attachment.computeWorldVertices(slot.bone, vertices, 0, 2);
+ var VERTEX = spine.RegionAttachment;
+ points.length = 0;
+ points.push(cc.p(vertices[VERTEX.OX1], vertices[VERTEX.OY1]));
+ points.push(cc.p(vertices[VERTEX.OX4], vertices[VERTEX.OY4]));
+ points.push(cc.p(vertices[VERTEX.OX3], vertices[VERTEX.OY3]));
+ points.push(cc.p(vertices[VERTEX.OX2], vertices[VERTEX.OY2]));
+};
+
+proto._createChildFormSkeletonData = function () {
+ var node = this._node;
+ var locSkeleton = node._skeleton, spriteName, sprite;
+ for (var i = 0, n = locSkeleton.slots.length; i < n; i++) {
+ var slot = locSkeleton.slots[i], attachment = slot.attachment;
+ var slotNode = new cc.Node();
+ slot._slotNode = slotNode;
+
+ if (attachment instanceof spine.RegionAttachment) {
+ spriteName = attachment.region.name;
+ sprite = this._createSprite(slot, attachment);
+ slot.currentSprite = sprite;
+ slot.currentSpriteName = spriteName;
+ slotNode.addChild(sprite);
+ } else if (attachment instanceof spine.MeshAttachment) {
+ //todo for mesh
+ }
+ }
+};
+
+var loaded = function (sprite, texture, attachment) {
+ var rendererObject = attachment.region;
+ var rect = new cc.Rect(rendererObject.x, rendererObject.y, rendererObject.width, rendererObject.height);
+ sprite.initWithTexture(texture, rect, rendererObject.rotate, false);
+ sprite._rect.width = attachment.width;
+ sprite._rect.height = attachment.height;
+ sprite.setContentSize(attachment.width, attachment.height);
+ sprite.setRotation(-attachment.rotation);
+ sprite.setScale(rendererObject.width / rendererObject.originalWidth * attachment.scaleX,
+ rendererObject.height / rendererObject.originalHeight * attachment.scaleY);
+};
+
+proto._createSprite = function (slot, attachment) {
+ var rendererObject = attachment.region;
+ var texture = rendererObject.texture.getRealTexture();
+ var sprite = new cc.Sprite();
+ if (texture.isLoaded()) {
+ loaded(sprite, texture, attachment);
+ } else {
+ texture.addEventListener('load', function () {
+ loaded(sprite, texture, attachment);
+ }, this);
+ }
+ slot.sprites = slot.sprites || {};
+ slot.sprites[rendererObject.name] = sprite;
+ return sprite;
+};
+
+proto._updateChild = function () {
+ var locSkeleton = this._node._skeleton, slots = locSkeleton.slots;
+ var color = this._displayedColor, opacity = this._displayedOpacity;
+ var i, n, selSprite, ax, ay;
+
+ var slot, attachment, slotNode;
+ for (i = 0, n = slots.length; i < n; i++) {
+ slot = slots[i];
+ attachment = slot.attachment;
+ slotNode = slot._slotNode;
+ if (!attachment) {
+ slotNode.setVisible(false);
+ continue;
+ }
+ if (attachment instanceof spine.RegionAttachment) {
+ if (attachment.region) {
+ if (!slot.currentSpriteName || slot.currentSpriteName !== attachment.name) {
+ var spriteName = attachment.region.name;
+ if (slot.currentSprite !== undefined)
+ slot.currentSprite.setVisible(false);
+ slot.sprites = slot.sprites || {};
+ if (slot.sprites[spriteName] !== undefined)
+ slot.sprites[spriteName].setVisible(true);
+ else {
+ var sprite = this._createSprite(slot, attachment);
+ slotNode.addChild(sprite);
+ }
+ slot.currentSprite = slot.sprites[spriteName];
+ slot.currentSpriteName = spriteName;
+ }
+ }
+ var bone = slot.bone;
+ if (attachment.region.offsetX === 0 && attachment.region.offsetY === 0) {
+ ax = attachment.x;
+ ay = attachment.y;
+ }
+ else {
+ //var regionScaleX = attachment.width / attachment.regionOriginalWidth * attachment.scaleX;
+ //ax = attachment.x + attachment.regionOffsetX * regionScaleX - (attachment.width * attachment.scaleX - attachment.regionWidth * regionScaleX) / 2;
+ ax = (attachment.offset[0] + attachment.offset[4]) * 0.5;
+ ay = (attachment.offset[1] + attachment.offset[5]) * 0.5;
+ }
+ slotNode.setPosition(bone.worldX + ax * bone.a + ay * bone.b, bone.worldY + ax * bone.c + ay * bone.d);
+ slotNode.setScale(bone.getWorldScaleX(), bone.getWorldScaleY());
+
+ //set the color and opacity
+ selSprite = slot.currentSprite;
+ selSprite._flippedX = bone.skeleton.flipX;
+ selSprite._flippedY = bone.skeleton.flipY;
+ if (selSprite._flippedY || selSprite._flippedX) {
+ slotNode.setRotation(bone.getWorldRotationX());
+ selSprite.setRotation(attachment.rotation);
+ } else {
+ slotNode.setRotation(-bone.getWorldRotationX());
+ selSprite.setRotation(-attachment.rotation);
+ }
+
+ //hack for sprite
+ selSprite._renderCmd._displayedOpacity = 0 | (opacity * slot.color.a);
+ var r = 0 | (color.r * slot.color.r), g = 0 | (color.g * slot.color.g), b = 0 | (color.b * slot.color.b);
+ selSprite.setColor(cc.color(r, g, b));
+ selSprite._renderCmd._updateColor();
+ } else if (attachment instanceof spine.MeshAttachment) {
+ // Can not render mesh
+ } else {
+ slotNode.setVisible(false);
+ continue;
+ }
+ slotNode.setVisible(true);
+ }
+};
+
+})();
diff --git a/extensions/spine/CCSkeletonTexture.js b/extensions/spine/CCSkeletonTexture.js
new file mode 100644
index 0000000000..9250369c30
--- /dev/null
+++ b/extensions/spine/CCSkeletonTexture.js
@@ -0,0 +1,67 @@
+/****************************************************************************
+ Copyright (c) 2017 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+sp.SkeletonTexture = function (image) {
+ sp.spine.Texture.call(this, image);
+};
+cc.inherits(sp.SkeletonTexture, sp.spine.Texture);
+cc.extend(sp.SkeletonTexture.prototype, {
+ name: 'sp.SkeletonTexture',
+ _texture: null,
+
+ setRealTexture: function(tex) {
+ this._texture = tex;
+ },
+
+ getRealTexture: function() {
+ return this._texture;
+ },
+
+ setFilters: function(minFilter, magFilter) {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ var gl = cc._renderContext;
+ this.bind();
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
+ }
+ },
+
+ setWraps: function(uWrap, vWrap) {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ var gl = cc._renderContext;
+ this.bind();
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap);
+ }
+ },
+
+ dispose: function() {
+ },
+
+ bind: function() {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ cc.glBindTexture2D(this._texture);
+ }
+ }
+});
\ No newline at end of file
diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js
new file mode 100644
index 0000000000..535e4c0ac5
--- /dev/null
+++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js
@@ -0,0 +1,347 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+(function () {
+
+var spine = sp.spine;
+
+sp.Skeleton.WebGLRenderCmd = function (renderableObject) {
+ this._rootCtor(renderableObject);
+ this._needDraw = true;
+ this._matrix = new cc.math.Matrix4();
+ this._matrix.identity();
+ this._currTexture = null;
+ this._currBlendFunc = {};
+ this.vertexType = cc.renderer.VertexType.CUSTOM;
+ this.setShaderProgram(cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR));
+};
+
+var proto = sp.Skeleton.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
+proto.constructor = sp.Skeleton.WebGLRenderCmd;
+
+proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset){
+ var node = this._node;
+ var color = this._displayedColor, locSkeleton = node._skeleton;
+
+ var attachment, slot, i, n;
+ var premultiAlpha = node._premultipliedAlpha;
+
+ locSkeleton.r = color.r / 255;
+ locSkeleton.g = color.g / 255;
+ locSkeleton.b = color.b / 255;
+ locSkeleton.a = this._displayedOpacity / 255;
+ if (premultiAlpha) {
+ locSkeleton.r *= locSkeleton.a;
+ locSkeleton.g *= locSkeleton.a;
+ locSkeleton.b *= locSkeleton.a;
+ }
+
+ var debugSlotsInfo = null;
+ if (this._node._debugSlots) {
+ debugSlotsInfo = [];
+ }
+
+ for (i = 0, n = locSkeleton.drawOrder.length; i < n; i++) {
+ slot = locSkeleton.drawOrder[i];
+ if (!slot.attachment)
+ continue;
+ attachment = slot.attachment;
+
+ // get the vertices length
+ var vertCount = 0;
+ if (attachment instanceof spine.RegionAttachment) {
+ vertCount = 6; // a quad = two triangles = six vertices
+ }
+ else if (attachment instanceof spine.MeshAttachment) {
+ vertCount = attachment.regionUVs.length / 2;
+ }
+ else {
+ continue;
+ }
+
+ // no vertices to render
+ if (vertCount === 0) {
+ continue;
+ }
+
+ var regionTextureAtlas = node.getTextureAtlas(attachment);
+
+ // Broken for changing batch info
+ this._currTexture = regionTextureAtlas.texture.getRealTexture();
+ var batchBroken = cc.renderer._updateBatchedInfo(this._currTexture, this._getBlendFunc(slot.data.blendMode, premultiAlpha), this._glProgramState);
+
+ // keep the same logic with RendererWebGL.js, avoid vertex data overflow
+ var uploadAll = vertexDataOffset / 6 + vertCount > (cc.BATCH_VERTEX_COUNT - 200) * 0.5;
+ // Broken for vertex data overflow
+ if (!batchBroken && uploadAll) {
+ // render the cached data
+ cc.renderer._batchRendering();
+ batchBroken = true;
+ }
+ if (batchBroken) {
+ vertexDataOffset = 0;
+ }
+
+ // update the vertex buffer
+ var slotDebugPoints = null;
+ if (attachment instanceof spine.RegionAttachment) {
+ slotDebugPoints = this._uploadRegionAttachmentData(attachment, slot, premultiAlpha, f32buffer, ui32buffer, vertexDataOffset);
+ }
+ else if (attachment instanceof spine.MeshAttachment) {
+ this._uploadMeshAttachmentData(attachment, slot, premultiAlpha, f32buffer, ui32buffer, vertexDataOffset);
+ }
+ else {
+ continue;
+ }
+
+ if (this._node._debugSlots) {
+ debugSlotsInfo[i] = slotDebugPoints;
+ }
+
+ // update the index buffer
+ if (attachment instanceof spine.RegionAttachment) {
+ cc.renderer._increaseBatchingSize(vertCount, cc.renderer.VertexType.TRIANGLE);
+ } else {
+ cc.renderer._increaseBatchingSize(vertCount, cc.renderer.VertexType.CUSTOM, attachment.triangles);
+ }
+
+ // update the index data
+ vertexDataOffset += vertCount * 6;
+ }
+
+ if (node._debugBones || node._debugSlots) {
+ // flush previous vertices
+ cc.renderer._batchRendering();
+
+ var wt = this._worldTransform, mat = this._matrix.mat;
+ mat[0] = wt.a;
+ mat[4] = wt.c;
+ mat[12] = wt.tx;
+ mat[1] = wt.b;
+ mat[5] = wt.d;
+ mat[13] = wt.ty;
+ cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
+ cc.current_stack.stack.push(cc.current_stack.top);
+ cc.current_stack.top = this._matrix;
+ var drawingUtil = cc._drawingUtil;
+
+ if (node._debugSlots && debugSlotsInfo && debugSlotsInfo.length > 0) {
+ // Slots.
+ drawingUtil.setDrawColor(0, 0, 255, 255);
+ drawingUtil.setLineWidth(1);
+
+ for (i = 0, n = locSkeleton.slots.length; i < n; i++) {
+ var points = debugSlotsInfo[i];
+ if (points) {
+ drawingUtil.drawPoly(points, 4, true);
+ }
+ }
+ }
+
+ if (node._debugBones) {
+ // Bone lengths.
+ var bone;
+ drawingUtil.setLineWidth(2);
+ drawingUtil.setDrawColor(255, 0, 0, 255);
+
+ for (i = 0, n = locSkeleton.bones.length; i < n; i++) {
+ bone = locSkeleton.bones[i];
+ var x = bone.data.length * bone.a + bone.worldX;
+ var y = bone.data.length * bone.c + bone.worldY;
+ drawingUtil.drawLine(cc.p(bone.worldX, bone.worldY), cc.p(x, y));
+ }
+
+ // Bone origins.
+ drawingUtil.setPointSize(4);
+ drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue.
+
+ for (i = 0, n = locSkeleton.bones.length; i < n; i++) {
+ bone = locSkeleton.bones[i];
+ drawingUtil.drawPoint(cc.p(bone.worldX, bone.worldY));
+ if (i == 0) {
+ drawingUtil.setDrawColor(0, 255, 0, 255);
+ }
+ }
+ }
+ cc.kmGLPopMatrix();
+ }
+
+ return 0;
+};
+
+proto._getBlendFunc = function (blendMode, premultiAlpha) {
+ var ret = this._currBlendFunc;
+ switch (blendMode) {
+ case spine.BlendMode.Normal:
+ ret.src = premultiAlpha ? cc.ONE : cc.SRC_ALPHA;
+ ret.dst = cc.ONE_MINUS_SRC_ALPHA;
+ break;
+ case spine.BlendMode.Additive:
+ ret.src = premultiAlpha ? cc.ONE : cc.SRC_ALPHA;
+ ret.dst = cc.ONE;
+ break;
+ case spine.BlendMode.Multiply:
+ ret.src = cc.DST_COLOR;
+ ret.dst = cc.ONE_MINUS_SRC_ALPHA;
+ break;
+ case spine.BlendMode.Screen:
+ ret.src = cc.ONE;
+ ret.dst = cc.ONE_MINUS_SRC_COLOR;
+ break;
+ default:
+ ret = this._node._blendFunc;
+ break;
+ }
+
+ return ret;
+};
+
+proto._createChildFormSkeletonData = function(){};
+
+proto._updateChild = function(){};
+
+proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlpha, f32buffer, ui32buffer, vertexDataOffset) {
+ // the vertices in format:
+ // [
+ // X1, Y1, C1R, C1G, C1B, C1A, U1, V1, // bottom left
+ // X2, Y2, C2R, C2G, C2B, C2A, U2, V2, // top left
+ // X3, Y3, C3R, C3G, C3B, C3A, U3, V3, // top right
+ // X4, Y4, C4R, C4G, C4B, C4A, U4, V4 // bottom right
+ // ]
+ //
+ var nodeColor = this._displayedColor;
+ var nodeR = nodeColor.r,
+ nodeG = nodeColor.g,
+ nodeB = nodeColor.b,
+ nodeA = this._displayedOpacity;
+
+ var vertices = spine.Utils.setArraySize(new Array(), 8, 0);
+ attachment.computeWorldVertices(slot.bone, vertices, 0, 2);
+
+ var uvs = attachment.uvs;
+
+ // get the colors data
+ var skeleton = slot.bone.skeleton;
+ var skeletonColor = skeleton.color;
+ var slotColor = slot.color;
+ var regionColor = attachment.color;
+ var alpha = skeletonColor.a * slotColor.a * regionColor.a;
+ var multiplier = premultipliedAlpha ? alpha : 1;
+ var colors = attachment.tempColor;
+ colors.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,
+ skeletonColor.g * slotColor.g * regionColor.g * multiplier,
+ skeletonColor.b * slotColor.b * regionColor.b * multiplier,
+ alpha);
+
+ var wt = this._worldTransform,
+ wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d,
+ wx = wt.tx, wy = wt.ty,
+ z = this._node.vertexZ;
+
+ var offset = vertexDataOffset;
+ // generate 6 vertices data (two triangles) from the quad vertices
+ // using two angles : (0, 1, 2) & (0, 2, 3)
+ for (var i = 0; i < 6; i++) {
+ var srcIdx = i < 4 ? i % 3 : i - 2;
+ var vx = vertices[srcIdx * 2],
+ vy = vertices[srcIdx * 2 + 1];
+ var x = vx * wa + vy * wc + wx,
+ y = vx * wb + vy * wd + wy;
+ var r = colors.r * nodeR,
+ g = colors.g * nodeG,
+ b = colors.b * nodeB,
+ a = colors.a * nodeA;
+ var color = ((a<<24) | (b<<16) | (g<<8) | r);
+ f32buffer[offset] = x;
+ f32buffer[offset + 1] = y;
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = color;
+ f32buffer[offset + 4] = uvs[srcIdx * 2];
+ f32buffer[offset + 5] = uvs[srcIdx * 2 + 1];
+ offset += 6;
+ }
+
+ if (this._node._debugSlots) {
+ // return the quad points info if debug slot enabled
+ var VERTEX = spine.RegionAttachment;
+ return [
+ cc.p(vertices[VERTEX.OX1], vertices[VERTEX.OY1]),
+ cc.p(vertices[VERTEX.OX2], vertices[VERTEX.OY2]),
+ cc.p(vertices[VERTEX.OX3], vertices[VERTEX.OY3]),
+ cc.p(vertices[VERTEX.OX4], vertices[VERTEX.OY4])
+ ];
+ }
+};
+
+proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, f32buffer, ui32buffer, vertexDataOffset) {
+ var wt = this._worldTransform,
+ wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d,
+ wx = wt.tx, wy = wt.ty,
+ z = this._node.vertexZ;
+ // get the vertex data
+ var verticesLength = attachment.worldVerticesLength;
+ var vertices = spine.Utils.setArraySize(new Array(), verticesLength, 0);
+ attachment.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
+
+ var uvs = attachment.uvs;
+
+ // get the colors data
+ var skeleton = slot.bone.skeleton;
+ var skeletonColor = skeleton.color, slotColor = slot.color, meshColor = attachment.color;
+ var alpha = skeletonColor.a * slotColor.a * meshColor.a;
+ var multiplier = premultipliedAlpha ? alpha : 1;
+ var colors = attachment.tempColor;
+ colors.set(skeletonColor.r * slotColor.r * meshColor.r * multiplier,
+ skeletonColor.g * slotColor.g * meshColor.g * multiplier,
+ skeletonColor.b * slotColor.b * meshColor.b * multiplier,
+ alpha);
+
+ var offset = vertexDataOffset;
+ var nodeColor = this._displayedColor;
+ var nodeR = nodeColor.r,
+ nodeG = nodeColor.g,
+ nodeB = nodeColor.b,
+ nodeA = this._displayedOpacity;
+ for (var i = 0, n = vertices.length; i < n; i += 2) {
+ var vx = vertices[i],
+ vy = vertices[i + 1];
+ var x = vx * wa + vy * wb + wx,
+ y = vx * wc + vy * wd + wy;
+ var r = colors.r * nodeR,
+ g = colors.g * nodeG,
+ b = colors.b * nodeB,
+ a = colors.a * nodeA;
+ var color = ((a<<24) | (b<<16) | (g<<8) | r);
+
+ f32buffer[offset] = x;
+ f32buffer[offset + 1] = y;
+ f32buffer[offset + 2] = z;
+ ui32buffer[offset + 3] = color;
+ f32buffer[offset + 4] = uvs[i];
+ f32buffer[offset + 5] = uvs[i + 1];
+ offset += 6;
+ }
+};
+
+})();
diff --git a/extensions/spine/LICENSE b/extensions/spine/LICENSE
new file mode 100644
index 0000000000..daceab94a4
--- /dev/null
+++ b/extensions/spine/LICENSE
@@ -0,0 +1,27 @@
+Spine Runtimes Software License v2.5
+
+Copyright (c) 2013-2016, Esoteric Software
+All rights reserved.
+
+You are granted a perpetual, non-exclusive, non-sublicensable, and
+non-transferable license to use, install, execute, and perform the Spine
+Runtimes software and derivative works solely for personal or internal
+use. Without the written permission of Esoteric Software (see Section 2 of
+the Spine Software License Agreement), you may not (a) modify, translate,
+adapt, or develop new applications using the Spine Runtimes or otherwise
+create derivative works or improvements of the Spine Runtimes or (b) remove,
+delete, alter, or obscure any trademarks or any copyright, trademark, patent,
+or other intellectual property or proprietary rights notices on or in the
+Software, including any copy thereof. Redistributions in binary or source
+form must include this license and terms.
+
+THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
+USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/extensions/spine/Spine.js b/extensions/spine/Spine.js
new file mode 100644
index 0000000000..e7c0d894ea
--- /dev/null
+++ b/extensions/spine/Spine.js
@@ -0,0 +1,6458 @@
+// Spine runtime version 3.6.39
+
+var __extends = (this && this.__extends) || (function () {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+ return function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+var spine;
+(function (spine) {
+ var Animation = (function () {
+ function Animation(name, timelines, duration) {
+ if (name == null)
+ throw new Error("name cannot be null.");
+ if (timelines == null)
+ throw new Error("timelines cannot be null.");
+ this.name = name;
+ this.timelines = timelines;
+ this.duration = duration;
+ }
+ Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, pose, direction) {
+ if (skeleton == null)
+ throw new Error("skeleton cannot be null.");
+ if (loop && this.duration != 0) {
+ time %= this.duration;
+ if (lastTime > 0)
+ lastTime %= this.duration;
+ }
+ var timelines = this.timelines;
+ for (var i = 0, n = timelines.length; i < n; i++)
+ timelines[i].apply(skeleton, lastTime, time, events, alpha, pose, direction);
+ };
+ Animation.binarySearch = function (values, target, step) {
+ if (step === void 0) { step = 1; }
+ var low = 0;
+ var high = 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;
+ }
+ };
+ Animation.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;
+ };
+ return Animation;
+ }());
+ spine.Animation = Animation;
+ var MixPose;
+ (function (MixPose) {
+ MixPose[MixPose["setup"] = 0] = "setup";
+ MixPose[MixPose["current"] = 1] = "current";
+ MixPose[MixPose["currentLayered"] = 2] = "currentLayered";
+ })(MixPose = spine.MixPose || (spine.MixPose = {}));
+ var MixDirection;
+ (function (MixDirection) {
+ MixDirection[MixDirection["in"] = 0] = "in";
+ MixDirection[MixDirection["out"] = 1] = "out";
+ })(MixDirection = spine.MixDirection || (spine.MixDirection = {}));
+ var TimelineType;
+ (function (TimelineType) {
+ TimelineType[TimelineType["rotate"] = 0] = "rotate";
+ TimelineType[TimelineType["translate"] = 1] = "translate";
+ TimelineType[TimelineType["scale"] = 2] = "scale";
+ TimelineType[TimelineType["shear"] = 3] = "shear";
+ TimelineType[TimelineType["attachment"] = 4] = "attachment";
+ TimelineType[TimelineType["color"] = 5] = "color";
+ TimelineType[TimelineType["deform"] = 6] = "deform";
+ TimelineType[TimelineType["event"] = 7] = "event";
+ TimelineType[TimelineType["drawOrder"] = 8] = "drawOrder";
+ TimelineType[TimelineType["ikConstraint"] = 9] = "ikConstraint";
+ TimelineType[TimelineType["transformConstraint"] = 10] = "transformConstraint";
+ TimelineType[TimelineType["pathConstraintPosition"] = 11] = "pathConstraintPosition";
+ TimelineType[TimelineType["pathConstraintSpacing"] = 12] = "pathConstraintSpacing";
+ TimelineType[TimelineType["pathConstraintMix"] = 13] = "pathConstraintMix";
+ TimelineType[TimelineType["twoColor"] = 14] = "twoColor";
+ })(TimelineType = spine.TimelineType || (spine.TimelineType = {}));
+ var CurveTimeline = (function () {
+ function CurveTimeline(frameCount) {
+ if (frameCount <= 0)
+ throw new Error("frameCount must be > 0: " + frameCount);
+ this.curves = spine.Utils.newFloatArray((frameCount - 1) * CurveTimeline.BEZIER_SIZE);
+ }
+ CurveTimeline.prototype.getFrameCount = function () {
+ return this.curves.length / CurveTimeline.BEZIER_SIZE + 1;
+ };
+ CurveTimeline.prototype.setLinear = function (frameIndex) {
+ this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.LINEAR;
+ };
+ CurveTimeline.prototype.setStepped = function (frameIndex) {
+ this.curves[frameIndex * CurveTimeline.BEZIER_SIZE] = CurveTimeline.STEPPED;
+ };
+ CurveTimeline.prototype.getCurveType = function (frameIndex) {
+ var index = frameIndex * CurveTimeline.BEZIER_SIZE;
+ if (index == this.curves.length)
+ return CurveTimeline.LINEAR;
+ var type = this.curves[index];
+ if (type == CurveTimeline.LINEAR)
+ return CurveTimeline.LINEAR;
+ if (type == CurveTimeline.STEPPED)
+ return CurveTimeline.STEPPED;
+ return CurveTimeline.BEZIER;
+ };
+ CurveTimeline.prototype.setCurve = function (frameIndex, cx1, cy1, cx2, cy2) {
+ var tmpx = (-cx1 * 2 + cx2) * 0.03, tmpy = (-cy1 * 2 + cy2) * 0.03;
+ var dddfx = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006;
+ var ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy;
+ var dfx = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy = cy1 * 0.3 + tmpy + dddfy * 0.16666667;
+ var i = frameIndex * CurveTimeline.BEZIER_SIZE;
+ var curves = this.curves;
+ curves[i++] = CurveTimeline.BEZIER;
+ var x = dfx, y = dfy;
+ for (var n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) {
+ curves[i] = x;
+ curves[i + 1] = y;
+ dfx += ddfx;
+ dfy += ddfy;
+ ddfx += dddfx;
+ ddfy += dddfy;
+ x += dfx;
+ y += dfy;
+ }
+ };
+ CurveTimeline.prototype.getCurvePercent = function (frameIndex, percent) {
+ percent = spine.MathUtils.clamp(percent, 0, 1);
+ var curves = this.curves;
+ var i = frameIndex * CurveTimeline.BEZIER_SIZE;
+ var type = curves[i];
+ if (type == CurveTimeline.LINEAR)
+ return percent;
+ if (type == CurveTimeline.STEPPED)
+ return 0;
+ i++;
+ var x = 0;
+ for (var start = i, n = i + CurveTimeline.BEZIER_SIZE - 1; i < n; i += 2) {
+ x = curves[i];
+ if (x >= percent) {
+ var prevX = void 0, prevY = void 0;
+ if (i == start) {
+ prevX = 0;
+ prevY = 0;
+ }
+ else {
+ prevX = curves[i - 2];
+ prevY = curves[i - 1];
+ }
+ return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX);
+ }
+ }
+ var y = curves[i - 1];
+ return y + (1 - y) * (percent - x) / (1 - x);
+ };
+ return CurveTimeline;
+ }());
+ CurveTimeline.LINEAR = 0;
+ CurveTimeline.STEPPED = 1;
+ CurveTimeline.BEZIER = 2;
+ CurveTimeline.BEZIER_SIZE = 10 * 2 - 1;
+ spine.CurveTimeline = CurveTimeline;
+ var RotateTimeline = (function (_super) {
+ __extends(RotateTimeline, _super);
+ function RotateTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount << 1);
+ return _this;
+ }
+ RotateTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.rotate << 24) + this.boneIndex;
+ };
+ RotateTimeline.prototype.setFrame = function (frameIndex, time, degrees) {
+ frameIndex <<= 1;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + RotateTimeline.ROTATION] = degrees;
+ };
+ RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) {
+ var frames = this.frames;
+ var bone = skeleton.bones[this.boneIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ bone.rotation = bone.data.rotation;
+ return;
+ case MixPose.current:
+ var r_1 = bone.data.rotation - bone.rotation;
+ r_1 -= (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360;
+ bone.rotation += r_1 * alpha;
+ }
+ return;
+ }
+ if (time >= frames[frames.length - RotateTimeline.ENTRIES]) {
+ if (pose == MixPose.setup)
+ bone.rotation = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] * alpha;
+ else {
+ var r_2 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation;
+ r_2 -= (16384 - ((16384.499999999996 - r_2 / 360) | 0)) * 360;
+ bone.rotation += r_2 * alpha;
+ }
+ return;
+ }
+ var frame = Animation.binarySearch(frames, time, RotateTimeline.ENTRIES);
+ var prevRotation = frames[frame + RotateTimeline.PREV_ROTATION];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime));
+ var r = frames[frame + RotateTimeline.ROTATION] - prevRotation;
+ r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
+ r = prevRotation + r * percent;
+ if (pose == MixPose.setup) {
+ r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
+ bone.rotation = bone.data.rotation + r * alpha;
+ }
+ else {
+ r = bone.data.rotation + r - bone.rotation;
+ r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
+ bone.rotation += r * alpha;
+ }
+ };
+ return RotateTimeline;
+ }(CurveTimeline));
+ RotateTimeline.ENTRIES = 2;
+ RotateTimeline.PREV_TIME = -2;
+ RotateTimeline.PREV_ROTATION = -1;
+ RotateTimeline.ROTATION = 1;
+ spine.RotateTimeline = RotateTimeline;
+ var TranslateTimeline = (function (_super) {
+ __extends(TranslateTimeline, _super);
+ function TranslateTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES);
+ return _this;
+ }
+ TranslateTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.translate << 24) + this.boneIndex;
+ };
+ TranslateTimeline.prototype.setFrame = function (frameIndex, time, x, y) {
+ frameIndex *= TranslateTimeline.ENTRIES;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + TranslateTimeline.X] = x;
+ this.frames[frameIndex + TranslateTimeline.Y] = y;
+ };
+ TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) {
+ var frames = this.frames;
+ var bone = skeleton.bones[this.boneIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ bone.x = bone.data.x;
+ bone.y = bone.data.y;
+ return;
+ case MixPose.current:
+ bone.x += (bone.data.x - bone.x) * alpha;
+ bone.y += (bone.data.y - bone.y) * alpha;
+ }
+ return;
+ }
+ var x = 0, y = 0;
+ if (time >= frames[frames.length - TranslateTimeline.ENTRIES]) {
+ x = frames[frames.length + TranslateTimeline.PREV_X];
+ y = frames[frames.length + TranslateTimeline.PREV_Y];
+ }
+ else {
+ var frame = Animation.binarySearch(frames, time, TranslateTimeline.ENTRIES);
+ x = frames[frame + TranslateTimeline.PREV_X];
+ y = frames[frame + TranslateTimeline.PREV_Y];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / TranslateTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TranslateTimeline.PREV_TIME] - frameTime));
+ x += (frames[frame + TranslateTimeline.X] - x) * percent;
+ y += (frames[frame + TranslateTimeline.Y] - y) * percent;
+ }
+ if (pose == MixPose.setup) {
+ bone.x = bone.data.x + x * alpha;
+ bone.y = bone.data.y + y * alpha;
+ }
+ else {
+ bone.x += (bone.data.x + x - bone.x) * alpha;
+ bone.y += (bone.data.y + y - bone.y) * alpha;
+ }
+ };
+ return TranslateTimeline;
+ }(CurveTimeline));
+ TranslateTimeline.ENTRIES = 3;
+ TranslateTimeline.PREV_TIME = -3;
+ TranslateTimeline.PREV_X = -2;
+ TranslateTimeline.PREV_Y = -1;
+ TranslateTimeline.X = 1;
+ TranslateTimeline.Y = 2;
+ spine.TranslateTimeline = TranslateTimeline;
+ var ScaleTimeline = (function (_super) {
+ __extends(ScaleTimeline, _super);
+ function ScaleTimeline(frameCount) {
+ return _super.call(this, frameCount) || this;
+ }
+ ScaleTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.scale << 24) + this.boneIndex;
+ };
+ ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) {
+ var frames = this.frames;
+ var bone = skeleton.bones[this.boneIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ bone.scaleX = bone.data.scaleX;
+ bone.scaleY = bone.data.scaleY;
+ return;
+ case MixPose.current:
+ bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
+ bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
+ }
+ return;
+ }
+ var x = 0, y = 0;
+ if (time >= frames[frames.length - ScaleTimeline.ENTRIES]) {
+ x = frames[frames.length + ScaleTimeline.PREV_X] * bone.data.scaleX;
+ y = frames[frames.length + ScaleTimeline.PREV_Y] * bone.data.scaleY;
+ }
+ else {
+ var frame = Animation.binarySearch(frames, time, ScaleTimeline.ENTRIES);
+ x = frames[frame + ScaleTimeline.PREV_X];
+ y = frames[frame + ScaleTimeline.PREV_Y];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / ScaleTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ScaleTimeline.PREV_TIME] - frameTime));
+ x = (x + (frames[frame + ScaleTimeline.X] - x) * percent) * bone.data.scaleX;
+ y = (y + (frames[frame + ScaleTimeline.Y] - y) * percent) * bone.data.scaleY;
+ }
+ if (alpha == 1) {
+ bone.scaleX = x;
+ bone.scaleY = y;
+ }
+ else {
+ var bx = 0, by = 0;
+ if (pose == MixPose.setup) {
+ bx = bone.data.scaleX;
+ by = bone.data.scaleY;
+ }
+ else {
+ bx = bone.scaleX;
+ by = bone.scaleY;
+ }
+ if (direction == MixDirection.out) {
+ x = Math.abs(x) * spine.MathUtils.signum(bx);
+ y = Math.abs(y) * spine.MathUtils.signum(by);
+ }
+ else {
+ bx = Math.abs(bx) * spine.MathUtils.signum(x);
+ by = Math.abs(by) * spine.MathUtils.signum(y);
+ }
+ bone.scaleX = bx + (x - bx) * alpha;
+ bone.scaleY = by + (y - by) * alpha;
+ }
+ };
+ return ScaleTimeline;
+ }(TranslateTimeline));
+ spine.ScaleTimeline = ScaleTimeline;
+ var ShearTimeline = (function (_super) {
+ __extends(ShearTimeline, _super);
+ function ShearTimeline(frameCount) {
+ return _super.call(this, frameCount) || this;
+ }
+ ShearTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.shear << 24) + this.boneIndex;
+ };
+ ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) {
+ var frames = this.frames;
+ var bone = skeleton.bones[this.boneIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ bone.shearX = bone.data.shearX;
+ bone.shearY = bone.data.shearY;
+ return;
+ case MixPose.current:
+ bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
+ bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
+ }
+ return;
+ }
+ var x = 0, y = 0;
+ if (time >= frames[frames.length - ShearTimeline.ENTRIES]) {
+ x = frames[frames.length + ShearTimeline.PREV_X];
+ y = frames[frames.length + ShearTimeline.PREV_Y];
+ }
+ else {
+ var frame = Animation.binarySearch(frames, time, ShearTimeline.ENTRIES);
+ x = frames[frame + ShearTimeline.PREV_X];
+ y = frames[frame + ShearTimeline.PREV_Y];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / ShearTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ShearTimeline.PREV_TIME] - frameTime));
+ x = x + (frames[frame + ShearTimeline.X] - x) * percent;
+ y = y + (frames[frame + ShearTimeline.Y] - y) * percent;
+ }
+ if (pose == MixPose.setup) {
+ bone.shearX = bone.data.shearX + x * alpha;
+ bone.shearY = bone.data.shearY + y * alpha;
+ }
+ else {
+ bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
+ bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
+ }
+ };
+ return ShearTimeline;
+ }(TranslateTimeline));
+ spine.ShearTimeline = ShearTimeline;
+ var ColorTimeline = (function (_super) {
+ __extends(ColorTimeline, _super);
+ function ColorTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES);
+ return _this;
+ }
+ ColorTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.color << 24) + this.slotIndex;
+ };
+ ColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a) {
+ frameIndex *= ColorTimeline.ENTRIES;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + ColorTimeline.R] = r;
+ this.frames[frameIndex + ColorTimeline.G] = g;
+ this.frames[frameIndex + ColorTimeline.B] = b;
+ this.frames[frameIndex + ColorTimeline.A] = a;
+ };
+ ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) {
+ var slot = skeleton.slots[this.slotIndex];
+ var frames = this.frames;
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ slot.color.setFromColor(slot.data.color);
+ return;
+ case MixPose.current:
+ var color = slot.color, setup = slot.data.color;
+ color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha);
+ }
+ return;
+ }
+ var r = 0, g = 0, b = 0, a = 0;
+ if (time >= frames[frames.length - ColorTimeline.ENTRIES]) {
+ var i = frames.length;
+ r = frames[i + ColorTimeline.PREV_R];
+ g = frames[i + ColorTimeline.PREV_G];
+ b = frames[i + ColorTimeline.PREV_B];
+ a = frames[i + ColorTimeline.PREV_A];
+ }
+ else {
+ var frame = Animation.binarySearch(frames, time, ColorTimeline.ENTRIES);
+ r = frames[frame + ColorTimeline.PREV_R];
+ g = frames[frame + ColorTimeline.PREV_G];
+ b = frames[frame + ColorTimeline.PREV_B];
+ a = frames[frame + ColorTimeline.PREV_A];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / ColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + ColorTimeline.PREV_TIME] - frameTime));
+ r += (frames[frame + ColorTimeline.R] - r) * percent;
+ g += (frames[frame + ColorTimeline.G] - g) * percent;
+ b += (frames[frame + ColorTimeline.B] - b) * percent;
+ a += (frames[frame + ColorTimeline.A] - a) * percent;
+ }
+ if (alpha == 1)
+ slot.color.set(r, g, b, a);
+ else {
+ var color = slot.color;
+ if (pose == MixPose.setup)
+ color.setFromColor(slot.data.color);
+ color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
+ }
+ };
+ return ColorTimeline;
+ }(CurveTimeline));
+ ColorTimeline.ENTRIES = 5;
+ ColorTimeline.PREV_TIME = -5;
+ ColorTimeline.PREV_R = -4;
+ ColorTimeline.PREV_G = -3;
+ ColorTimeline.PREV_B = -2;
+ ColorTimeline.PREV_A = -1;
+ ColorTimeline.R = 1;
+ ColorTimeline.G = 2;
+ ColorTimeline.B = 3;
+ ColorTimeline.A = 4;
+ spine.ColorTimeline = ColorTimeline;
+ var TwoColorTimeline = (function (_super) {
+ __extends(TwoColorTimeline, _super);
+ function TwoColorTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount * TwoColorTimeline.ENTRIES);
+ return _this;
+ }
+ TwoColorTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.twoColor << 24) + this.slotIndex;
+ };
+ TwoColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a, r2, g2, b2) {
+ frameIndex *= TwoColorTimeline.ENTRIES;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + TwoColorTimeline.R] = r;
+ this.frames[frameIndex + TwoColorTimeline.G] = g;
+ this.frames[frameIndex + TwoColorTimeline.B] = b;
+ this.frames[frameIndex + TwoColorTimeline.A] = a;
+ this.frames[frameIndex + TwoColorTimeline.R2] = r2;
+ this.frames[frameIndex + TwoColorTimeline.G2] = g2;
+ this.frames[frameIndex + TwoColorTimeline.B2] = b2;
+ };
+ TwoColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) {
+ var slot = skeleton.slots[this.slotIndex];
+ var frames = this.frames;
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ slot.color.setFromColor(slot.data.color);
+ slot.darkColor.setFromColor(slot.data.darkColor);
+ return;
+ case MixPose.current:
+ var light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor;
+ light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha);
+ dark.add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0);
+ }
+ return;
+ }
+ var r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;
+ if (time >= frames[frames.length - TwoColorTimeline.ENTRIES]) {
+ var i = frames.length;
+ r = frames[i + TwoColorTimeline.PREV_R];
+ g = frames[i + TwoColorTimeline.PREV_G];
+ b = frames[i + TwoColorTimeline.PREV_B];
+ a = frames[i + TwoColorTimeline.PREV_A];
+ r2 = frames[i + TwoColorTimeline.PREV_R2];
+ g2 = frames[i + TwoColorTimeline.PREV_G2];
+ b2 = frames[i + TwoColorTimeline.PREV_B2];
+ }
+ else {
+ var frame = Animation.binarySearch(frames, time, TwoColorTimeline.ENTRIES);
+ r = frames[frame + TwoColorTimeline.PREV_R];
+ g = frames[frame + TwoColorTimeline.PREV_G];
+ b = frames[frame + TwoColorTimeline.PREV_B];
+ a = frames[frame + TwoColorTimeline.PREV_A];
+ r2 = frames[frame + TwoColorTimeline.PREV_R2];
+ g2 = frames[frame + TwoColorTimeline.PREV_G2];
+ b2 = frames[frame + TwoColorTimeline.PREV_B2];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / TwoColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TwoColorTimeline.PREV_TIME] - frameTime));
+ r += (frames[frame + TwoColorTimeline.R] - r) * percent;
+ g += (frames[frame + TwoColorTimeline.G] - g) * percent;
+ b += (frames[frame + TwoColorTimeline.B] - b) * percent;
+ a += (frames[frame + TwoColorTimeline.A] - a) * percent;
+ r2 += (frames[frame + TwoColorTimeline.R2] - r2) * percent;
+ g2 += (frames[frame + TwoColorTimeline.G2] - g2) * percent;
+ b2 += (frames[frame + TwoColorTimeline.B2] - b2) * percent;
+ }
+ if (alpha == 1) {
+ slot.color.set(r, g, b, a);
+ slot.darkColor.set(r2, g2, b2, 1);
+ }
+ else {
+ var light = slot.color, dark = slot.darkColor;
+ if (pose == MixPose.setup) {
+ light.setFromColor(slot.data.color);
+ dark.setFromColor(slot.data.darkColor);
+ }
+ light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
+ dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0);
+ }
+ };
+ return TwoColorTimeline;
+ }(CurveTimeline));
+ TwoColorTimeline.ENTRIES = 8;
+ TwoColorTimeline.PREV_TIME = -8;
+ TwoColorTimeline.PREV_R = -7;
+ TwoColorTimeline.PREV_G = -6;
+ TwoColorTimeline.PREV_B = -5;
+ TwoColorTimeline.PREV_A = -4;
+ TwoColorTimeline.PREV_R2 = -3;
+ TwoColorTimeline.PREV_G2 = -2;
+ TwoColorTimeline.PREV_B2 = -1;
+ TwoColorTimeline.R = 1;
+ TwoColorTimeline.G = 2;
+ TwoColorTimeline.B = 3;
+ TwoColorTimeline.A = 4;
+ TwoColorTimeline.R2 = 5;
+ TwoColorTimeline.G2 = 6;
+ TwoColorTimeline.B2 = 7;
+ spine.TwoColorTimeline = TwoColorTimeline;
+ var AttachmentTimeline = (function () {
+ function AttachmentTimeline(frameCount) {
+ this.frames = spine.Utils.newFloatArray(frameCount);
+ this.attachmentNames = new Array(frameCount);
+ }
+ AttachmentTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.attachment << 24) + this.slotIndex;
+ };
+ AttachmentTimeline.prototype.getFrameCount = function () {
+ return this.frames.length;
+ };
+ AttachmentTimeline.prototype.setFrame = function (frameIndex, time, attachmentName) {
+ this.frames[frameIndex] = time;
+ this.attachmentNames[frameIndex] = attachmentName;
+ };
+ AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) {
+ var slot = skeleton.slots[this.slotIndex];
+ if (direction == MixDirection.out && pose == MixPose.setup) {
+ var attachmentName_1 = slot.data.attachmentName;
+ slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1));
+ return;
+ }
+ var frames = this.frames;
+ if (time < frames[0]) {
+ if (pose == MixPose.setup) {
+ var attachmentName_2 = slot.data.attachmentName;
+ slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2));
+ }
+ return;
+ }
+ var frameIndex = 0;
+ if (time >= frames[frames.length - 1])
+ frameIndex = frames.length - 1;
+ else
+ frameIndex = Animation.binarySearch(frames, time, 1) - 1;
+ var attachmentName = this.attachmentNames[frameIndex];
+ skeleton.slots[this.slotIndex]
+ .setAttachment(attachmentName == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
+ };
+ return AttachmentTimeline;
+ }());
+ spine.AttachmentTimeline = AttachmentTimeline;
+ var zeros = null;
+ var DeformTimeline = (function (_super) {
+ __extends(DeformTimeline, _super);
+ function DeformTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount);
+ _this.frameVertices = new Array(frameCount);
+ if (zeros == null)
+ zeros = spine.Utils.newFloatArray(64);
+ return _this;
+ }
+ DeformTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.deform << 27) + +this.attachment.id + this.slotIndex;
+ };
+ DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) {
+ this.frames[frameIndex] = time;
+ this.frameVertices[frameIndex] = vertices;
+ };
+ DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ var slot = skeleton.slots[this.slotIndex];
+ var slotAttachment = slot.getAttachment();
+ if (!(slotAttachment instanceof spine.VertexAttachment) || !slotAttachment.applyDeform(this.attachment))
+ return;
+ var verticesArray = slot.attachmentVertices;
+ var frameVertices = this.frameVertices;
+ var vertexCount = frameVertices[0].length;
+ var vertices = spine.Utils.setArraySize(verticesArray, vertexCount);
+ var frames = this.frames;
+ if (time < frames[0]) {
+ var vertexAttachment = slotAttachment;
+ switch (pose) {
+ case MixPose.setup:
+ var zeroVertices;
+ if (vertexAttachment.bones == null) {
+ zeroVertices = vertexAttachment.vertices;
+ }
+ else {
+ zeroVertices = zeros;
+ if (zeroVertices.length < vertexCount)
+ zeros = zeroVertices = spine.Utils.newFloatArray(vertexCount);
+ }
+ spine.Utils.arrayCopy(zeroVertices, 0, vertices, 0, vertexCount);
+ return;
+ case MixPose.current:
+ if (alpha == 1)
+ break;
+ if (vertexAttachment.bones == null) {
+ var setupVertices = vertexAttachment.vertices;
+ for (var i = 0; i < vertexCount; i++)
+ vertices[i] += (setupVertices[i] - vertices[i]) * alpha;
+ }
+ else {
+ alpha = 1 - alpha;
+ for (var i = 0; i < vertexCount; i++)
+ vertices[i] *= alpha;
+ }
+ }
+ return;
+ }
+ if (time >= frames[frames.length - 1]) {
+ var lastVertices = frameVertices[frames.length - 1];
+ if (alpha == 1) {
+ spine.Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount);
+ }
+ else if (pose == MixPose.setup) {
+ var vertexAttachment = slotAttachment;
+ if (vertexAttachment.bones == null) {
+ var setupVertices_1 = vertexAttachment.vertices;
+ for (var i_1 = 0; i_1 < vertexCount; i_1++) {
+ var setup = setupVertices_1[i_1];
+ vertices[i_1] = setup + (lastVertices[i_1] - setup) * alpha;
+ }
+ }
+ else {
+ for (var i_2 = 0; i_2 < vertexCount; i_2++)
+ vertices[i_2] = lastVertices[i_2] * alpha;
+ }
+ }
+ else {
+ for (var i_3 = 0; i_3 < vertexCount; i_3++)
+ vertices[i_3] += (lastVertices[i_3] - vertices[i_3]) * alpha;
+ }
+ return;
+ }
+ var frame = Animation.binarySearch(frames, time);
+ var prevVertices = frameVertices[frame - 1];
+ var nextVertices = frameVertices[frame];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));
+ if (alpha == 1) {
+ for (var i_4 = 0; i_4 < vertexCount; i_4++) {
+ var prev = prevVertices[i_4];
+ vertices[i_4] = prev + (nextVertices[i_4] - prev) * percent;
+ }
+ }
+ else if (pose == MixPose.setup) {
+ var vertexAttachment = slotAttachment;
+ if (vertexAttachment.bones == null) {
+ var setupVertices_2 = vertexAttachment.vertices;
+ for (var i_5 = 0; i_5 < vertexCount; i_5++) {
+ var prev = prevVertices[i_5], setup = setupVertices_2[i_5];
+ vertices[i_5] = setup + (prev + (nextVertices[i_5] - prev) * percent - setup) * alpha;
+ }
+ }
+ else {
+ for (var i_6 = 0; i_6 < vertexCount; i_6++) {
+ var prev = prevVertices[i_6];
+ vertices[i_6] = (prev + (nextVertices[i_6] - prev) * percent) * alpha;
+ }
+ }
+ }
+ else {
+ for (var i_7 = 0; i_7 < vertexCount; i_7++) {
+ var prev = prevVertices[i_7];
+ vertices[i_7] += (prev + (nextVertices[i_7] - prev) * percent - vertices[i_7]) * alpha;
+ }
+ }
+ };
+ return DeformTimeline;
+ }(CurveTimeline));
+ spine.DeformTimeline = DeformTimeline;
+ var EventTimeline = (function () {
+ function EventTimeline(frameCount) {
+ this.frames = spine.Utils.newFloatArray(frameCount);
+ this.events = new Array(frameCount);
+ }
+ EventTimeline.prototype.getPropertyId = function () {
+ return TimelineType.event << 24;
+ };
+ EventTimeline.prototype.getFrameCount = function () {
+ return this.frames.length;
+ };
+ EventTimeline.prototype.setFrame = function (frameIndex, event) {
+ this.frames[frameIndex] = event.time;
+ this.events[frameIndex] = event;
+ };
+ EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ if (firedEvents == null)
+ return;
+ var frames = this.frames;
+ var frameCount = this.frames.length;
+ if (lastTime > time) {
+ this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, pose, direction);
+ lastTime = -1;
+ }
+ else if (lastTime >= frames[frameCount - 1])
+ return;
+ if (time < frames[0])
+ return;
+ var frame = 0;
+ if (lastTime < frames[0])
+ frame = 0;
+ else {
+ frame = Animation.binarySearch(frames, lastTime);
+ var frameTime = frames[frame];
+ while (frame > 0) {
+ if (frames[frame - 1] != frameTime)
+ break;
+ frame--;
+ }
+ }
+ for (; frame < frameCount && time >= frames[frame]; frame++)
+ firedEvents.push(this.events[frame]);
+ };
+ return EventTimeline;
+ }());
+ spine.EventTimeline = EventTimeline;
+ var DrawOrderTimeline = (function () {
+ function DrawOrderTimeline(frameCount) {
+ this.frames = spine.Utils.newFloatArray(frameCount);
+ this.drawOrders = new Array(frameCount);
+ }
+ DrawOrderTimeline.prototype.getPropertyId = function () {
+ return TimelineType.drawOrder << 24;
+ };
+ DrawOrderTimeline.prototype.getFrameCount = function () {
+ return this.frames.length;
+ };
+ DrawOrderTimeline.prototype.setFrame = function (frameIndex, time, drawOrder) {
+ this.frames[frameIndex] = time;
+ this.drawOrders[frameIndex] = drawOrder;
+ };
+ DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ var drawOrder = skeleton.drawOrder;
+ var slots = skeleton.slots;
+ if (direction == MixDirection.out && pose == MixPose.setup) {
+ spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
+ return;
+ }
+ var frames = this.frames;
+ if (time < frames[0]) {
+ if (pose == MixPose.setup)
+ spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
+ return;
+ }
+ var frame = 0;
+ if (time >= frames[frames.length - 1])
+ frame = frames.length - 1;
+ else
+ frame = Animation.binarySearch(frames, time) - 1;
+ var drawOrderToSetupIndex = this.drawOrders[frame];
+ if (drawOrderToSetupIndex == null)
+ spine.Utils.arrayCopy(slots, 0, drawOrder, 0, slots.length);
+ else {
+ for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
+ drawOrder[i] = slots[drawOrderToSetupIndex[i]];
+ }
+ };
+ return DrawOrderTimeline;
+ }());
+ spine.DrawOrderTimeline = DrawOrderTimeline;
+ var IkConstraintTimeline = (function (_super) {
+ __extends(IkConstraintTimeline, _super);
+ function IkConstraintTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES);
+ return _this;
+ }
+ IkConstraintTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex;
+ };
+ IkConstraintTimeline.prototype.setFrame = function (frameIndex, time, mix, bendDirection) {
+ frameIndex *= IkConstraintTimeline.ENTRIES;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + IkConstraintTimeline.MIX] = mix;
+ this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection;
+ };
+ IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ var frames = this.frames;
+ var constraint = skeleton.ikConstraints[this.ikConstraintIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ constraint.mix = constraint.data.mix;
+ constraint.bendDirection = constraint.data.bendDirection;
+ return;
+ case MixPose.current:
+ constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
+ constraint.bendDirection = constraint.data.bendDirection;
+ }
+ return;
+ }
+ if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) {
+ if (pose == MixPose.setup) {
+ constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha;
+ constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection
+ : frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION];
+ }
+ else {
+ constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha;
+ if (direction == MixDirection["in"])
+ constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION];
+ }
+ return;
+ }
+ var frame = Animation.binarySearch(frames, time, IkConstraintTimeline.ENTRIES);
+ var mix = frames[frame + IkConstraintTimeline.PREV_MIX];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime));
+ if (pose == MixPose.setup) {
+ constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha;
+ constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION];
+ }
+ else {
+ constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha;
+ if (direction == MixDirection["in"])
+ constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION];
+ }
+ };
+ return IkConstraintTimeline;
+ }(CurveTimeline));
+ IkConstraintTimeline.ENTRIES = 3;
+ IkConstraintTimeline.PREV_TIME = -3;
+ IkConstraintTimeline.PREV_MIX = -2;
+ IkConstraintTimeline.PREV_BEND_DIRECTION = -1;
+ IkConstraintTimeline.MIX = 1;
+ IkConstraintTimeline.BEND_DIRECTION = 2;
+ spine.IkConstraintTimeline = IkConstraintTimeline;
+ var TransformConstraintTimeline = (function (_super) {
+ __extends(TransformConstraintTimeline, _super);
+ function TransformConstraintTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES);
+ return _this;
+ }
+ TransformConstraintTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex;
+ };
+ TransformConstraintTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix, scaleMix, shearMix) {
+ frameIndex *= TransformConstraintTimeline.ENTRIES;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + TransformConstraintTimeline.ROTATE] = rotateMix;
+ this.frames[frameIndex + TransformConstraintTimeline.TRANSLATE] = translateMix;
+ this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix;
+ this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix;
+ };
+ TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ var frames = this.frames;
+ var constraint = skeleton.transformConstraints[this.transformConstraintIndex];
+ if (time < frames[0]) {
+ var data = constraint.data;
+ switch (pose) {
+ case MixPose.setup:
+ constraint.rotateMix = data.rotateMix;
+ constraint.translateMix = data.translateMix;
+ constraint.scaleMix = data.scaleMix;
+ constraint.shearMix = data.shearMix;
+ return;
+ case MixPose.current:
+ constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha;
+ constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha;
+ constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha;
+ constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha;
+ }
+ return;
+ }
+ var rotate = 0, translate = 0, scale = 0, shear = 0;
+ if (time >= frames[frames.length - TransformConstraintTimeline.ENTRIES]) {
+ var i = frames.length;
+ rotate = frames[i + TransformConstraintTimeline.PREV_ROTATE];
+ translate = frames[i + TransformConstraintTimeline.PREV_TRANSLATE];
+ scale = frames[i + TransformConstraintTimeline.PREV_SCALE];
+ shear = frames[i + TransformConstraintTimeline.PREV_SHEAR];
+ }
+ else {
+ var frame = Animation.binarySearch(frames, time, TransformConstraintTimeline.ENTRIES);
+ rotate = frames[frame + TransformConstraintTimeline.PREV_ROTATE];
+ translate = frames[frame + TransformConstraintTimeline.PREV_TRANSLATE];
+ scale = frames[frame + TransformConstraintTimeline.PREV_SCALE];
+ shear = frames[frame + TransformConstraintTimeline.PREV_SHEAR];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / TransformConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TransformConstraintTimeline.PREV_TIME] - frameTime));
+ rotate += (frames[frame + TransformConstraintTimeline.ROTATE] - rotate) * percent;
+ translate += (frames[frame + TransformConstraintTimeline.TRANSLATE] - translate) * percent;
+ scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent;
+ shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent;
+ }
+ if (pose == MixPose.setup) {
+ var data = constraint.data;
+ constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha;
+ constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha;
+ constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha;
+ constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha;
+ }
+ else {
+ constraint.rotateMix += (rotate - constraint.rotateMix) * alpha;
+ constraint.translateMix += (translate - constraint.translateMix) * alpha;
+ constraint.scaleMix += (scale - constraint.scaleMix) * alpha;
+ constraint.shearMix += (shear - constraint.shearMix) * alpha;
+ }
+ };
+ return TransformConstraintTimeline;
+ }(CurveTimeline));
+ TransformConstraintTimeline.ENTRIES = 5;
+ TransformConstraintTimeline.PREV_TIME = -5;
+ TransformConstraintTimeline.PREV_ROTATE = -4;
+ TransformConstraintTimeline.PREV_TRANSLATE = -3;
+ TransformConstraintTimeline.PREV_SCALE = -2;
+ TransformConstraintTimeline.PREV_SHEAR = -1;
+ TransformConstraintTimeline.ROTATE = 1;
+ TransformConstraintTimeline.TRANSLATE = 2;
+ TransformConstraintTimeline.SCALE = 3;
+ TransformConstraintTimeline.SHEAR = 4;
+ spine.TransformConstraintTimeline = TransformConstraintTimeline;
+ var PathConstraintPositionTimeline = (function (_super) {
+ __extends(PathConstraintPositionTimeline, _super);
+ function PathConstraintPositionTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES);
+ return _this;
+ }
+ PathConstraintPositionTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex;
+ };
+ PathConstraintPositionTimeline.prototype.setFrame = function (frameIndex, time, value) {
+ frameIndex *= PathConstraintPositionTimeline.ENTRIES;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value;
+ };
+ PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ var frames = this.frames;
+ var constraint = skeleton.pathConstraints[this.pathConstraintIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ constraint.position = constraint.data.position;
+ return;
+ case MixPose.current:
+ constraint.position += (constraint.data.position - constraint.position) * alpha;
+ }
+ return;
+ }
+ var position = 0;
+ if (time >= frames[frames.length - PathConstraintPositionTimeline.ENTRIES])
+ position = frames[frames.length + PathConstraintPositionTimeline.PREV_VALUE];
+ else {
+ var frame = Animation.binarySearch(frames, time, PathConstraintPositionTimeline.ENTRIES);
+ position = frames[frame + PathConstraintPositionTimeline.PREV_VALUE];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime));
+ position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent;
+ }
+ if (pose == MixPose.setup)
+ constraint.position = constraint.data.position + (position - constraint.data.position) * alpha;
+ else
+ constraint.position += (position - constraint.position) * alpha;
+ };
+ return PathConstraintPositionTimeline;
+ }(CurveTimeline));
+ PathConstraintPositionTimeline.ENTRIES = 2;
+ PathConstraintPositionTimeline.PREV_TIME = -2;
+ PathConstraintPositionTimeline.PREV_VALUE = -1;
+ PathConstraintPositionTimeline.VALUE = 1;
+ spine.PathConstraintPositionTimeline = PathConstraintPositionTimeline;
+ var PathConstraintSpacingTimeline = (function (_super) {
+ __extends(PathConstraintSpacingTimeline, _super);
+ function PathConstraintSpacingTimeline(frameCount) {
+ return _super.call(this, frameCount) || this;
+ }
+ PathConstraintSpacingTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex;
+ };
+ PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ var frames = this.frames;
+ var constraint = skeleton.pathConstraints[this.pathConstraintIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ constraint.spacing = constraint.data.spacing;
+ return;
+ case MixPose.current:
+ constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha;
+ }
+ return;
+ }
+ var spacing = 0;
+ if (time >= frames[frames.length - PathConstraintSpacingTimeline.ENTRIES])
+ spacing = frames[frames.length + PathConstraintSpacingTimeline.PREV_VALUE];
+ else {
+ var frame = Animation.binarySearch(frames, time, PathConstraintSpacingTimeline.ENTRIES);
+ spacing = frames[frame + PathConstraintSpacingTimeline.PREV_VALUE];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime));
+ spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent;
+ }
+ if (pose == MixPose.setup)
+ constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha;
+ else
+ constraint.spacing += (spacing - constraint.spacing) * alpha;
+ };
+ return PathConstraintSpacingTimeline;
+ }(PathConstraintPositionTimeline));
+ spine.PathConstraintSpacingTimeline = PathConstraintSpacingTimeline;
+ var PathConstraintMixTimeline = (function (_super) {
+ __extends(PathConstraintMixTimeline, _super);
+ function PathConstraintMixTimeline(frameCount) {
+ var _this = _super.call(this, frameCount) || this;
+ _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES);
+ return _this;
+ }
+ PathConstraintMixTimeline.prototype.getPropertyId = function () {
+ return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex;
+ };
+ PathConstraintMixTimeline.prototype.setFrame = function (frameIndex, time, rotateMix, translateMix) {
+ frameIndex *= PathConstraintMixTimeline.ENTRIES;
+ this.frames[frameIndex] = time;
+ this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix;
+ this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix;
+ };
+ PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) {
+ var frames = this.frames;
+ var constraint = skeleton.pathConstraints[this.pathConstraintIndex];
+ if (time < frames[0]) {
+ switch (pose) {
+ case MixPose.setup:
+ constraint.rotateMix = constraint.data.rotateMix;
+ constraint.translateMix = constraint.data.translateMix;
+ return;
+ case MixPose.current:
+ constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha;
+ constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha;
+ }
+ return;
+ }
+ var rotate = 0, translate = 0;
+ if (time >= frames[frames.length - PathConstraintMixTimeline.ENTRIES]) {
+ rotate = frames[frames.length + PathConstraintMixTimeline.PREV_ROTATE];
+ translate = frames[frames.length + PathConstraintMixTimeline.PREV_TRANSLATE];
+ }
+ else {
+ var frame = Animation.binarySearch(frames, time, PathConstraintMixTimeline.ENTRIES);
+ rotate = frames[frame + PathConstraintMixTimeline.PREV_ROTATE];
+ translate = frames[frame + PathConstraintMixTimeline.PREV_TRANSLATE];
+ var frameTime = frames[frame];
+ var percent = this.getCurvePercent(frame / PathConstraintMixTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintMixTimeline.PREV_TIME] - frameTime));
+ rotate += (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent;
+ translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent;
+ }
+ if (pose == MixPose.setup) {
+ constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha;
+ constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha;
+ }
+ else {
+ constraint.rotateMix += (rotate - constraint.rotateMix) * alpha;
+ constraint.translateMix += (translate - constraint.translateMix) * alpha;
+ }
+ };
+ return PathConstraintMixTimeline;
+ }(CurveTimeline));
+ PathConstraintMixTimeline.ENTRIES = 3;
+ PathConstraintMixTimeline.PREV_TIME = -3;
+ PathConstraintMixTimeline.PREV_ROTATE = -2;
+ PathConstraintMixTimeline.PREV_TRANSLATE = -1;
+ PathConstraintMixTimeline.ROTATE = 1;
+ PathConstraintMixTimeline.TRANSLATE = 2;
+ spine.PathConstraintMixTimeline = PathConstraintMixTimeline;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var AnimationState = (function () {
+ function AnimationState(data) {
+ this.tracks = new Array();
+ this.events = new Array();
+ this.listeners = new Array();
+ this.queue = new EventQueue(this);
+ this.propertyIDs = new spine.IntSet();
+ this.mixingTo = new Array();
+ this.animationsChanged = false;
+ this.timeScale = 1;
+ this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); });
+ this.data = data;
+ }
+ AnimationState.prototype.update = function (delta) {
+ delta *= this.timeScale;
+ var tracks = this.tracks;
+ for (var i = 0, n = tracks.length; i < n; i++) {
+ var current = tracks[i];
+ if (current == null)
+ continue;
+ current.animationLast = current.nextAnimationLast;
+ current.trackLast = current.nextTrackLast;
+ var currentDelta = delta * current.timeScale;
+ if (current.delay > 0) {
+ current.delay -= currentDelta;
+ if (current.delay > 0)
+ continue;
+ currentDelta = -current.delay;
+ current.delay = 0;
+ }
+ var next = current.next;
+ if (next != null) {
+ var nextTime = current.trackLast - next.delay;
+ if (nextTime >= 0) {
+ next.delay = 0;
+ next.trackTime = nextTime + delta * next.timeScale;
+ current.trackTime += currentDelta;
+ this.setCurrent(i, next, true);
+ while (next.mixingFrom != null) {
+ next.mixTime += currentDelta;
+ next = next.mixingFrom;
+ }
+ continue;
+ }
+ }
+ else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) {
+ tracks[i] = null;
+ this.queue.end(current);
+ this.disposeNext(current);
+ continue;
+ }
+ if (current.mixingFrom != null && this.updateMixingFrom(current, delta)) {
+ var from = current.mixingFrom;
+ current.mixingFrom = null;
+ while (from != null) {
+ this.queue.end(from);
+ from = from.mixingFrom;
+ }
+ }
+ current.trackTime += currentDelta;
+ }
+ this.queue.drain();
+ };
+ AnimationState.prototype.updateMixingFrom = function (to, delta) {
+ var from = to.mixingFrom;
+ if (from == null)
+ return true;
+ var finished = this.updateMixingFrom(from, delta);
+ if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) {
+ if (from.totalAlpha == 0 || to.mixDuration == 0) {
+ to.mixingFrom = from.mixingFrom;
+ to.interruptAlpha = from.interruptAlpha;
+ this.queue.end(from);
+ }
+ return finished;
+ }
+ from.animationLast = from.nextAnimationLast;
+ from.trackLast = from.nextTrackLast;
+ from.trackTime += delta * from.timeScale;
+ to.mixTime += delta * to.timeScale;
+ return false;
+ };
+ AnimationState.prototype.apply = function (skeleton) {
+ if (skeleton == null)
+ throw new Error("skeleton cannot be null.");
+ if (this.animationsChanged)
+ this._animationsChanged();
+ var events = this.events;
+ var tracks = this.tracks;
+ var applied = false;
+ for (var i = 0, n = tracks.length; i < n; i++) {
+ var current = tracks[i];
+ if (current == null || current.delay > 0)
+ continue;
+ applied = true;
+ var currentPose = i == 0 ? spine.MixPose.current : spine.MixPose.currentLayered;
+ var mix = current.alpha;
+ if (current.mixingFrom != null)
+ mix *= this.applyMixingFrom(current, skeleton, currentPose);
+ else if (current.trackTime >= current.trackEnd && current.next == null)
+ mix = 0;
+ var animationLast = current.animationLast, animationTime = current.getAnimationTime();
+ var timelineCount = current.animation.timelines.length;
+ var timelines = current.animation.timelines;
+ if (mix == 1) {
+ for (var ii = 0; ii < timelineCount; ii++)
+ timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, spine.MixPose.setup, spine.MixDirection["in"]);
+ }
+ else {
+ var timelineData = current.timelineData;
+ var firstFrame = current.timelinesRotation.length == 0;
+ if (firstFrame)
+ spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null);
+ var timelinesRotation = current.timelinesRotation;
+ for (var ii = 0; ii < timelineCount; ii++) {
+ var timeline = timelines[ii];
+ var pose = timelineData[ii] >= AnimationState.FIRST ? spine.MixPose.setup : currentPose;
+ if (timeline instanceof spine.RotateTimeline) {
+ this.applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame);
+ }
+ else
+ timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, spine.MixDirection["in"]);
+ }
+ }
+ this.queueEvents(current, animationTime);
+ events.length = 0;
+ current.nextAnimationLast = animationTime;
+ current.nextTrackLast = current.trackTime;
+ }
+ this.queue.drain();
+ return applied;
+ };
+ AnimationState.prototype.applyMixingFrom = function (to, skeleton, currentPose) {
+ var from = to.mixingFrom;
+ if (from.mixingFrom != null)
+ this.applyMixingFrom(from, skeleton, currentPose);
+ var mix = 0;
+ if (to.mixDuration == 0)
+ mix = 1;
+ else {
+ mix = to.mixTime / to.mixDuration;
+ if (mix > 1)
+ mix = 1;
+ }
+ var events = mix < from.eventThreshold ? this.events : null;
+ var attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold;
+ var animationLast = from.animationLast, animationTime = from.getAnimationTime();
+ var timelineCount = from.animation.timelines.length;
+ var timelines = from.animation.timelines;
+ var timelineData = from.timelineData;
+ var timelineDipMix = from.timelineDipMix;
+ var firstFrame = from.timelinesRotation.length == 0;
+ if (firstFrame)
+ spine.Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null);
+ var timelinesRotation = from.timelinesRotation;
+ var pose;
+ var alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha = 0;
+ from.totalAlpha = 0;
+ for (var i = 0; i < timelineCount; i++) {
+ var timeline = timelines[i];
+ switch (timelineData[i]) {
+ case AnimationState.SUBSEQUENT:
+ if (!attachments && timeline instanceof spine.AttachmentTimeline)
+ continue;
+ if (!drawOrder && timeline instanceof spine.DrawOrderTimeline)
+ continue;
+ pose = currentPose;
+ alpha = alphaMix;
+ break;
+ case AnimationState.FIRST:
+ pose = spine.MixPose.setup;
+ alpha = alphaMix;
+ break;
+ case AnimationState.DIP:
+ pose = spine.MixPose.setup;
+ alpha = alphaDip;
+ break;
+ default:
+ pose = spine.MixPose.setup;
+ alpha = alphaDip;
+ var dipMix = timelineDipMix[i];
+ alpha *= Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration);
+ break;
+ }
+ from.totalAlpha += alpha;
+ if (timeline instanceof spine.RotateTimeline)
+ this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame);
+ else {
+ timeline.apply(skeleton, animationLast, animationTime, events, alpha, pose, spine.MixDirection.out);
+ }
+ }
+ if (to.mixDuration > 0)
+ this.queueEvents(from, animationTime);
+ this.events.length = 0;
+ from.nextAnimationLast = animationTime;
+ from.nextTrackLast = from.trackTime;
+ return mix;
+ };
+ AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, pose, timelinesRotation, i, firstFrame) {
+ if (firstFrame)
+ timelinesRotation[i] = 0;
+ if (alpha == 1) {
+ timeline.apply(skeleton, 0, time, null, 1, pose, spine.MixDirection["in"]);
+ return;
+ }
+ var rotateTimeline = timeline;
+ var frames = rotateTimeline.frames;
+ var bone = skeleton.bones[rotateTimeline.boneIndex];
+ if (time < frames[0]) {
+ if (pose == spine.MixPose.setup)
+ bone.rotation = bone.data.rotation;
+ return;
+ }
+ var r2 = 0;
+ if (time >= frames[frames.length - spine.RotateTimeline.ENTRIES])
+ r2 = bone.data.rotation + frames[frames.length + spine.RotateTimeline.PREV_ROTATION];
+ else {
+ var frame = spine.Animation.binarySearch(frames, time, spine.RotateTimeline.ENTRIES);
+ var prevRotation = frames[frame + spine.RotateTimeline.PREV_ROTATION];
+ var frameTime = frames[frame];
+ var percent = rotateTimeline.getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + spine.RotateTimeline.PREV_TIME] - frameTime));
+ r2 = frames[frame + spine.RotateTimeline.ROTATION] - prevRotation;
+ r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360;
+ r2 = prevRotation + r2 * percent + bone.data.rotation;
+ r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360;
+ }
+ var r1 = pose == spine.MixPose.setup ? bone.data.rotation : bone.rotation;
+ var total = 0, diff = r2 - r1;
+ if (diff == 0) {
+ total = timelinesRotation[i];
+ }
+ else {
+ diff -= (16384 - ((16384.499999999996 - diff / 360) | 0)) * 360;
+ var lastTotal = 0, lastDiff = 0;
+ if (firstFrame) {
+ lastTotal = 0;
+ lastDiff = diff;
+ }
+ else {
+ lastTotal = timelinesRotation[i];
+ lastDiff = timelinesRotation[i + 1];
+ }
+ var current = diff > 0, dir = lastTotal >= 0;
+ if (spine.MathUtils.signum(lastDiff) != spine.MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) {
+ if (Math.abs(lastTotal) > 180)
+ lastTotal += 360 * spine.MathUtils.signum(lastTotal);
+ dir = current;
+ }
+ total = diff + lastTotal - lastTotal % 360;
+ if (dir != current)
+ total += 360 * spine.MathUtils.signum(lastTotal);
+ timelinesRotation[i] = total;
+ }
+ timelinesRotation[i + 1] = diff;
+ r1 += total * alpha;
+ bone.rotation = r1 - (16384 - ((16384.499999999996 - r1 / 360) | 0)) * 360;
+ };
+ AnimationState.prototype.queueEvents = function (entry, animationTime) {
+ var animationStart = entry.animationStart, animationEnd = entry.animationEnd;
+ var duration = animationEnd - animationStart;
+ var trackLastWrapped = entry.trackLast % duration;
+ var events = this.events;
+ var i = 0, n = events.length;
+ for (; i < n; i++) {
+ var event_1 = events[i];
+ if (event_1.time < trackLastWrapped)
+ break;
+ if (event_1.time > animationEnd)
+ continue;
+ this.queue.event(entry, event_1);
+ }
+ if (entry.loop ? (trackLastWrapped > entry.trackTime % duration)
+ : (animationTime >= animationEnd && entry.animationLast < animationEnd)) {
+ this.queue.complete(entry);
+ }
+ for (; i < n; i++) {
+ var event_2 = events[i];
+ if (event_2.time < animationStart)
+ continue;
+ this.queue.event(entry, events[i]);
+ }
+ };
+ AnimationState.prototype.clearTracks = function () {
+ var oldDrainDisabled = this.queue.drainDisabled;
+ this.queue.drainDisabled = true;
+ for (var i = 0, n = this.tracks.length; i < n; i++)
+ this.clearTrack(i);
+ this.tracks.length = 0;
+ this.queue.drainDisabled = oldDrainDisabled;
+ this.queue.drain();
+ };
+ AnimationState.prototype.clearTrack = function (trackIndex) {
+ if (trackIndex >= this.tracks.length)
+ return;
+ var current = this.tracks[trackIndex];
+ if (current == null)
+ return;
+ this.queue.end(current);
+ this.disposeNext(current);
+ var entry = current;
+ while (true) {
+ var from = entry.mixingFrom;
+ if (from == null)
+ break;
+ this.queue.end(from);
+ entry.mixingFrom = null;
+ entry = from;
+ }
+ this.tracks[current.trackIndex] = null;
+ this.queue.drain();
+ };
+ AnimationState.prototype.setCurrent = function (index, current, interrupt) {
+ var from = this.expandToIndex(index);
+ this.tracks[index] = current;
+ if (from != null) {
+ if (interrupt)
+ this.queue.interrupt(from);
+ current.mixingFrom = from;
+ current.mixTime = 0;
+ if (from.mixingFrom != null && from.mixDuration > 0)
+ current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration);
+ from.timelinesRotation.length = 0;
+ }
+ this.queue.start(current);
+ };
+ AnimationState.prototype.setAnimation = function (trackIndex, animationName, loop) {
+ var animation = this.data.skeletonData.findAnimation(animationName);
+ if (animation == null)
+ throw new Error("Animation not found: " + animationName);
+ return this.setAnimationWith(trackIndex, animation, loop);
+ };
+ AnimationState.prototype.setAnimationWith = function (trackIndex, animation, loop) {
+ if (animation == null)
+ throw new Error("animation cannot be null.");
+ var interrupt = true;
+ var current = this.expandToIndex(trackIndex);
+ if (current != null) {
+ if (current.nextTrackLast == -1) {
+ this.tracks[trackIndex] = current.mixingFrom;
+ this.queue.interrupt(current);
+ this.queue.end(current);
+ this.disposeNext(current);
+ current = current.mixingFrom;
+ interrupt = false;
+ }
+ else
+ this.disposeNext(current);
+ }
+ var entry = this.trackEntry(trackIndex, animation, loop, current);
+ this.setCurrent(trackIndex, entry, interrupt);
+ this.queue.drain();
+ return entry;
+ };
+ AnimationState.prototype.addAnimation = function (trackIndex, animationName, loop, delay) {
+ var animation = this.data.skeletonData.findAnimation(animationName);
+ if (animation == null)
+ throw new Error("Animation not found: " + animationName);
+ return this.addAnimationWith(trackIndex, animation, loop, delay);
+ };
+ AnimationState.prototype.addAnimationWith = function (trackIndex, animation, loop, delay) {
+ if (animation == null)
+ throw new Error("animation cannot be null.");
+ var last = this.expandToIndex(trackIndex);
+ if (last != null) {
+ while (last.next != null)
+ last = last.next;
+ }
+ var entry = this.trackEntry(trackIndex, animation, loop, last);
+ if (last == null) {
+ this.setCurrent(trackIndex, entry, true);
+ this.queue.drain();
+ }
+ else {
+ last.next = entry;
+ if (delay <= 0) {
+ var duration = last.animationEnd - last.animationStart;
+ if (duration != 0)
+ delay += duration * (1 + ((last.trackTime / duration) | 0)) - this.data.getMix(last.animation, animation);
+ else
+ delay = 0;
+ }
+ }
+ entry.delay = delay;
+ return entry;
+ };
+ AnimationState.prototype.setEmptyAnimation = function (trackIndex, mixDuration) {
+ var entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation, false);
+ entry.mixDuration = mixDuration;
+ entry.trackEnd = mixDuration;
+ return entry;
+ };
+ AnimationState.prototype.addEmptyAnimation = function (trackIndex, mixDuration, delay) {
+ if (delay <= 0)
+ delay -= mixDuration;
+ var entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation, false, delay);
+ entry.mixDuration = mixDuration;
+ entry.trackEnd = mixDuration;
+ return entry;
+ };
+ AnimationState.prototype.setEmptyAnimations = function (mixDuration) {
+ var oldDrainDisabled = this.queue.drainDisabled;
+ this.queue.drainDisabled = true;
+ for (var i = 0, n = this.tracks.length; i < n; i++) {
+ var current = this.tracks[i];
+ if (current != null)
+ this.setEmptyAnimation(current.trackIndex, mixDuration);
+ }
+ this.queue.drainDisabled = oldDrainDisabled;
+ this.queue.drain();
+ };
+ AnimationState.prototype.expandToIndex = function (index) {
+ if (index < this.tracks.length)
+ return this.tracks[index];
+ spine.Utils.ensureArrayCapacity(this.tracks, index - this.tracks.length + 1, null);
+ this.tracks.length = index + 1;
+ return null;
+ };
+ AnimationState.prototype.trackEntry = function (trackIndex, animation, loop, last) {
+ var entry = this.trackEntryPool.obtain();
+ entry.trackIndex = trackIndex;
+ entry.animation = animation;
+ entry.loop = loop;
+ entry.eventThreshold = 0;
+ entry.attachmentThreshold = 0;
+ entry.drawOrderThreshold = 0;
+ entry.animationStart = 0;
+ entry.animationEnd = animation.duration;
+ entry.animationLast = -1;
+ entry.nextAnimationLast = -1;
+ entry.delay = 0;
+ entry.trackTime = 0;
+ entry.trackLast = -1;
+ entry.nextTrackLast = -1;
+ entry.trackEnd = Number.MAX_VALUE;
+ entry.timeScale = 1;
+ entry.alpha = 1;
+ entry.interruptAlpha = 1;
+ entry.mixTime = 0;
+ entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation);
+ return entry;
+ };
+ AnimationState.prototype.disposeNext = function (entry) {
+ var next = entry.next;
+ while (next != null) {
+ this.queue.dispose(next);
+ next = next.next;
+ }
+ entry.next = null;
+ };
+ AnimationState.prototype._animationsChanged = function () {
+ this.animationsChanged = false;
+ var propertyIDs = this.propertyIDs;
+ propertyIDs.clear();
+ var mixingTo = this.mixingTo;
+ for (var i = 0, n = this.tracks.length; i < n; i++) {
+ var entry = this.tracks[i];
+ if (entry != null)
+ entry.setTimelineData(null, mixingTo, propertyIDs);
+ }
+ };
+ AnimationState.prototype.getCurrent = function (trackIndex) {
+ if (trackIndex >= this.tracks.length)
+ return null;
+ return this.tracks[trackIndex];
+ };
+ AnimationState.prototype.addListener = function (listener) {
+ if (listener == null)
+ throw new Error("listener cannot be null.");
+ this.listeners.push(listener);
+ };
+ AnimationState.prototype.removeListener = function (listener) {
+ var index = this.listeners.indexOf(listener);
+ if (index >= 0)
+ this.listeners.splice(index, 1);
+ };
+ AnimationState.prototype.clearListeners = function () {
+ this.listeners.length = 0;
+ };
+ AnimationState.prototype.clearListenerNotifications = function () {
+ this.queue.clear();
+ };
+ return AnimationState;
+ }());
+ AnimationState.emptyAnimation = new spine.Animation("", [], 0);
+ AnimationState.SUBSEQUENT = 0;
+ AnimationState.FIRST = 1;
+ AnimationState.DIP = 2;
+ AnimationState.DIP_MIX = 3;
+ spine.AnimationState = AnimationState;
+ var TrackEntry = (function () {
+ function TrackEntry() {
+ this.timelineData = new Array();
+ this.timelineDipMix = new Array();
+ this.timelinesRotation = new Array();
+ }
+ TrackEntry.prototype.reset = function () {
+ this.next = null;
+ this.mixingFrom = null;
+ this.animation = null;
+ this.listener = null;
+ this.timelineData.length = 0;
+ this.timelineDipMix.length = 0;
+ this.timelinesRotation.length = 0;
+ };
+ TrackEntry.prototype.setTimelineData = function (to, mixingToArray, propertyIDs) {
+ if (to != null)
+ mixingToArray.push(to);
+ var lastEntry = this.mixingFrom != null ? this.mixingFrom.setTimelineData(this, mixingToArray, propertyIDs) : this;
+ if (to != null)
+ mixingToArray.pop();
+ var mixingTo = mixingToArray;
+ var mixingToLast = mixingToArray.length - 1;
+ var timelines = this.animation.timelines;
+ var timelinesCount = this.animation.timelines.length;
+ var timelineData = spine.Utils.setArraySize(this.timelineData, timelinesCount);
+ this.timelineDipMix.length = 0;
+ var timelineDipMix = spine.Utils.setArraySize(this.timelineDipMix, timelinesCount);
+ outer: for (var i = 0; i < timelinesCount; i++) {
+ var id = timelines[i].getPropertyId();
+ if (!propertyIDs.add(id))
+ timelineData[i] = AnimationState.SUBSEQUENT;
+ else if (to == null || !to.hasTimeline(id))
+ timelineData[i] = AnimationState.FIRST;
+ else {
+ for (var ii = mixingToLast; ii >= 0; ii--) {
+ var entry = mixingTo[ii];
+ if (!entry.hasTimeline(id)) {
+ if (entry.mixDuration > 0) {
+ timelineData[i] = AnimationState.DIP_MIX;
+ timelineDipMix[i] = entry;
+ continue outer;
+ }
+ }
+ }
+ timelineData[i] = AnimationState.DIP;
+ }
+ }
+ return lastEntry;
+ };
+ TrackEntry.prototype.hasTimeline = function (id) {
+ var timelines = this.animation.timelines;
+ for (var i = 0, n = timelines.length; i < n; i++)
+ if (timelines[i].getPropertyId() == id)
+ return true;
+ return false;
+ };
+ TrackEntry.prototype.getAnimationTime = function () {
+ if (this.loop) {
+ var duration = this.animationEnd - this.animationStart;
+ if (duration == 0)
+ return this.animationStart;
+ return (this.trackTime % duration) + this.animationStart;
+ }
+ return Math.min(this.trackTime + this.animationStart, this.animationEnd);
+ };
+ TrackEntry.prototype.setAnimationLast = function (animationLast) {
+ this.animationLast = animationLast;
+ this.nextAnimationLast = animationLast;
+ };
+ TrackEntry.prototype.isComplete = function () {
+ return this.trackTime >= this.animationEnd - this.animationStart;
+ };
+ TrackEntry.prototype.resetRotationDirections = function () {
+ this.timelinesRotation.length = 0;
+ };
+ return TrackEntry;
+ }());
+ spine.TrackEntry = TrackEntry;
+ var EventQueue = (function () {
+ function EventQueue(animState) {
+ this.objects = [];
+ this.drainDisabled = false;
+ this.animState = animState;
+ }
+ EventQueue.prototype.start = function (entry) {
+ this.objects.push(EventType.start);
+ this.objects.push(entry);
+ this.animState.animationsChanged = true;
+ };
+ EventQueue.prototype.interrupt = function (entry) {
+ this.objects.push(EventType.interrupt);
+ this.objects.push(entry);
+ };
+ EventQueue.prototype.end = function (entry) {
+ this.objects.push(EventType.end);
+ this.objects.push(entry);
+ this.animState.animationsChanged = true;
+ };
+ EventQueue.prototype.dispose = function (entry) {
+ this.objects.push(EventType.dispose);
+ this.objects.push(entry);
+ };
+ EventQueue.prototype.complete = function (entry) {
+ this.objects.push(EventType.complete);
+ this.objects.push(entry);
+ };
+ EventQueue.prototype.event = function (entry, event) {
+ this.objects.push(EventType.event);
+ this.objects.push(entry);
+ this.objects.push(event);
+ };
+ EventQueue.prototype.drain = function () {
+ if (this.drainDisabled)
+ return;
+ this.drainDisabled = true;
+ var objects = this.objects;
+ var listeners = this.animState.listeners;
+ for (var i = 0; i < objects.length; i += 2) {
+ var type = objects[i];
+ var entry = objects[i + 1];
+ switch (type) {
+ case EventType.start:
+ if (entry.listener != null && entry.listener.start)
+ entry.listener.start(entry);
+ for (var ii = 0; ii < listeners.length; ii++)
+ if (listeners[ii].start)
+ listeners[ii].start(entry);
+ break;
+ case EventType.interrupt:
+ if (entry.listener != null && entry.listener.interrupt)
+ entry.listener.interrupt(entry);
+ for (var ii = 0; ii < listeners.length; ii++)
+ if (listeners[ii].interrupt)
+ listeners[ii].interrupt(entry);
+ break;
+ case EventType.end:
+ if (entry.listener != null && entry.listener.end)
+ entry.listener.end(entry);
+ for (var ii = 0; ii < listeners.length; ii++)
+ if (listeners[ii].end)
+ listeners[ii].end(entry);
+ case EventType.dispose:
+ if (entry.listener != null && entry.listener.dispose)
+ entry.listener.dispose(entry);
+ for (var ii = 0; ii < listeners.length; ii++)
+ if (listeners[ii].dispose)
+ listeners[ii].dispose(entry);
+ this.animState.trackEntryPool.free(entry);
+ break;
+ case EventType.complete:
+ if (entry.listener != null && entry.listener.complete)
+ entry.listener.complete(entry);
+ for (var ii = 0; ii < listeners.length; ii++)
+ if (listeners[ii].complete)
+ listeners[ii].complete(entry);
+ break;
+ case EventType.event:
+ var event_3 = objects[i++ + 2];
+ if (entry.listener != null && entry.listener.event)
+ entry.listener.event(entry, event_3);
+ for (var ii = 0; ii < listeners.length; ii++)
+ if (listeners[ii].event)
+ listeners[ii].event(entry, event_3);
+ break;
+ }
+ }
+ this.clear();
+ this.drainDisabled = false;
+ };
+ EventQueue.prototype.clear = function () {
+ this.objects.length = 0;
+ };
+ return EventQueue;
+ }());
+ spine.EventQueue = EventQueue;
+ var EventType;
+ (function (EventType) {
+ EventType[EventType["start"] = 0] = "start";
+ EventType[EventType["interrupt"] = 1] = "interrupt";
+ EventType[EventType["end"] = 2] = "end";
+ EventType[EventType["dispose"] = 3] = "dispose";
+ EventType[EventType["complete"] = 4] = "complete";
+ EventType[EventType["event"] = 5] = "event";
+ })(EventType = spine.EventType || (spine.EventType = {}));
+ var AnimationStateAdapter2 = (function () {
+ function AnimationStateAdapter2() {
+ }
+ AnimationStateAdapter2.prototype.start = function (entry) {
+ };
+ AnimationStateAdapter2.prototype.interrupt = function (entry) {
+ };
+ AnimationStateAdapter2.prototype.end = function (entry) {
+ };
+ AnimationStateAdapter2.prototype.dispose = function (entry) {
+ };
+ AnimationStateAdapter2.prototype.complete = function (entry) {
+ };
+ AnimationStateAdapter2.prototype.event = function (entry, event) {
+ };
+ return AnimationStateAdapter2;
+ }());
+ spine.AnimationStateAdapter2 = AnimationStateAdapter2;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var AnimationStateData = (function () {
+ function AnimationStateData(skeletonData) {
+ this.animationToMixTime = {};
+ this.defaultMix = 0;
+ if (skeletonData == null)
+ throw new Error("skeletonData cannot be null.");
+ this.skeletonData = skeletonData;
+ }
+ AnimationStateData.prototype.setMix = function (fromName, toName, duration) {
+ var from = this.skeletonData.findAnimation(fromName);
+ if (from == null)
+ throw new Error("Animation not found: " + fromName);
+ var to = this.skeletonData.findAnimation(toName);
+ if (to == null)
+ throw new Error("Animation not found: " + toName);
+ this.setMixWith(from, to, duration);
+ };
+ AnimationStateData.prototype.setMixWith = function (from, to, duration) {
+ if (from == null)
+ throw new Error("from cannot be null.");
+ if (to == null)
+ throw new Error("to cannot be null.");
+ var key = from.name + to.name;
+ this.animationToMixTime[key] = duration;
+ };
+ AnimationStateData.prototype.getMix = function (from, to) {
+ var key = from.name + to.name;
+ var value = this.animationToMixTime[key];
+ return value === undefined ? this.defaultMix : value;
+ };
+ return AnimationStateData;
+ }());
+ spine.AnimationStateData = AnimationStateData;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var AssetManager = (function () {
+ function AssetManager(textureLoader, pathPrefix) {
+ if (pathPrefix === void 0) { pathPrefix = ""; }
+ this.assets = {};
+ this.errors = {};
+ this.toLoad = 0;
+ this.loaded = 0;
+ this.textureLoader = textureLoader;
+ this.pathPrefix = pathPrefix;
+ }
+ AssetManager.prototype.loadText = function (path, success, error) {
+ var _this = this;
+ if (success === void 0) { success = null; }
+ if (error === void 0) { error = null; }
+ path = this.pathPrefix + path;
+ this.toLoad++;
+ var request = new XMLHttpRequest();
+ request.onreadystatechange = function () {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ if (request.status >= 200 && request.status < 300) {
+ _this.assets[path] = request.responseText;
+ if (success)
+ success(path, request.responseText);
+ }
+ else {
+ _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText;
+ if (error)
+ error(path, "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText);
+ }
+ _this.toLoad--;
+ _this.loaded++;
+ }
+ };
+ request.open("GET", path, true);
+ request.send();
+ };
+ AssetManager.prototype.loadTexture = function (path, success, error) {
+ var _this = this;
+ if (success === void 0) { success = null; }
+ if (error === void 0) { error = null; }
+ path = this.pathPrefix + path;
+ this.toLoad++;
+ var img = new Image();
+ img.crossOrigin = "anonymous";
+ img.onload = function (ev) {
+ var texture = _this.textureLoader(img);
+ _this.assets[path] = texture;
+ _this.toLoad--;
+ _this.loaded++;
+ if (success)
+ success(path, img);
+ };
+ img.onerror = function (ev) {
+ _this.errors[path] = "Couldn't load image " + path;
+ _this.toLoad--;
+ _this.loaded++;
+ if (error)
+ error(path, "Couldn't load image " + path);
+ };
+ img.src = path;
+ };
+ AssetManager.prototype.loadTextureData = function (path, data, success, error) {
+ var _this = this;
+ if (success === void 0) { success = null; }
+ if (error === void 0) { error = null; }
+ path = this.pathPrefix + path;
+ this.toLoad++;
+ var img = new Image();
+ img.onload = function (ev) {
+ var texture = _this.textureLoader(img);
+ _this.assets[path] = texture;
+ _this.toLoad--;
+ _this.loaded++;
+ if (success)
+ success(path, img);
+ };
+ img.onerror = function (ev) {
+ _this.errors[path] = "Couldn't load image " + path;
+ _this.toLoad--;
+ _this.loaded++;
+ if (error)
+ error(path, "Couldn't load image " + path);
+ };
+ img.src = data;
+ };
+ AssetManager.prototype.get = function (path) {
+ path = this.pathPrefix + path;
+ return this.assets[path];
+ };
+ AssetManager.prototype.remove = function (path) {
+ path = this.pathPrefix + path;
+ var asset = this.assets[path];
+ if (asset.dispose)
+ asset.dispose();
+ this.assets[path] = null;
+ };
+ AssetManager.prototype.removeAll = function () {
+ for (var key in this.assets) {
+ var asset = this.assets[key];
+ if (asset.dispose)
+ asset.dispose();
+ }
+ this.assets = {};
+ };
+ AssetManager.prototype.isLoadingComplete = function () {
+ return this.toLoad == 0;
+ };
+ AssetManager.prototype.getToLoad = function () {
+ return this.toLoad;
+ };
+ AssetManager.prototype.getLoaded = function () {
+ return this.loaded;
+ };
+ AssetManager.prototype.dispose = function () {
+ this.removeAll();
+ };
+ AssetManager.prototype.hasErrors = function () {
+ return Object.keys(this.errors).length > 0;
+ };
+ AssetManager.prototype.getErrors = function () {
+ return this.errors;
+ };
+ return AssetManager;
+ }());
+ spine.AssetManager = AssetManager;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var AtlasAttachmentLoader = (function () {
+ function AtlasAttachmentLoader(atlas) {
+ this.atlas = atlas;
+ }
+ AtlasAttachmentLoader.prototype.newRegionAttachment = function (skin, name, path) {
+ var region = this.atlas.findRegion(path);
+ if (region == null)
+ throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")");
+ region.renderObject = region;
+ var attachment = new spine.RegionAttachment(name);
+ attachment.setRegion(region);
+ return attachment;
+ };
+ AtlasAttachmentLoader.prototype.newMeshAttachment = function (skin, name, path) {
+ var region = this.atlas.findRegion(path);
+ if (region == null)
+ throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
+ region.renderObject = region;
+ var attachment = new spine.MeshAttachment(name);
+ attachment.region = region;
+ return attachment;
+ };
+ AtlasAttachmentLoader.prototype.newBoundingBoxAttachment = function (skin, name) {
+ return new spine.BoundingBoxAttachment(name);
+ };
+ AtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) {
+ return new spine.PathAttachment(name);
+ };
+ AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) {
+ return new spine.PointAttachment(name);
+ };
+ AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) {
+ return new spine.ClippingAttachment(name);
+ };
+ return AtlasAttachmentLoader;
+ }());
+ spine.AtlasAttachmentLoader = AtlasAttachmentLoader;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var BlendMode;
+ (function (BlendMode) {
+ BlendMode[BlendMode["Normal"] = 0] = "Normal";
+ BlendMode[BlendMode["Additive"] = 1] = "Additive";
+ BlendMode[BlendMode["Multiply"] = 2] = "Multiply";
+ BlendMode[BlendMode["Screen"] = 3] = "Screen";
+ })(BlendMode = spine.BlendMode || (spine.BlendMode = {}));
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Bone = (function () {
+ function Bone(data, skeleton, parent) {
+ this.children = new Array();
+ this.x = 0;
+ this.y = 0;
+ this.rotation = 0;
+ this.scaleX = 0;
+ this.scaleY = 0;
+ this.shearX = 0;
+ this.shearY = 0;
+ this.ax = 0;
+ this.ay = 0;
+ this.arotation = 0;
+ this.ascaleX = 0;
+ this.ascaleY = 0;
+ this.ashearX = 0;
+ this.ashearY = 0;
+ this.appliedValid = false;
+ this.a = 0;
+ this.b = 0;
+ this.worldX = 0;
+ this.c = 0;
+ this.d = 0;
+ this.worldY = 0;
+ this.sorted = false;
+ if (data == null)
+ throw new Error("data cannot be null.");
+ if (skeleton == null)
+ throw new Error("skeleton cannot be null.");
+ this.data = data;
+ this.skeleton = skeleton;
+ this.parent = parent;
+ this.setToSetupPose();
+ }
+ Bone.prototype.update = function () {
+ this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);
+ };
+ Bone.prototype.updateWorldTransform = function () {
+ this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);
+ };
+ Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) {
+ this.ax = x;
+ this.ay = y;
+ this.arotation = rotation;
+ this.ascaleX = scaleX;
+ this.ascaleY = scaleY;
+ this.ashearX = shearX;
+ this.ashearY = shearY;
+ this.appliedValid = true;
+ var parent = this.parent;
+ if (parent == null) {
+ var rotationY = rotation + 90 + shearY;
+ var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX;
+ var lb = spine.MathUtils.cosDeg(rotationY) * scaleY;
+ var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX;
+ var ld = spine.MathUtils.sinDeg(rotationY) * scaleY;
+ var skeleton = this.skeleton;
+ if (skeleton.flipX) {
+ x = -x;
+ la = -la;
+ lb = -lb;
+ }
+ if (skeleton.flipY) {
+ y = -y;
+ lc = -lc;
+ ld = -ld;
+ }
+ this.a = la;
+ this.b = lb;
+ this.c = lc;
+ this.d = ld;
+ this.worldX = x + skeleton.x;
+ this.worldY = y + skeleton.y;
+ return;
+ }
+ var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
+ this.worldX = pa * x + pb * y + parent.worldX;
+ this.worldY = pc * x + pd * y + parent.worldY;
+ switch (this.data.transformMode) {
+ case spine.TransformMode.Normal: {
+ var rotationY = rotation + 90 + shearY;
+ var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX;
+ var lb = spine.MathUtils.cosDeg(rotationY) * scaleY;
+ var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX;
+ var ld = spine.MathUtils.sinDeg(rotationY) * scaleY;
+ this.a = pa * la + pb * lc;
+ this.b = pa * lb + pb * ld;
+ this.c = pc * la + pd * lc;
+ this.d = pc * lb + pd * ld;
+ return;
+ }
+ case spine.TransformMode.OnlyTranslation: {
+ var rotationY = rotation + 90 + shearY;
+ this.a = spine.MathUtils.cosDeg(rotation + shearX) * scaleX;
+ this.b = spine.MathUtils.cosDeg(rotationY) * scaleY;
+ this.c = spine.MathUtils.sinDeg(rotation + shearX) * scaleX;
+ this.d = spine.MathUtils.sinDeg(rotationY) * scaleY;
+ break;
+ }
+ case spine.TransformMode.NoRotationOrReflection: {
+ var s = pa * pa + pc * pc;
+ var prx = 0;
+ if (s > 0.0001) {
+ s = Math.abs(pa * pd - pb * pc) / s;
+ pb = pc * s;
+ pd = pa * s;
+ prx = Math.atan2(pc, pa) * spine.MathUtils.radDeg;
+ }
+ else {
+ pa = 0;
+ pc = 0;
+ prx = 90 - Math.atan2(pd, pb) * spine.MathUtils.radDeg;
+ }
+ var rx = rotation + shearX - prx;
+ var ry = rotation + shearY - prx + 90;
+ var la = spine.MathUtils.cosDeg(rx) * scaleX;
+ var lb = spine.MathUtils.cosDeg(ry) * scaleY;
+ var lc = spine.MathUtils.sinDeg(rx) * scaleX;
+ var ld = spine.MathUtils.sinDeg(ry) * scaleY;
+ this.a = pa * la - pb * lc;
+ this.b = pa * lb - pb * ld;
+ this.c = pc * la + pd * lc;
+ this.d = pc * lb + pd * ld;
+ break;
+ }
+ case spine.TransformMode.NoScale:
+ case spine.TransformMode.NoScaleOrReflection: {
+ var cos = spine.MathUtils.cosDeg(rotation);
+ var sin = spine.MathUtils.sinDeg(rotation);
+ var za = pa * cos + pb * sin;
+ var zc = pc * cos + pd * sin;
+ var s = Math.sqrt(za * za + zc * zc);
+ if (s > 0.00001)
+ s = 1 / s;
+ za *= s;
+ zc *= s;
+ s = Math.sqrt(za * za + zc * zc);
+ var r = Math.PI / 2 + Math.atan2(zc, za);
+ var zb = Math.cos(r) * s;
+ var zd = Math.sin(r) * s;
+ var la = spine.MathUtils.cosDeg(shearX) * scaleX;
+ var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY;
+ var lc = spine.MathUtils.sinDeg(shearX) * scaleX;
+ var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY;
+ if (this.data.transformMode != spine.TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) {
+ zb = -zb;
+ zd = -zd;
+ }
+ this.a = za * la + zb * lc;
+ this.b = za * lb + zb * ld;
+ this.c = zc * la + zd * lc;
+ this.d = zc * lb + zd * ld;
+ return;
+ }
+ }
+ if (this.skeleton.flipX) {
+ this.a = -this.a;
+ this.b = -this.b;
+ }
+ if (this.skeleton.flipY) {
+ this.c = -this.c;
+ this.d = -this.d;
+ }
+ };
+ Bone.prototype.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;
+ this.shearX = data.shearX;
+ this.shearY = data.shearY;
+ };
+ Bone.prototype.getWorldRotationX = function () {
+ return Math.atan2(this.c, this.a) * spine.MathUtils.radDeg;
+ };
+ Bone.prototype.getWorldRotationY = function () {
+ return Math.atan2(this.d, this.b) * spine.MathUtils.radDeg;
+ };
+ Bone.prototype.getWorldScaleX = function () {
+ return Math.sqrt(this.a * this.a + this.c * this.c);
+ };
+ Bone.prototype.getWorldScaleY = function () {
+ return Math.sqrt(this.b * this.b + this.d * this.d);
+ };
+ Bone.prototype.updateAppliedTransform = function () {
+ this.appliedValid = true;
+ var parent = this.parent;
+ if (parent == null) {
+ this.ax = this.worldX;
+ this.ay = this.worldY;
+ this.arotation = Math.atan2(this.c, this.a) * spine.MathUtils.radDeg;
+ this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c);
+ this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d);
+ this.ashearX = 0;
+ this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * spine.MathUtils.radDeg;
+ return;
+ }
+ var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
+ var pid = 1 / (pa * pd - pb * pc);
+ var dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY;
+ this.ax = (dx * pd * pid - dy * pb * pid);
+ this.ay = (dy * pa * pid - dx * pc * pid);
+ var ia = pid * pd;
+ var id = pid * pa;
+ var ib = pid * pb;
+ var ic = pid * pc;
+ var ra = ia * this.a - ib * this.c;
+ var rb = ia * this.b - ib * this.d;
+ var rc = id * this.c - ic * this.a;
+ var rd = id * this.d - ic * this.b;
+ this.ashearX = 0;
+ this.ascaleX = Math.sqrt(ra * ra + rc * rc);
+ if (this.ascaleX > 0.0001) {
+ var det = ra * rd - rb * rc;
+ this.ascaleY = det / this.ascaleX;
+ this.ashearY = Math.atan2(ra * rb + rc * rd, det) * spine.MathUtils.radDeg;
+ this.arotation = Math.atan2(rc, ra) * spine.MathUtils.radDeg;
+ }
+ else {
+ this.ascaleX = 0;
+ this.ascaleY = Math.sqrt(rb * rb + rd * rd);
+ this.ashearY = 0;
+ this.arotation = 90 - Math.atan2(rd, rb) * spine.MathUtils.radDeg;
+ }
+ };
+ Bone.prototype.worldToLocal = function (world) {
+ var a = this.a, b = this.b, c = this.c, d = this.d;
+ var invDet = 1 / (a * d - b * c);
+ var x = world.x - this.worldX, y = world.y - this.worldY;
+ world.x = (x * d * invDet - y * b * invDet);
+ world.y = (y * a * invDet - x * c * invDet);
+ return world;
+ };
+ Bone.prototype.localToWorld = function (local) {
+ var x = local.x, y = local.y;
+ local.x = x * this.a + y * this.b + this.worldX;
+ local.y = x * this.c + y * this.d + this.worldY;
+ return local;
+ };
+ Bone.prototype.worldToLocalRotation = function (worldRotation) {
+ var sin = spine.MathUtils.sinDeg(worldRotation), cos = spine.MathUtils.cosDeg(worldRotation);
+ return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * spine.MathUtils.radDeg;
+ };
+ Bone.prototype.localToWorldRotation = function (localRotation) {
+ var sin = spine.MathUtils.sinDeg(localRotation), cos = spine.MathUtils.cosDeg(localRotation);
+ return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * spine.MathUtils.radDeg;
+ };
+ Bone.prototype.rotateWorld = function (degrees) {
+ var a = this.a, b = this.b, c = this.c, d = this.d;
+ var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees);
+ this.a = cos * a - sin * c;
+ this.b = cos * b - sin * d;
+ this.c = sin * a + cos * c;
+ this.d = sin * b + cos * d;
+ this.appliedValid = false;
+ };
+ return Bone;
+ }());
+ spine.Bone = Bone;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var BoneData = (function () {
+ function BoneData(index, name, parent) {
+ this.x = 0;
+ this.y = 0;
+ this.rotation = 0;
+ this.scaleX = 1;
+ this.scaleY = 1;
+ this.shearX = 0;
+ this.shearY = 0;
+ this.transformMode = TransformMode.Normal;
+ if (index < 0)
+ throw new Error("index must be >= 0.");
+ if (name == null)
+ throw new Error("name cannot be null.");
+ this.index = index;
+ this.name = name;
+ this.parent = parent;
+ }
+ return BoneData;
+ }());
+ spine.BoneData = BoneData;
+ var TransformMode;
+ (function (TransformMode) {
+ TransformMode[TransformMode["Normal"] = 0] = "Normal";
+ TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation";
+ TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection";
+ TransformMode[TransformMode["NoScale"] = 3] = "NoScale";
+ TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection";
+ })(TransformMode = spine.TransformMode || (spine.TransformMode = {}));
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Event = (function () {
+ function Event(time, data) {
+ if (data == null)
+ throw new Error("data cannot be null.");
+ this.time = time;
+ this.data = data;
+ }
+ return Event;
+ }());
+ spine.Event = Event;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var EventData = (function () {
+ function EventData(name) {
+ this.name = name;
+ }
+ return EventData;
+ }());
+ spine.EventData = EventData;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var IkConstraint = (function () {
+ function IkConstraint(data, skeleton) {
+ this.mix = 1;
+ this.bendDirection = 0;
+ if (data == null)
+ throw new Error("data cannot be null.");
+ if (skeleton == null)
+ throw new Error("skeleton cannot be null.");
+ this.data = data;
+ this.mix = data.mix;
+ this.bendDirection = data.bendDirection;
+ this.bones = new Array();
+ for (var i = 0; i < data.bones.length; i++)
+ this.bones.push(skeleton.findBone(data.bones[i].name));
+ this.target = skeleton.findBone(data.target.name);
+ }
+ IkConstraint.prototype.getOrder = function () {
+ return this.data.order;
+ };
+ IkConstraint.prototype.apply = function () {
+ this.update();
+ };
+ IkConstraint.prototype.update = function () {
+ var target = this.target;
+ var bones = this.bones;
+ switch (bones.length) {
+ case 1:
+ this.apply1(bones[0], target.worldX, target.worldY, this.mix);
+ break;
+ case 2:
+ this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix);
+ break;
+ }
+ };
+ IkConstraint.prototype.apply1 = function (bone, targetX, targetY, alpha) {
+ if (!bone.appliedValid)
+ bone.updateAppliedTransform();
+ var p = bone.parent;
+ var id = 1 / (p.a * p.d - p.b * p.c);
+ var x = targetX - p.worldX, y = targetY - p.worldY;
+ var tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay;
+ var rotationIK = Math.atan2(ty, tx) * spine.MathUtils.radDeg - bone.ashearX - bone.arotation;
+ if (bone.ascaleX < 0)
+ rotationIK += 180;
+ if (rotationIK > 180)
+ rotationIK -= 360;
+ else if (rotationIK < -180)
+ rotationIK += 360;
+ bone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY);
+ };
+ IkConstraint.prototype.apply2 = function (parent, child, targetX, targetY, bendDir, alpha) {
+ if (alpha == 0) {
+ child.updateWorldTransform();
+ return;
+ }
+ if (!parent.appliedValid)
+ parent.updateAppliedTransform();
+ if (!child.appliedValid)
+ child.updateAppliedTransform();
+ var px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX;
+ var os1 = 0, os2 = 0, s2 = 0;
+ if (psx < 0) {
+ psx = -psx;
+ os1 = 180;
+ s2 = -1;
+ }
+ else {
+ os1 = 0;
+ s2 = 1;
+ }
+ if (psy < 0) {
+ psy = -psy;
+ s2 = -s2;
+ }
+ if (csx < 0) {
+ csx = -csx;
+ os2 = 180;
+ }
+ else
+ os2 = 0;
+ var cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d;
+ var u = Math.abs(psx - psy) <= 0.0001;
+ if (!u) {
+ cy = 0;
+ cwx = a * cx + parent.worldX;
+ cwy = c * cx + parent.worldY;
+ }
+ else {
+ cy = child.ay;
+ cwx = a * cx + b * cy + parent.worldX;
+ cwy = c * cx + d * cy + parent.worldY;
+ }
+ var pp = parent.parent;
+ a = pp.a;
+ b = pp.b;
+ c = pp.c;
+ d = pp.d;
+ var id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY;
+ var tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;
+ x = cwx - pp.worldX;
+ y = cwy - pp.worldY;
+ var dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;
+ var l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1 = 0, a2 = 0;
+ outer: if (u) {
+ l2 *= psx;
+ var cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
+ if (cos < -1)
+ cos = -1;
+ else if (cos > 1)
+ cos = 1;
+ a2 = Math.acos(cos) * bendDir;
+ a = l1 + l2 * cos;
+ b = l2 * Math.sin(a2);
+ a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b);
+ }
+ else {
+ a = psx * l2;
+ b = psy * l2;
+ var aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = Math.atan2(ty, tx);
+ c = bb * l1 * l1 + aa * dd - aa * bb;
+ var c1 = -2 * bb * l1, c2 = bb - aa;
+ d = c1 * c1 - 4 * c2 * c;
+ if (d >= 0) {
+ var q = Math.sqrt(d);
+ if (c1 < 0)
+ q = -q;
+ q = -(c1 + q) / 2;
+ var r0 = q / c2, r1 = c / q;
+ var r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
+ if (r * r <= dd) {
+ y = Math.sqrt(dd - r * r) * bendDir;
+ a1 = ta - Math.atan2(y, r);
+ a2 = Math.atan2(y / psy, (r - l1) / psx);
+ break outer;
+ }
+ }
+ var minAngle = spine.MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0;
+ var maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;
+ c = -a * l1 / (aa - bb);
+ if (c >= -1 && c <= 1) {
+ c = Math.acos(c);
+ x = a * Math.cos(c) + l1;
+ y = b * Math.sin(c);
+ d = x * x + y * y;
+ if (d < minDist) {
+ minAngle = c;
+ minDist = d;
+ minX = x;
+ minY = y;
+ }
+ if (d > maxDist) {
+ maxAngle = c;
+ maxDist = d;
+ maxX = x;
+ maxY = y;
+ }
+ }
+ if (dd <= (minDist + maxDist) / 2) {
+ a1 = ta - Math.atan2(minY * bendDir, minX);
+ a2 = minAngle * bendDir;
+ }
+ else {
+ a1 = ta - Math.atan2(maxY * bendDir, maxX);
+ a2 = maxAngle * bendDir;
+ }
+ }
+ var os = Math.atan2(cy, cx) * s2;
+ var rotation = parent.arotation;
+ a1 = (a1 - os) * spine.MathUtils.radDeg + os1 - rotation;
+ if (a1 > 180)
+ a1 -= 360;
+ else if (a1 < -180)
+ a1 += 360;
+ parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.ascaleX, parent.ascaleY, 0, 0);
+ rotation = child.arotation;
+ a2 = ((a2 + os) * spine.MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation;
+ if (a2 > 180)
+ a2 -= 360;
+ else if (a2 < -180)
+ a2 += 360;
+ child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
+ };
+ return IkConstraint;
+ }());
+ spine.IkConstraint = IkConstraint;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var IkConstraintData = (function () {
+ function IkConstraintData(name) {
+ this.order = 0;
+ this.bones = new Array();
+ this.bendDirection = 1;
+ this.mix = 1;
+ this.name = name;
+ }
+ return IkConstraintData;
+ }());
+ spine.IkConstraintData = IkConstraintData;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var PathConstraint = (function () {
+ function PathConstraint(data, skeleton) {
+ this.position = 0;
+ this.spacing = 0;
+ this.rotateMix = 0;
+ this.translateMix = 0;
+ this.spaces = new Array();
+ this.positions = new Array();
+ this.world = new Array();
+ this.curves = new Array();
+ this.lengths = new Array();
+ this.segments = new Array();
+ if (data == null)
+ throw new Error("data cannot be null.");
+ if (skeleton == null)
+ throw new Error("skeleton cannot be null.");
+ this.data = data;
+ this.bones = new Array();
+ for (var i = 0, n = data.bones.length; i < n; i++)
+ this.bones.push(skeleton.findBone(data.bones[i].name));
+ this.target = skeleton.findSlot(data.target.name);
+ this.position = data.position;
+ this.spacing = data.spacing;
+ this.rotateMix = data.rotateMix;
+ this.translateMix = data.translateMix;
+ }
+ PathConstraint.prototype.apply = function () {
+ this.update();
+ };
+ PathConstraint.prototype.update = function () {
+ var attachment = this.target.getAttachment();
+ if (!(attachment instanceof spine.PathAttachment))
+ return;
+ var rotateMix = this.rotateMix, translateMix = this.translateMix;
+ var translate = translateMix > 0, rotate = rotateMix > 0;
+ if (!translate && !rotate)
+ return;
+ var data = this.data;
+ var spacingMode = data.spacingMode;
+ var lengthSpacing = spacingMode == spine.SpacingMode.Length;
+ var rotateMode = data.rotateMode;
+ var tangents = rotateMode == spine.RotateMode.Tangent, scale = rotateMode == spine.RotateMode.ChainScale;
+ var boneCount = this.bones.length, spacesCount = tangents ? boneCount : boneCount + 1;
+ var bones = this.bones;
+ var spaces = spine.Utils.setArraySize(this.spaces, spacesCount), lengths = null;
+ var spacing = this.spacing;
+ if (scale || lengthSpacing) {
+ if (scale)
+ lengths = spine.Utils.setArraySize(this.lengths, boneCount);
+ for (var i = 0, n = spacesCount - 1; i < n;) {
+ var bone = bones[i];
+ var setupLength = bone.data.length;
+ if (setupLength == 0)
+ setupLength = 0.0000001;
+ var x = setupLength * bone.a, y = setupLength * bone.c;
+ var length_1 = Math.sqrt(x * x + y * y);
+ if (scale)
+ lengths[i] = length_1;
+ spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length_1 / setupLength;
+ }
+ }
+ else {
+ for (var i = 1; i < spacesCount; i++)
+ spaces[i] = spacing;
+ }
+ var positions = this.computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == spine.PositionMode.Percent, spacingMode == spine.SpacingMode.Percent);
+ var boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;
+ var tip = false;
+ if (offsetRotation == 0)
+ tip = rotateMode == spine.RotateMode.Chain;
+ else {
+ tip = false;
+ var p = this.target.bone;
+ offsetRotation *= p.a * p.d - p.b * p.c > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad;
+ }
+ for (var i = 0, p = 3; i < boneCount; i++, p += 3) {
+ var bone = bones[i];
+ bone.worldX += (boneX - bone.worldX) * translateMix;
+ bone.worldY += (boneY - bone.worldY) * translateMix;
+ var x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
+ if (scale) {
+ var length_2 = lengths[i];
+ if (length_2 != 0) {
+ var s = (Math.sqrt(dx * dx + dy * dy) / length_2 - 1) * rotateMix + 1;
+ bone.a *= s;
+ bone.c *= s;
+ }
+ }
+ boneX = x;
+ boneY = y;
+ if (rotate) {
+ var a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0;
+ if (tangents)
+ r = positions[p - 1];
+ else if (spaces[i + 1] == 0)
+ r = positions[p + 2];
+ else
+ r = Math.atan2(dy, dx);
+ r -= Math.atan2(c, a);
+ if (tip) {
+ cos = Math.cos(r);
+ sin = Math.sin(r);
+ var length_3 = bone.data.length;
+ boneX += (length_3 * (cos * a - sin * c) - dx) * rotateMix;
+ boneY += (length_3 * (sin * a + cos * c) - dy) * rotateMix;
+ }
+ else {
+ r += offsetRotation;
+ }
+ if (r > spine.MathUtils.PI)
+ r -= spine.MathUtils.PI2;
+ else if (r < -spine.MathUtils.PI)
+ r += spine.MathUtils.PI2;
+ r *= rotateMix;
+ cos = Math.cos(r);
+ sin = Math.sin(r);
+ bone.a = cos * a - sin * c;
+ bone.b = cos * b - sin * d;
+ bone.c = sin * a + cos * c;
+ bone.d = sin * b + cos * d;
+ }
+ bone.appliedValid = false;
+ }
+ };
+ PathConstraint.prototype.computeWorldPositions = function (path, spacesCount, tangents, percentPosition, percentSpacing) {
+ var target = this.target;
+ var position = this.position;
+ var spaces = this.spaces, out = spine.Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = null;
+ var closed = path.closed;
+ var verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE;
+ if (!path.constantSpeed) {
+ var lengths = path.lengths;
+ curveCount -= closed ? 1 : 2;
+ var pathLength_1 = lengths[curveCount];
+ if (percentPosition)
+ position *= pathLength_1;
+ if (percentSpacing) {
+ for (var i = 0; i < spacesCount; i++)
+ spaces[i] *= pathLength_1;
+ }
+ world = spine.Utils.setArraySize(this.world, 8);
+ for (var i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
+ var space = spaces[i];
+ position += space;
+ var p = position;
+ if (closed) {
+ p %= pathLength_1;
+ if (p < 0)
+ p += pathLength_1;
+ curve = 0;
+ }
+ else if (p < 0) {
+ if (prevCurve != PathConstraint.BEFORE) {
+ prevCurve = PathConstraint.BEFORE;
+ path.computeWorldVertices(target, 2, 4, world, 0, 2);
+ }
+ this.addBeforePosition(p, world, 0, out, o);
+ continue;
+ }
+ else if (p > pathLength_1) {
+ if (prevCurve != PathConstraint.AFTER) {
+ prevCurve = PathConstraint.AFTER;
+ path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);
+ }
+ this.addAfterPosition(p - pathLength_1, world, 0, out, o);
+ continue;
+ }
+ for (;; curve++) {
+ var length_4 = lengths[curve];
+ if (p > length_4)
+ continue;
+ if (curve == 0)
+ p /= length_4;
+ else {
+ var prev = lengths[curve - 1];
+ p = (p - prev) / (length_4 - prev);
+ }
+ break;
+ }
+ if (curve != prevCurve) {
+ prevCurve = curve;
+ if (closed && curve == curveCount) {
+ path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);
+ path.computeWorldVertices(target, 0, 4, world, 4, 2);
+ }
+ else
+ path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);
+ }
+ this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0));
+ }
+ return out;
+ }
+ if (closed) {
+ verticesLength += 2;
+ world = spine.Utils.setArraySize(this.world, verticesLength);
+ path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);
+ path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);
+ world[verticesLength - 2] = world[0];
+ world[verticesLength - 1] = world[1];
+ }
+ else {
+ curveCount--;
+ verticesLength -= 4;
+ world = spine.Utils.setArraySize(this.world, verticesLength);
+ path.computeWorldVertices(target, 2, verticesLength, world, 0, 2);
+ }
+ var curves = spine.Utils.setArraySize(this.curves, curveCount);
+ var pathLength = 0;
+ var x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
+ var tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0;
+ for (var i = 0, w = 2; i < curveCount; i++, w += 6) {
+ cx1 = world[w];
+ cy1 = world[w + 1];
+ cx2 = world[w + 2];
+ cy2 = world[w + 3];
+ x2 = world[w + 4];
+ y2 = world[w + 5];
+ tmpx = (x1 - cx1 * 2 + cx2) * 0.1875;
+ tmpy = (y1 - cy1 * 2 + cy2) * 0.1875;
+ dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;
+ dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;
+ ddfx = tmpx * 2 + dddfx;
+ ddfy = tmpy * 2 + dddfy;
+ dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;
+ dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;
+ pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+ dfx += ddfx;
+ dfy += ddfy;
+ ddfx += dddfx;
+ ddfy += dddfy;
+ pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+ dfx += ddfx;
+ dfy += ddfy;
+ pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+ dfx += ddfx + dddfx;
+ dfy += ddfy + dddfy;
+ pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+ curves[i] = pathLength;
+ x1 = x2;
+ y1 = y2;
+ }
+ if (percentPosition)
+ position *= pathLength;
+ if (percentSpacing) {
+ for (var i = 0; i < spacesCount; i++)
+ spaces[i] *= pathLength;
+ }
+ var segments = this.segments;
+ var curveLength = 0;
+ for (var i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
+ var space = spaces[i];
+ position += space;
+ var p = position;
+ if (closed) {
+ p %= pathLength;
+ if (p < 0)
+ p += pathLength;
+ curve = 0;
+ }
+ else if (p < 0) {
+ this.addBeforePosition(p, world, 0, out, o);
+ continue;
+ }
+ else if (p > pathLength) {
+ this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
+ continue;
+ }
+ for (;; curve++) {
+ var length_5 = curves[curve];
+ if (p > length_5)
+ continue;
+ if (curve == 0)
+ p /= length_5;
+ else {
+ var prev = curves[curve - 1];
+ p = (p - prev) / (length_5 - prev);
+ }
+ break;
+ }
+ if (curve != prevCurve) {
+ prevCurve = curve;
+ var ii = curve * 6;
+ x1 = world[ii];
+ y1 = world[ii + 1];
+ cx1 = world[ii + 2];
+ cy1 = world[ii + 3];
+ cx2 = world[ii + 4];
+ cy2 = world[ii + 5];
+ x2 = world[ii + 6];
+ y2 = world[ii + 7];
+ tmpx = (x1 - cx1 * 2 + cx2) * 0.03;
+ tmpy = (y1 - cy1 * 2 + cy2) * 0.03;
+ dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006;
+ dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006;
+ ddfx = tmpx * 2 + dddfx;
+ ddfy = tmpy * 2 + dddfy;
+ dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;
+ dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;
+ curveLength = Math.sqrt(dfx * dfx + dfy * dfy);
+ segments[0] = curveLength;
+ for (ii = 1; ii < 8; ii++) {
+ dfx += ddfx;
+ dfy += ddfy;
+ ddfx += dddfx;
+ ddfy += dddfy;
+ curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
+ segments[ii] = curveLength;
+ }
+ dfx += ddfx;
+ dfy += ddfy;
+ curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
+ segments[8] = curveLength;
+ dfx += ddfx + dddfx;
+ dfy += ddfy + dddfy;
+ curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
+ segments[9] = curveLength;
+ segment = 0;
+ }
+ p *= curveLength;
+ for (;; segment++) {
+ var length_6 = segments[segment];
+ if (p > length_6)
+ continue;
+ if (segment == 0)
+ p /= length_6;
+ else {
+ var prev = segments[segment - 1];
+ p = segment + (p - prev) / (length_6 - prev);
+ }
+ break;
+ }
+ this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0));
+ }
+ return out;
+ };
+ PathConstraint.prototype.addBeforePosition = function (p, temp, i, out, o) {
+ var x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx);
+ out[o] = x1 + p * Math.cos(r);
+ out[o + 1] = y1 + p * Math.sin(r);
+ out[o + 2] = r;
+ };
+ PathConstraint.prototype.addAfterPosition = function (p, temp, i, out, o) {
+ var x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx);
+ out[o] = x1 + p * Math.cos(r);
+ out[o + 1] = y1 + p * Math.sin(r);
+ out[o + 2] = r;
+ };
+ PathConstraint.prototype.addCurvePosition = function (p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) {
+ if (p == 0 || isNaN(p))
+ p = 0.0001;
+ var tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u;
+ var ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p;
+ var x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;
+ out[o] = x;
+ out[o + 1] = y;
+ if (tangents)
+ out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
+ };
+ PathConstraint.prototype.getOrder = function () {
+ return this.data.order;
+ };
+ return PathConstraint;
+ }());
+ PathConstraint.NONE = -1;
+ PathConstraint.BEFORE = -2;
+ PathConstraint.AFTER = -3;
+ spine.PathConstraint = PathConstraint;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var PathConstraintData = (function () {
+ function PathConstraintData(name) {
+ this.order = 0;
+ this.bones = new Array();
+ this.name = name;
+ }
+ return PathConstraintData;
+ }());
+ spine.PathConstraintData = PathConstraintData;
+ var PositionMode;
+ (function (PositionMode) {
+ PositionMode[PositionMode["Fixed"] = 0] = "Fixed";
+ PositionMode[PositionMode["Percent"] = 1] = "Percent";
+ })(PositionMode = spine.PositionMode || (spine.PositionMode = {}));
+ var SpacingMode;
+ (function (SpacingMode) {
+ SpacingMode[SpacingMode["Length"] = 0] = "Length";
+ SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed";
+ SpacingMode[SpacingMode["Percent"] = 2] = "Percent";
+ })(SpacingMode = spine.SpacingMode || (spine.SpacingMode = {}));
+ var RotateMode;
+ (function (RotateMode) {
+ RotateMode[RotateMode["Tangent"] = 0] = "Tangent";
+ RotateMode[RotateMode["Chain"] = 1] = "Chain";
+ RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale";
+ })(RotateMode = spine.RotateMode || (spine.RotateMode = {}));
+})(spine || (spine = {}));
+(function () {
+ if (!Math.fround) {
+ Math.fround = (function (array) {
+ return function (x) {
+ return array[0] = x, array[0];
+ };
+ })(new Float32Array(1));
+ }
+})();
+var spine;
+(function (spine) {
+ var Assets = (function () {
+ function Assets(clientId) {
+ this.toLoad = new Array();
+ this.assets = {};
+ this.clientId = clientId;
+ }
+ Assets.prototype.loaded = function () {
+ var i = 0;
+ for (var v in this.assets)
+ i++;
+ return i;
+ };
+ return Assets;
+ }());
+ var SharedAssetManager = (function () {
+ function SharedAssetManager(pathPrefix) {
+ if (pathPrefix === void 0) { pathPrefix = ""; }
+ this.clientAssets = {};
+ this.queuedAssets = {};
+ this.rawAssets = {};
+ this.errors = {};
+ this.pathPrefix = pathPrefix;
+ }
+ SharedAssetManager.prototype.queueAsset = function (clientId, textureLoader, path) {
+ var clientAssets = this.clientAssets[clientId];
+ if (clientAssets === null || clientAssets === undefined) {
+ clientAssets = new Assets(clientId);
+ this.clientAssets[clientId] = clientAssets;
+ }
+ if (textureLoader !== null)
+ clientAssets.textureLoader = textureLoader;
+ clientAssets.toLoad.push(path);
+ if (this.queuedAssets[path] === path) {
+ return false;
+ }
+ else {
+ this.queuedAssets[path] = path;
+ return true;
+ }
+ };
+ SharedAssetManager.prototype.loadText = function (clientId, path) {
+ var _this = this;
+ path = this.pathPrefix + path;
+ if (!this.queueAsset(clientId, null, path))
+ return;
+ var request = new XMLHttpRequest();
+ request.onreadystatechange = function () {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ if (request.status >= 200 && request.status < 300) {
+ _this.rawAssets[path] = request.responseText;
+ }
+ else {
+ _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText;
+ }
+ }
+ };
+ request.open("GET", path, true);
+ request.send();
+ };
+ SharedAssetManager.prototype.loadJson = function (clientId, path) {
+ var _this = this;
+ path = this.pathPrefix + path;
+ if (!this.queueAsset(clientId, null, path))
+ return;
+ var request = new XMLHttpRequest();
+ request.onreadystatechange = function () {
+ if (request.readyState == XMLHttpRequest.DONE) {
+ if (request.status >= 200 && request.status < 300) {
+ _this.rawAssets[path] = JSON.parse(request.responseText);
+ }
+ else {
+ _this.errors[path] = "Couldn't load text " + path + ": status " + request.status + ", " + request.responseText;
+ }
+ }
+ };
+ request.open("GET", path, true);
+ request.send();
+ };
+ SharedAssetManager.prototype.loadTexture = function (clientId, textureLoader, path) {
+ var _this = this;
+ path = this.pathPrefix + path;
+ if (!this.queueAsset(clientId, textureLoader, path))
+ return;
+ var img = new Image();
+ img.src = path;
+ img.crossOrigin = "anonymous";
+ img.onload = function (ev) {
+ _this.rawAssets[path] = img;
+ };
+ img.onerror = function (ev) {
+ _this.errors[path] = "Couldn't load image " + path;
+ };
+ };
+ SharedAssetManager.prototype.get = function (clientId, path) {
+ path = this.pathPrefix + path;
+ var clientAssets = this.clientAssets[clientId];
+ if (clientAssets === null || clientAssets === undefined)
+ return true;
+ return clientAssets.assets[path];
+ };
+ SharedAssetManager.prototype.updateClientAssets = function (clientAssets) {
+ for (var i = 0; i < clientAssets.toLoad.length; i++) {
+ var path = clientAssets.toLoad[i];
+ var asset = clientAssets.assets[path];
+ if (asset === null || asset === undefined) {
+ var rawAsset = this.rawAssets[path];
+ if (rawAsset === null || rawAsset === undefined)
+ continue;
+ if (rawAsset instanceof HTMLImageElement) {
+ clientAssets.assets[path] = clientAssets.textureLoader(rawAsset);
+ }
+ else {
+ clientAssets.assets[path] = rawAsset;
+ }
+ }
+ }
+ };
+ SharedAssetManager.prototype.isLoadingComplete = function (clientId) {
+ var clientAssets = this.clientAssets[clientId];
+ if (clientAssets === null || clientAssets === undefined)
+ return true;
+ this.updateClientAssets(clientAssets);
+ return clientAssets.toLoad.length == clientAssets.loaded();
+ };
+ SharedAssetManager.prototype.dispose = function () {
+ };
+ SharedAssetManager.prototype.hasErrors = function () {
+ return Object.keys(this.errors).length > 0;
+ };
+ SharedAssetManager.prototype.getErrors = function () {
+ return this.errors;
+ };
+ return SharedAssetManager;
+ }());
+ spine.SharedAssetManager = SharedAssetManager;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Skeleton = (function () {
+ function Skeleton(data) {
+ this._updateCache = new Array();
+ this.updateCacheReset = new Array();
+ this.time = 0;
+ this.flipX = false;
+ this.flipY = false;
+ this.x = 0;
+ this.y = 0;
+ if (data == null)
+ throw new Error("data cannot be null.");
+ this.data = data;
+ this.bones = new Array();
+ for (var i = 0; i < data.bones.length; i++) {
+ var boneData = data.bones[i];
+ var bone = void 0;
+ if (boneData.parent == null)
+ bone = new spine.Bone(boneData, this, null);
+ else {
+ var parent_1 = this.bones[boneData.parent.index];
+ bone = new spine.Bone(boneData, this, parent_1);
+ parent_1.children.push(bone);
+ }
+ this.bones.push(bone);
+ }
+ this.slots = new Array();
+ this.drawOrder = new Array();
+ for (var i = 0; i < data.slots.length; i++) {
+ var slotData = data.slots[i];
+ var bone = this.bones[slotData.boneData.index];
+ var slot = new spine.Slot(slotData, bone);
+ this.slots.push(slot);
+ this.drawOrder.push(slot);
+ }
+ this.ikConstraints = new Array();
+ for (var i = 0; i < data.ikConstraints.length; i++) {
+ var ikConstraintData = data.ikConstraints[i];
+ this.ikConstraints.push(new spine.IkConstraint(ikConstraintData, this));
+ }
+ this.transformConstraints = new Array();
+ for (var i = 0; i < data.transformConstraints.length; i++) {
+ var transformConstraintData = data.transformConstraints[i];
+ this.transformConstraints.push(new spine.TransformConstraint(transformConstraintData, this));
+ }
+ this.pathConstraints = new Array();
+ for (var i = 0; i < data.pathConstraints.length; i++) {
+ var pathConstraintData = data.pathConstraints[i];
+ this.pathConstraints.push(new spine.PathConstraint(pathConstraintData, this));
+ }
+ this.color = new spine.Color(1, 1, 1, 1);
+ this.updateCache();
+ }
+ Skeleton.prototype.updateCache = function () {
+ var updateCache = this._updateCache;
+ updateCache.length = 0;
+ this.updateCacheReset.length = 0;
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ bones[i].sorted = false;
+ var ikConstraints = this.ikConstraints;
+ var transformConstraints = this.transformConstraints;
+ var pathConstraints = this.pathConstraints;
+ var ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length;
+ var constraintCount = ikCount + transformCount + pathCount;
+ outer: for (var i = 0; i < constraintCount; i++) {
+ for (var ii = 0; ii < ikCount; ii++) {
+ var constraint = ikConstraints[ii];
+ if (constraint.data.order == i) {
+ this.sortIkConstraint(constraint);
+ continue outer;
+ }
+ }
+ for (var ii = 0; ii < transformCount; ii++) {
+ var constraint = transformConstraints[ii];
+ if (constraint.data.order == i) {
+ this.sortTransformConstraint(constraint);
+ continue outer;
+ }
+ }
+ for (var ii = 0; ii < pathCount; ii++) {
+ var constraint = pathConstraints[ii];
+ if (constraint.data.order == i) {
+ this.sortPathConstraint(constraint);
+ continue outer;
+ }
+ }
+ }
+ for (var i = 0, n = bones.length; i < n; i++)
+ this.sortBone(bones[i]);
+ };
+ Skeleton.prototype.sortIkConstraint = function (constraint) {
+ var target = constraint.target;
+ this.sortBone(target);
+ var constrained = constraint.bones;
+ var parent = constrained[0];
+ this.sortBone(parent);
+ if (constrained.length > 1) {
+ var child = constrained[constrained.length - 1];
+ if (!(this._updateCache.indexOf(child) > -1))
+ this.updateCacheReset.push(child);
+ }
+ this._updateCache.push(constraint);
+ this.sortReset(parent.children);
+ constrained[constrained.length - 1].sorted = true;
+ };
+ Skeleton.prototype.sortPathConstraint = function (constraint) {
+ var slot = constraint.target;
+ var slotIndex = slot.data.index;
+ var slotBone = slot.bone;
+ if (this.skin != null)
+ this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);
+ if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin)
+ this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone);
+ for (var i = 0, n = this.data.skins.length; i < n; i++)
+ this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone);
+ var attachment = slot.getAttachment();
+ if (attachment instanceof spine.PathAttachment)
+ this.sortPathConstraintAttachmentWith(attachment, slotBone);
+ var constrained = constraint.bones;
+ var boneCount = constrained.length;
+ for (var i = 0; i < boneCount; i++)
+ this.sortBone(constrained[i]);
+ this._updateCache.push(constraint);
+ for (var i = 0; i < boneCount; i++)
+ this.sortReset(constrained[i].children);
+ for (var i = 0; i < boneCount; i++)
+ constrained[i].sorted = true;
+ };
+ Skeleton.prototype.sortTransformConstraint = function (constraint) {
+ this.sortBone(constraint.target);
+ var constrained = constraint.bones;
+ var boneCount = constrained.length;
+ if (constraint.data.local) {
+ for (var i = 0; i < boneCount; i++) {
+ var child = constrained[i];
+ this.sortBone(child.parent);
+ if (!(this._updateCache.indexOf(child) > -1))
+ this.updateCacheReset.push(child);
+ }
+ }
+ else {
+ for (var i = 0; i < boneCount; i++) {
+ this.sortBone(constrained[i]);
+ }
+ }
+ this._updateCache.push(constraint);
+ for (var ii = 0; ii < boneCount; ii++)
+ this.sortReset(constrained[ii].children);
+ for (var ii = 0; ii < boneCount; ii++)
+ constrained[ii].sorted = true;
+ };
+ Skeleton.prototype.sortPathConstraintAttachment = function (skin, slotIndex, slotBone) {
+ var attachments = skin.attachments[slotIndex];
+ if (!attachments)
+ return;
+ for (var key in attachments) {
+ this.sortPathConstraintAttachmentWith(attachments[key], slotBone);
+ }
+ };
+ Skeleton.prototype.sortPathConstraintAttachmentWith = function (attachment, slotBone) {
+ if (!(attachment instanceof spine.PathAttachment))
+ return;
+ var pathBones = attachment.bones;
+ if (pathBones == null)
+ this.sortBone(slotBone);
+ else {
+ var bones = this.bones;
+ var i = 0;
+ while (i < pathBones.length) {
+ var boneCount = pathBones[i++];
+ for (var n = i + boneCount; i < n; i++) {
+ var boneIndex = pathBones[i];
+ this.sortBone(bones[boneIndex]);
+ }
+ }
+ }
+ };
+ Skeleton.prototype.sortBone = function (bone) {
+ if (bone.sorted)
+ return;
+ var parent = bone.parent;
+ if (parent != null)
+ this.sortBone(parent);
+ bone.sorted = true;
+ this._updateCache.push(bone);
+ };
+ Skeleton.prototype.sortReset = function (bones) {
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ if (bone.sorted)
+ this.sortReset(bone.children);
+ bone.sorted = false;
+ }
+ };
+ Skeleton.prototype.updateWorldTransform = function () {
+ var updateCacheReset = this.updateCacheReset;
+ for (var i = 0, n = updateCacheReset.length; i < n; i++) {
+ var bone = updateCacheReset[i];
+ bone.ax = bone.x;
+ bone.ay = bone.y;
+ bone.arotation = bone.rotation;
+ bone.ascaleX = bone.scaleX;
+ bone.ascaleY = bone.scaleY;
+ bone.ashearX = bone.shearX;
+ bone.ashearY = bone.shearY;
+ bone.appliedValid = true;
+ }
+ var updateCache = this._updateCache;
+ for (var i = 0, n = updateCache.length; i < n; i++)
+ updateCache[i].update();
+ };
+ Skeleton.prototype.setToSetupPose = function () {
+ this.setBonesToSetupPose();
+ this.setSlotsToSetupPose();
+ };
+ Skeleton.prototype.setBonesToSetupPose = function () {
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ bones[i].setToSetupPose();
+ var ikConstraints = this.ikConstraints;
+ for (var i = 0, n = ikConstraints.length; i < n; i++) {
+ var constraint = ikConstraints[i];
+ constraint.bendDirection = constraint.data.bendDirection;
+ constraint.mix = constraint.data.mix;
+ }
+ var transformConstraints = this.transformConstraints;
+ for (var i = 0, n = transformConstraints.length; i < n; i++) {
+ var constraint = transformConstraints[i];
+ var data = constraint.data;
+ constraint.rotateMix = data.rotateMix;
+ constraint.translateMix = data.translateMix;
+ constraint.scaleMix = data.scaleMix;
+ constraint.shearMix = data.shearMix;
+ }
+ var pathConstraints = this.pathConstraints;
+ for (var i = 0, n = pathConstraints.length; i < n; i++) {
+ var constraint = pathConstraints[i];
+ var data = constraint.data;
+ constraint.position = data.position;
+ constraint.spacing = data.spacing;
+ constraint.rotateMix = data.rotateMix;
+ constraint.translateMix = data.translateMix;
+ }
+ };
+ Skeleton.prototype.setSlotsToSetupPose = function () {
+ var slots = this.slots;
+ spine.Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length);
+ for (var i = 0, n = slots.length; i < n; i++)
+ slots[i].setToSetupPose();
+ };
+ Skeleton.prototype.getRootBone = function () {
+ if (this.bones.length == 0)
+ return null;
+ return this.bones[0];
+ };
+ Skeleton.prototype.findBone = function (boneName) {
+ if (boneName == null)
+ throw new Error("boneName cannot be null.");
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ if (bone.data.name == boneName)
+ return bone;
+ }
+ return null;
+ };
+ Skeleton.prototype.findBoneIndex = function (boneName) {
+ if (boneName == null)
+ throw new Error("boneName cannot be null.");
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ if (bones[i].data.name == boneName)
+ return i;
+ return -1;
+ };
+ Skeleton.prototype.findSlot = function (slotName) {
+ if (slotName == null)
+ throw new Error("slotName cannot be null.");
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++) {
+ var slot = slots[i];
+ if (slot.data.name == slotName)
+ return slot;
+ }
+ return null;
+ };
+ Skeleton.prototype.findSlotIndex = function (slotName) {
+ if (slotName == null)
+ throw new Error("slotName cannot be null.");
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++)
+ if (slots[i].data.name == slotName)
+ return i;
+ return -1;
+ };
+ Skeleton.prototype.setSkinByName = function (skinName) {
+ var skin = this.data.findSkin(skinName);
+ if (skin == null)
+ throw new Error("Skin not found: " + skinName);
+ this.setSkin(skin);
+ };
+ Skeleton.prototype.setSkin = function (newSkin) {
+ if (newSkin != null) {
+ if (this.skin != null)
+ newSkin.attachAll(this, this.skin);
+ else {
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++) {
+ var slot = slots[i];
+ var name_1 = slot.data.attachmentName;
+ if (name_1 != null) {
+ var attachment = newSkin.getAttachment(i, name_1);
+ if (attachment != null)
+ slot.setAttachment(attachment);
+ }
+ }
+ }
+ }
+ this.skin = newSkin;
+ };
+ Skeleton.prototype.getAttachmentByName = function (slotName, attachmentName) {
+ return this.getAttachment(this.data.findSlotIndex(slotName), attachmentName);
+ };
+ Skeleton.prototype.getAttachment = function (slotIndex, attachmentName) {
+ if (attachmentName == null)
+ throw new Error("attachmentName cannot be null.");
+ if (this.skin != null) {
+ var attachment = this.skin.getAttachment(slotIndex, attachmentName);
+ if (attachment != null)
+ return attachment;
+ }
+ if (this.data.defaultSkin != null)
+ return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);
+ return null;
+ };
+ Skeleton.prototype.setAttachment = function (slotName, attachmentName) {
+ if (slotName == null)
+ throw new Error("slotName cannot be null.");
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++) {
+ var slot = slots[i];
+ if (slot.data.name == slotName) {
+ var attachment = null;
+ if (attachmentName != null) {
+ attachment = this.getAttachment(i, attachmentName);
+ if (attachment == null)
+ throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName);
+ }
+ slot.setAttachment(attachment);
+ return;
+ }
+ }
+ throw new Error("Slot not found: " + slotName);
+ };
+ Skeleton.prototype.findIkConstraint = function (constraintName) {
+ if (constraintName == null)
+ throw new Error("constraintName cannot be null.");
+ var ikConstraints = this.ikConstraints;
+ for (var i = 0, n = ikConstraints.length; i < n; i++) {
+ var ikConstraint = ikConstraints[i];
+ if (ikConstraint.data.name == constraintName)
+ return ikConstraint;
+ }
+ return null;
+ };
+ Skeleton.prototype.findTransformConstraint = function (constraintName) {
+ if (constraintName == null)
+ throw new Error("constraintName cannot be null.");
+ var transformConstraints = this.transformConstraints;
+ for (var i = 0, n = transformConstraints.length; i < n; i++) {
+ var constraint = transformConstraints[i];
+ if (constraint.data.name == constraintName)
+ return constraint;
+ }
+ return null;
+ };
+ Skeleton.prototype.findPathConstraint = function (constraintName) {
+ if (constraintName == null)
+ throw new Error("constraintName cannot be null.");
+ var pathConstraints = this.pathConstraints;
+ for (var i = 0, n = pathConstraints.length; i < n; i++) {
+ var constraint = pathConstraints[i];
+ if (constraint.data.name == constraintName)
+ return constraint;
+ }
+ return null;
+ };
+ Skeleton.prototype.getBounds = function (offset, size, temp) {
+ if (offset == null)
+ throw new Error("offset cannot be null.");
+ if (size == null)
+ throw new Error("size cannot be null.");
+ var drawOrder = this.drawOrder;
+ var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
+ for (var i = 0, n = drawOrder.length; i < n; i++) {
+ var slot = drawOrder[i];
+ var verticesLength = 0;
+ var vertices = null;
+ var attachment = slot.getAttachment();
+ if (attachment instanceof spine.RegionAttachment) {
+ verticesLength = 8;
+ vertices = spine.Utils.setArraySize(temp, verticesLength, 0);
+ attachment.computeWorldVertices(slot.bone, vertices, 0, 2);
+ }
+ else if (attachment instanceof spine.MeshAttachment) {
+ var mesh = attachment;
+ verticesLength = mesh.worldVerticesLength;
+ vertices = spine.Utils.setArraySize(temp, verticesLength, 0);
+ mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
+ }
+ if (vertices != null) {
+ for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) {
+ var x = vertices[ii], y = vertices[ii + 1];
+ minX = Math.min(minX, x);
+ minY = Math.min(minY, y);
+ maxX = Math.max(maxX, x);
+ maxY = Math.max(maxY, y);
+ }
+ }
+ }
+ offset.set(minX, minY);
+ size.set(maxX - minX, maxY - minY);
+ };
+ Skeleton.prototype.update = function (delta) {
+ this.time += delta;
+ };
+ return Skeleton;
+ }());
+ spine.Skeleton = Skeleton;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var SkeletonBounds = (function () {
+ function SkeletonBounds() {
+ this.minX = 0;
+ this.minY = 0;
+ this.maxX = 0;
+ this.maxY = 0;
+ this.boundingBoxes = new Array();
+ this.polygons = new Array();
+ this.polygonPool = new spine.Pool(function () {
+ return spine.Utils.newFloatArray(16);
+ });
+ }
+ SkeletonBounds.prototype.update = function (skeleton, updateAabb) {
+ if (skeleton == null)
+ throw new Error("skeleton cannot be null.");
+ var boundingBoxes = this.boundingBoxes;
+ var polygons = this.polygons;
+ var polygonPool = this.polygonPool;
+ var slots = skeleton.slots;
+ var slotCount = slots.length;
+ boundingBoxes.length = 0;
+ polygonPool.freeAll(polygons);
+ polygons.length = 0;
+ for (var i = 0; i < slotCount; i++) {
+ var slot = slots[i];
+ var attachment = slot.getAttachment();
+ if (attachment instanceof spine.BoundingBoxAttachment) {
+ var boundingBox = attachment;
+ boundingBoxes.push(boundingBox);
+ var polygon = polygonPool.obtain();
+ if (polygon.length != boundingBox.worldVerticesLength) {
+ polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength);
+ }
+ polygons.push(polygon);
+ boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2);
+ }
+ }
+ if (updateAabb) {
+ this.aabbCompute();
+ }
+ else {
+ this.minX = Number.POSITIVE_INFINITY;
+ this.minY = Number.POSITIVE_INFINITY;
+ this.maxX = Number.NEGATIVE_INFINITY;
+ this.maxY = Number.NEGATIVE_INFINITY;
+ }
+ };
+ SkeletonBounds.prototype.aabbCompute = function () {
+ var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
+ var polygons = this.polygons;
+ for (var i = 0, n = polygons.length; i < n; i++) {
+ var polygon = polygons[i];
+ var vertices = polygon;
+ for (var ii = 0, nn = polygon.length; ii < nn; ii += 2) {
+ var x = vertices[ii];
+ var y = vertices[ii + 1];
+ minX = Math.min(minX, x);
+ minY = Math.min(minY, y);
+ maxX = Math.max(maxX, x);
+ maxY = Math.max(maxY, y);
+ }
+ }
+ this.minX = minX;
+ this.minY = minY;
+ this.maxX = maxX;
+ this.maxY = maxY;
+ };
+ SkeletonBounds.prototype.aabbContainsPoint = function (x, y) {
+ return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;
+ };
+ SkeletonBounds.prototype.aabbIntersectsSegment = function (x1, y1, x2, y2) {
+ var minX = this.minX;
+ var minY = this.minY;
+ var maxX = this.maxX;
+ var maxY = this.maxY;
+ if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))
+ return false;
+ var m = (y2 - y1) / (x2 - x1);
+ var y = m * (minX - x1) + y1;
+ if (y > minY && y < maxY)
+ return true;
+ y = m * (maxX - x1) + y1;
+ if (y > minY && y < maxY)
+ return true;
+ var x = (minY - y1) / m + x1;
+ if (x > minX && x < maxX)
+ return true;
+ x = (maxY - y1) / m + x1;
+ if (x > minX && x < maxX)
+ return true;
+ return false;
+ };
+ SkeletonBounds.prototype.aabbIntersectsSkeleton = function (bounds) {
+ return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY;
+ };
+ SkeletonBounds.prototype.containsPoint = function (x, y) {
+ var polygons = this.polygons;
+ for (var i = 0, n = polygons.length; i < n; i++)
+ if (this.containsPointPolygon(polygons[i], x, y))
+ return this.boundingBoxes[i];
+ return null;
+ };
+ SkeletonBounds.prototype.containsPointPolygon = function (polygon, x, y) {
+ var vertices = polygon;
+ var nn = polygon.length;
+ var prevIndex = nn - 2;
+ var inside = false;
+ for (var ii = 0; ii < nn; ii += 2) {
+ var vertexY = vertices[ii + 1];
+ var prevY = vertices[prevIndex + 1];
+ if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
+ var vertexX = vertices[ii];
+ if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x)
+ inside = !inside;
+ }
+ prevIndex = ii;
+ }
+ return inside;
+ };
+ SkeletonBounds.prototype.intersectsSegment = function (x1, y1, x2, y2) {
+ var polygons = this.polygons;
+ for (var i = 0, n = polygons.length; i < n; i++)
+ if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2))
+ return this.boundingBoxes[i];
+ return null;
+ };
+ SkeletonBounds.prototype.intersectsSegmentPolygon = function (polygon, x1, y1, x2, y2) {
+ var vertices = polygon;
+ var nn = polygon.length;
+ var width12 = x1 - x2, height12 = y1 - y2;
+ var det1 = x1 * y2 - y1 * x2;
+ var x3 = vertices[nn - 2], y3 = vertices[nn - 1];
+ for (var ii = 0; ii < nn; ii += 2) {
+ var x4 = vertices[ii], y4 = vertices[ii + 1];
+ var det2 = x3 * y4 - y3 * x4;
+ var width34 = x3 - x4, height34 = y3 - y4;
+ var det3 = width12 * height34 - height12 * width34;
+ var x = (det1 * width34 - width12 * det2) / det3;
+ if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
+ var y = (det1 * height34 - height12 * det2) / det3;
+ if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1)))
+ return true;
+ }
+ x3 = x4;
+ y3 = y4;
+ }
+ return false;
+ };
+ SkeletonBounds.prototype.getPolygon = function (boundingBox) {
+ if (boundingBox == null)
+ throw new Error("boundingBox cannot be null.");
+ var index = this.boundingBoxes.indexOf(boundingBox);
+ return index == -1 ? null : this.polygons[index];
+ };
+ SkeletonBounds.prototype.getWidth = function () {
+ return this.maxX - this.minX;
+ };
+ SkeletonBounds.prototype.getHeight = function () {
+ return this.maxY - this.minY;
+ };
+ return SkeletonBounds;
+ }());
+ spine.SkeletonBounds = SkeletonBounds;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var SkeletonClipping = (function () {
+ function SkeletonClipping() {
+ this.triangulator = new spine.Triangulator();
+ this.clippingPolygon = new Array();
+ this.clipOutput = new Array();
+ this.clippedVertices = new Array();
+ this.clippedTriangles = new Array();
+ this.scratch = new Array();
+ }
+ SkeletonClipping.prototype.clipStart = function (slot, clip) {
+ if (this.clipAttachment != null)
+ return 0;
+ this.clipAttachment = clip;
+ var n = clip.worldVerticesLength;
+ var vertices = spine.Utils.setArraySize(this.clippingPolygon, n);
+ clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
+ var clippingPolygon = this.clippingPolygon;
+ SkeletonClipping.makeClockwise(clippingPolygon);
+ var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));
+ for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) {
+ var polygon = clippingPolygons[i];
+ SkeletonClipping.makeClockwise(polygon);
+ polygon.push(polygon[0]);
+ polygon.push(polygon[1]);
+ }
+ return clippingPolygons.length;
+ };
+ SkeletonClipping.prototype.clipEndWithSlot = function (slot) {
+ if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data)
+ this.clipEnd();
+ };
+ SkeletonClipping.prototype.clipEnd = function () {
+ if (this.clipAttachment == null)
+ return;
+ this.clipAttachment = null;
+ this.clippingPolygons = null;
+ this.clippedVertices.length = 0;
+ this.clippedTriangles.length = 0;
+ this.clippingPolygon.length = 0;
+ };
+ SkeletonClipping.prototype.isClipping = function () {
+ return this.clipAttachment != null;
+ };
+ SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
+ var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
+ var clippedTriangles = this.clippedTriangles;
+ var polygons = this.clippingPolygons;
+ var polygonsCount = this.clippingPolygons.length;
+ var vertexSize = twoColor ? 12 : 8;
+ var index = 0;
+ clippedVertices.length = 0;
+ clippedTriangles.length = 0;
+ outer: for (var i = 0; i < trianglesLength; i += 3) {
+ var vertexOffset = triangles[i] << 1;
+ var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
+ var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
+ vertexOffset = triangles[i + 1] << 1;
+ var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
+ var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
+ vertexOffset = triangles[i + 2] << 1;
+ var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
+ var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
+ for (var p = 0; p < polygonsCount; p++) {
+ var s = clippedVertices.length;
+ if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
+ var clipOutputLength = clipOutput.length;
+ if (clipOutputLength == 0)
+ continue;
+ var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
+ var d = 1 / (d0 * d2 + d1 * (y1 - y3));
+ var clipOutputCount = clipOutputLength >> 1;
+ var clipOutputItems = this.clipOutput;
+ var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
+ for (var ii = 0; ii < clipOutputLength; ii += 2) {
+ var x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
+ clippedVerticesItems[s] = x;
+ clippedVerticesItems[s + 1] = y;
+ clippedVerticesItems[s + 2] = light.r;
+ clippedVerticesItems[s + 3] = light.g;
+ clippedVerticesItems[s + 4] = light.b;
+ clippedVerticesItems[s + 5] = light.a;
+ var c0 = x - x3, c1 = y - y3;
+ var a = (d0 * c0 + d1 * c1) * d;
+ var b = (d4 * c0 + d2 * c1) * d;
+ var c = 1 - a - b;
+ clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
+ clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
+ if (twoColor) {
+ clippedVerticesItems[s + 8] = dark.r;
+ clippedVerticesItems[s + 9] = dark.g;
+ clippedVerticesItems[s + 10] = dark.b;
+ clippedVerticesItems[s + 11] = dark.a;
+ }
+ s += vertexSize;
+ }
+ s = clippedTriangles.length;
+ var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
+ clipOutputCount--;
+ for (var ii = 1; ii < clipOutputCount; ii++) {
+ clippedTrianglesItems[s] = index;
+ clippedTrianglesItems[s + 1] = (index + ii);
+ clippedTrianglesItems[s + 2] = (index + ii + 1);
+ s += 3;
+ }
+ index += clipOutputCount + 1;
+ }
+ else {
+ var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
+ clippedVerticesItems[s] = x1;
+ clippedVerticesItems[s + 1] = y1;
+ clippedVerticesItems[s + 2] = light.r;
+ clippedVerticesItems[s + 3] = light.g;
+ clippedVerticesItems[s + 4] = light.b;
+ clippedVerticesItems[s + 5] = light.a;
+ if (!twoColor) {
+ clippedVerticesItems[s + 6] = u1;
+ clippedVerticesItems[s + 7] = v1;
+ clippedVerticesItems[s + 8] = x2;
+ clippedVerticesItems[s + 9] = y2;
+ clippedVerticesItems[s + 10] = light.r;
+ clippedVerticesItems[s + 11] = light.g;
+ clippedVerticesItems[s + 12] = light.b;
+ clippedVerticesItems[s + 13] = light.a;
+ clippedVerticesItems[s + 14] = u2;
+ clippedVerticesItems[s + 15] = v2;
+ clippedVerticesItems[s + 16] = x3;
+ clippedVerticesItems[s + 17] = y3;
+ clippedVerticesItems[s + 18] = light.r;
+ clippedVerticesItems[s + 19] = light.g;
+ clippedVerticesItems[s + 20] = light.b;
+ clippedVerticesItems[s + 21] = light.a;
+ clippedVerticesItems[s + 22] = u3;
+ clippedVerticesItems[s + 23] = v3;
+ }
+ else {
+ clippedVerticesItems[s + 6] = u1;
+ clippedVerticesItems[s + 7] = v1;
+ clippedVerticesItems[s + 8] = dark.r;
+ clippedVerticesItems[s + 9] = dark.g;
+ clippedVerticesItems[s + 10] = dark.b;
+ clippedVerticesItems[s + 11] = dark.a;
+ clippedVerticesItems[s + 12] = x2;
+ clippedVerticesItems[s + 13] = y2;
+ clippedVerticesItems[s + 14] = light.r;
+ clippedVerticesItems[s + 15] = light.g;
+ clippedVerticesItems[s + 16] = light.b;
+ clippedVerticesItems[s + 17] = light.a;
+ clippedVerticesItems[s + 18] = u2;
+ clippedVerticesItems[s + 19] = v2;
+ clippedVerticesItems[s + 20] = dark.r;
+ clippedVerticesItems[s + 21] = dark.g;
+ clippedVerticesItems[s + 22] = dark.b;
+ clippedVerticesItems[s + 23] = dark.a;
+ clippedVerticesItems[s + 24] = x3;
+ clippedVerticesItems[s + 25] = y3;
+ clippedVerticesItems[s + 26] = light.r;
+ clippedVerticesItems[s + 27] = light.g;
+ clippedVerticesItems[s + 28] = light.b;
+ clippedVerticesItems[s + 29] = light.a;
+ clippedVerticesItems[s + 30] = u3;
+ clippedVerticesItems[s + 31] = v3;
+ clippedVerticesItems[s + 32] = dark.r;
+ clippedVerticesItems[s + 33] = dark.g;
+ clippedVerticesItems[s + 34] = dark.b;
+ clippedVerticesItems[s + 35] = dark.a;
+ }
+ s = clippedTriangles.length;
+ var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3);
+ clippedTrianglesItems[s] = index;
+ clippedTrianglesItems[s + 1] = (index + 1);
+ clippedTrianglesItems[s + 2] = (index + 2);
+ index += 3;
+ continue outer;
+ }
+ }
+ }
+ };
+ SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) {
+ var originalOutput = output;
+ var clipped = false;
+ var input = null;
+ if (clippingArea.length % 4 >= 2) {
+ input = output;
+ output = this.scratch;
+ }
+ else
+ input = this.scratch;
+ input.length = 0;
+ input.push(x1);
+ input.push(y1);
+ input.push(x2);
+ input.push(y2);
+ input.push(x3);
+ input.push(y3);
+ input.push(x1);
+ input.push(y1);
+ output.length = 0;
+ var clippingVertices = clippingArea;
+ var clippingVerticesLast = clippingArea.length - 4;
+ for (var i = 0;; i += 2) {
+ var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
+ var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
+ var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
+ var inputVertices = input;
+ var inputVerticesLength = input.length - 2, outputStart = output.length;
+ for (var ii = 0; ii < inputVerticesLength; ii += 2) {
+ var inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
+ var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
+ var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
+ if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
+ if (side2) {
+ output.push(inputX2);
+ output.push(inputY2);
+ continue;
+ }
+ var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
+ var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
+ output.push(edgeX + (edgeX2 - edgeX) * ua);
+ output.push(edgeY + (edgeY2 - edgeY) * ua);
+ }
+ else if (side2) {
+ var c0 = inputY2 - inputY, c2 = inputX2 - inputX;
+ var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY));
+ output.push(edgeX + (edgeX2 - edgeX) * ua);
+ output.push(edgeY + (edgeY2 - edgeY) * ua);
+ output.push(inputX2);
+ output.push(inputY2);
+ }
+ clipped = true;
+ }
+ if (outputStart == output.length) {
+ originalOutput.length = 0;
+ return true;
+ }
+ output.push(output[0]);
+ output.push(output[1]);
+ if (i == clippingVerticesLast)
+ break;
+ var temp = output;
+ output = input;
+ output.length = 0;
+ input = temp;
+ }
+ if (originalOutput != output) {
+ originalOutput.length = 0;
+ for (var i = 0, n = output.length - 2; i < n; i++)
+ originalOutput[i] = output[i];
+ }
+ else
+ originalOutput.length = originalOutput.length - 2;
+ return clipped;
+ };
+ SkeletonClipping.makeClockwise = function (polygon) {
+ var vertices = polygon;
+ var verticeslength = polygon.length;
+ var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
+ for (var i = 0, n = verticeslength - 3; i < n; i += 2) {
+ p1x = vertices[i];
+ p1y = vertices[i + 1];
+ p2x = vertices[i + 2];
+ p2y = vertices[i + 3];
+ area += p1x * p2y - p2x * p1y;
+ }
+ if (area < 0)
+ return;
+ for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
+ var x = vertices[i], y = vertices[i + 1];
+ var other = lastX - i;
+ vertices[i] = vertices[other];
+ vertices[i + 1] = vertices[other + 1];
+ vertices[other] = x;
+ vertices[other + 1] = y;
+ }
+ };
+ return SkeletonClipping;
+ }());
+ spine.SkeletonClipping = SkeletonClipping;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var SkeletonData = (function () {
+ function SkeletonData() {
+ this.bones = new Array();
+ this.slots = new Array();
+ this.skins = new Array();
+ this.events = new Array();
+ this.animations = new Array();
+ this.ikConstraints = new Array();
+ this.transformConstraints = new Array();
+ this.pathConstraints = new Array();
+ this.fps = 0;
+ }
+ SkeletonData.prototype.findBone = function (boneName) {
+ if (boneName == null)
+ throw new Error("boneName cannot be null.");
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ if (bone.name == boneName)
+ return bone;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findBoneIndex = function (boneName) {
+ if (boneName == null)
+ throw new Error("boneName cannot be null.");
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++)
+ if (bones[i].name == boneName)
+ return i;
+ return -1;
+ };
+ SkeletonData.prototype.findSlot = function (slotName) {
+ if (slotName == null)
+ throw new Error("slotName cannot be null.");
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++) {
+ var slot = slots[i];
+ if (slot.name == slotName)
+ return slot;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findSlotIndex = function (slotName) {
+ if (slotName == null)
+ throw new Error("slotName cannot be null.");
+ var slots = this.slots;
+ for (var i = 0, n = slots.length; i < n; i++)
+ if (slots[i].name == slotName)
+ return i;
+ return -1;
+ };
+ SkeletonData.prototype.findSkin = function (skinName) {
+ if (skinName == null)
+ throw new Error("skinName cannot be null.");
+ var skins = this.skins;
+ for (var i = 0, n = skins.length; i < n; i++) {
+ var skin = skins[i];
+ if (skin.name == skinName)
+ return skin;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findEvent = function (eventDataName) {
+ if (eventDataName == null)
+ throw new Error("eventDataName cannot be null.");
+ var events = this.events;
+ for (var i = 0, n = events.length; i < n; i++) {
+ var event_4 = events[i];
+ if (event_4.name == eventDataName)
+ return event_4;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findAnimation = function (animationName) {
+ if (animationName == null)
+ throw new Error("animationName cannot be null.");
+ var animations = this.animations;
+ for (var i = 0, n = animations.length; i < n; i++) {
+ var animation = animations[i];
+ if (animation.name == animationName)
+ return animation;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findIkConstraint = function (constraintName) {
+ if (constraintName == null)
+ throw new Error("constraintName cannot be null.");
+ var ikConstraints = this.ikConstraints;
+ for (var i = 0, n = ikConstraints.length; i < n; i++) {
+ var constraint = ikConstraints[i];
+ if (constraint.name == constraintName)
+ return constraint;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findTransformConstraint = function (constraintName) {
+ if (constraintName == null)
+ throw new Error("constraintName cannot be null.");
+ var transformConstraints = this.transformConstraints;
+ for (var i = 0, n = transformConstraints.length; i < n; i++) {
+ var constraint = transformConstraints[i];
+ if (constraint.name == constraintName)
+ return constraint;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findPathConstraint = function (constraintName) {
+ if (constraintName == null)
+ throw new Error("constraintName cannot be null.");
+ var pathConstraints = this.pathConstraints;
+ for (var i = 0, n = pathConstraints.length; i < n; i++) {
+ var constraint = pathConstraints[i];
+ if (constraint.name == constraintName)
+ return constraint;
+ }
+ return null;
+ };
+ SkeletonData.prototype.findPathConstraintIndex = function (pathConstraintName) {
+ if (pathConstraintName == null)
+ throw new Error("pathConstraintName cannot be null.");
+ var pathConstraints = this.pathConstraints;
+ for (var i = 0, n = pathConstraints.length; i < n; i++)
+ if (pathConstraints[i].name == pathConstraintName)
+ return i;
+ return -1;
+ };
+ return SkeletonData;
+ }());
+ spine.SkeletonData = SkeletonData;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var SkeletonJson = (function () {
+ function SkeletonJson(attachmentLoader) {
+ this.scale = 1;
+ this.linkedMeshes = new Array();
+ this.attachmentLoader = attachmentLoader;
+ }
+ SkeletonJson.prototype.readSkeletonData = function (json) {
+ var scale = this.scale;
+ var skeletonData = new spine.SkeletonData();
+ var root = typeof (json) === "string" ? JSON.parse(json) : json;
+ var skeletonMap = root.skeleton;
+ if (skeletonMap != null) {
+ skeletonData.hash = skeletonMap.hash;
+ skeletonData.version = skeletonMap.spine;
+ skeletonData.width = skeletonMap.width;
+ skeletonData.height = skeletonMap.height;
+ skeletonData.fps = skeletonMap.fps;
+ skeletonData.imagesPath = skeletonMap.images;
+ }
+ if (root.bones) {
+ for (var i = 0; i < root.bones.length; i++) {
+ var boneMap = root.bones[i];
+ var parent_2 = null;
+ var parentName = this.getValue(boneMap, "parent", null);
+ if (parentName != null) {
+ parent_2 = skeletonData.findBone(parentName);
+ if (parent_2 == null)
+ throw new Error("Parent bone not found: " + parentName);
+ }
+ var data = new spine.BoneData(skeletonData.bones.length, boneMap.name, parent_2);
+ data.length = this.getValue(boneMap, "length", 0) * scale;
+ data.x = this.getValue(boneMap, "x", 0) * scale;
+ data.y = this.getValue(boneMap, "y", 0) * scale;
+ data.rotation = this.getValue(boneMap, "rotation", 0);
+ data.scaleX = this.getValue(boneMap, "scaleX", 1);
+ data.scaleY = this.getValue(boneMap, "scaleY", 1);
+ data.shearX = this.getValue(boneMap, "shearX", 0);
+ data.shearY = this.getValue(boneMap, "shearY", 0);
+ data.transformMode = SkeletonJson.transformModeFromString(this.getValue(boneMap, "transform", "normal"));
+ skeletonData.bones.push(data);
+ }
+ }
+ if (root.slots) {
+ for (var i = 0; i < root.slots.length; i++) {
+ var slotMap = root.slots[i];
+ var slotName = slotMap.name;
+ var boneName = slotMap.bone;
+ var boneData = skeletonData.findBone(boneName);
+ if (boneData == null)
+ throw new Error("Slot bone not found: " + boneName);
+ var data = new spine.SlotData(skeletonData.slots.length, slotName, boneData);
+ var color = this.getValue(slotMap, "color", null);
+ if (color != null)
+ data.color.setFromString(color);
+ var dark = this.getValue(slotMap, "dark", null);
+ if (dark != null) {
+ data.darkColor = new spine.Color(1, 1, 1, 1);
+ data.darkColor.setFromString(dark);
+ }
+ data.attachmentName = this.getValue(slotMap, "attachment", null);
+ data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal"));
+ skeletonData.slots.push(data);
+ }
+ }
+ if (root.ik) {
+ for (var i = 0; i < root.ik.length; i++) {
+ var constraintMap = root.ik[i];
+ var data = new spine.IkConstraintData(constraintMap.name);
+ data.order = this.getValue(constraintMap, "order", 0);
+ for (var j = 0; j < constraintMap.bones.length; j++) {
+ var boneName = constraintMap.bones[j];
+ var bone = skeletonData.findBone(boneName);
+ if (bone == null)
+ throw new Error("IK bone not found: " + boneName);
+ data.bones.push(bone);
+ }
+ var targetName = constraintMap.target;
+ data.target = skeletonData.findBone(targetName);
+ if (data.target == null)
+ throw new Error("IK target bone not found: " + targetName);
+ data.bendDirection = this.getValue(constraintMap, "bendPositive", true) ? 1 : -1;
+ data.mix = this.getValue(constraintMap, "mix", 1);
+ skeletonData.ikConstraints.push(data);
+ }
+ }
+ if (root.transform) {
+ for (var i = 0; i < root.transform.length; i++) {
+ var constraintMap = root.transform[i];
+ var data = new spine.TransformConstraintData(constraintMap.name);
+ data.order = this.getValue(constraintMap, "order", 0);
+ for (var j = 0; j < constraintMap.bones.length; j++) {
+ var boneName = constraintMap.bones[j];
+ var bone = skeletonData.findBone(boneName);
+ if (bone == null)
+ throw new Error("Transform constraint bone not found: " + boneName);
+ data.bones.push(bone);
+ }
+ var targetName = constraintMap.target;
+ data.target = skeletonData.findBone(targetName);
+ if (data.target == null)
+ throw new Error("Transform constraint target bone not found: " + targetName);
+ data.local = this.getValue(constraintMap, "local", false);
+ data.relative = this.getValue(constraintMap, "relative", false);
+ data.offsetRotation = this.getValue(constraintMap, "rotation", 0);
+ data.offsetX = this.getValue(constraintMap, "x", 0) * scale;
+ data.offsetY = this.getValue(constraintMap, "y", 0) * scale;
+ data.offsetScaleX = this.getValue(constraintMap, "scaleX", 0);
+ data.offsetScaleY = this.getValue(constraintMap, "scaleY", 0);
+ data.offsetShearY = this.getValue(constraintMap, "shearY", 0);
+ data.rotateMix = this.getValue(constraintMap, "rotateMix", 1);
+ data.translateMix = this.getValue(constraintMap, "translateMix", 1);
+ data.scaleMix = this.getValue(constraintMap, "scaleMix", 1);
+ data.shearMix = this.getValue(constraintMap, "shearMix", 1);
+ skeletonData.transformConstraints.push(data);
+ }
+ }
+ if (root.path) {
+ for (var i = 0; i < root.path.length; i++) {
+ var constraintMap = root.path[i];
+ var data = new spine.PathConstraintData(constraintMap.name);
+ data.order = this.getValue(constraintMap, "order", 0);
+ for (var j = 0; j < constraintMap.bones.length; j++) {
+ var boneName = constraintMap.bones[j];
+ var bone = skeletonData.findBone(boneName);
+ if (bone == null)
+ throw new Error("Transform constraint bone not found: " + boneName);
+ data.bones.push(bone);
+ }
+ var targetName = constraintMap.target;
+ data.target = skeletonData.findSlot(targetName);
+ if (data.target == null)
+ throw new Error("Path target slot not found: " + targetName);
+ data.positionMode = SkeletonJson.positionModeFromString(this.getValue(constraintMap, "positionMode", "percent"));
+ data.spacingMode = SkeletonJson.spacingModeFromString(this.getValue(constraintMap, "spacingMode", "length"));
+ data.rotateMode = SkeletonJson.rotateModeFromString(this.getValue(constraintMap, "rotateMode", "tangent"));
+ data.offsetRotation = this.getValue(constraintMap, "rotation", 0);
+ data.position = this.getValue(constraintMap, "position", 0);
+ if (data.positionMode == spine.PositionMode.Fixed)
+ data.position *= scale;
+ data.spacing = this.getValue(constraintMap, "spacing", 0);
+ if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed)
+ data.spacing *= scale;
+ data.rotateMix = this.getValue(constraintMap, "rotateMix", 1);
+ data.translateMix = this.getValue(constraintMap, "translateMix", 1);
+ skeletonData.pathConstraints.push(data);
+ }
+ }
+ if (root.skins) {
+ for (var skinName in root.skins) {
+ var skinMap = root.skins[skinName];
+ var skin = new spine.Skin(skinName);
+ for (var slotName in skinMap) {
+ var slotIndex = skeletonData.findSlotIndex(slotName);
+ if (slotIndex == -1)
+ throw new Error("Slot not found: " + slotName);
+ var slotMap = skinMap[slotName];
+ for (var entryName in slotMap) {
+ var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData);
+ if (attachment != null)
+ skin.addAttachment(slotIndex, entryName, attachment);
+ }
+ }
+ skeletonData.skins.push(skin);
+ if (skin.name == "default")
+ skeletonData.defaultSkin = skin;
+ }
+ }
+ for (var i = 0, n = this.linkedMeshes.length; i < n; i++) {
+ var linkedMesh = this.linkedMeshes[i];
+ var skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
+ if (skin == null)
+ throw new Error("Skin not found: " + linkedMesh.skin);
+ var parent_3 = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
+ if (parent_3 == null)
+ throw new Error("Parent mesh not found: " + linkedMesh.parent);
+ linkedMesh.mesh.setParentMesh(parent_3);
+ linkedMesh.mesh.updateUVs();
+ }
+ this.linkedMeshes.length = 0;
+ if (root.events) {
+ for (var eventName in root.events) {
+ var eventMap = root.events[eventName];
+ var data = new spine.EventData(eventName);
+ data.intValue = this.getValue(eventMap, "int", 0);
+ data.floatValue = this.getValue(eventMap, "float", 0);
+ data.stringValue = this.getValue(eventMap, "string", "");
+ skeletonData.events.push(data);
+ }
+ }
+ if (root.animations) {
+ for (var animationName in root.animations) {
+ var animationMap = root.animations[animationName];
+ this.readAnimation(animationMap, animationName, skeletonData);
+ }
+ }
+ return skeletonData;
+ };
+ SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) {
+ var scale = this.scale;
+ name = this.getValue(map, "name", name);
+ var type = this.getValue(map, "type", "region");
+ switch (type) {
+ case "region": {
+ var path = this.getValue(map, "path", name);
+ var region = this.attachmentLoader.newRegionAttachment(skin, name, path);
+ if (region == null)
+ return null;
+ region.path = path;
+ region.x = this.getValue(map, "x", 0) * scale;
+ region.y = this.getValue(map, "y", 0) * scale;
+ region.scaleX = this.getValue(map, "scaleX", 1);
+ region.scaleY = this.getValue(map, "scaleY", 1);
+ region.rotation = this.getValue(map, "rotation", 0);
+ region.width = map.width * scale;
+ region.height = map.height * scale;
+ var color = this.getValue(map, "color", null);
+ if (color != null)
+ region.color.setFromString(color);
+ region.updateOffset();
+ return region;
+ }
+ case "boundingbox": {
+ var box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);
+ if (box == null)
+ return null;
+ this.readVertices(map, box, map.vertexCount << 1);
+ var color = this.getValue(map, "color", null);
+ if (color != null)
+ box.color.setFromString(color);
+ return box;
+ }
+ case "mesh":
+ case "linkedmesh": {
+ var path = this.getValue(map, "path", name);
+ var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path);
+ if (mesh == null)
+ return null;
+ mesh.path = path;
+ var color = this.getValue(map, "color", null);
+ if (color != null)
+ mesh.color.setFromString(color);
+ var parent_4 = this.getValue(map, "parent", null);
+ if (parent_4 != null) {
+ mesh.inheritDeform = this.getValue(map, "deform", true);
+ this.linkedMeshes.push(new LinkedMesh(mesh, this.getValue(map, "skin", null), slotIndex, parent_4));
+ return mesh;
+ }
+ var uvs = map.uvs;
+ this.readVertices(map, mesh, uvs.length);
+ mesh.triangles = map.triangles;
+ mesh.regionUVs = uvs;
+ mesh.updateUVs();
+ mesh.hullLength = this.getValue(map, "hull", 0) * 2;
+ return mesh;
+ }
+ case "path": {
+ var path = this.attachmentLoader.newPathAttachment(skin, name);
+ if (path == null)
+ return null;
+ path.closed = this.getValue(map, "closed", false);
+ path.constantSpeed = this.getValue(map, "constantSpeed", true);
+ var vertexCount = map.vertexCount;
+ this.readVertices(map, path, vertexCount << 1);
+ var lengths = spine.Utils.newArray(vertexCount / 3, 0);
+ for (var i = 0; i < map.lengths.length; i++)
+ lengths[i] = map.lengths[i] * scale;
+ path.lengths = lengths;
+ var color = this.getValue(map, "color", null);
+ if (color != null)
+ path.color.setFromString(color);
+ return path;
+ }
+ case "point": {
+ var point = this.attachmentLoader.newPointAttachment(skin, name);
+ if (point == null)
+ return null;
+ point.x = this.getValue(map, "x", 0) * scale;
+ point.y = this.getValue(map, "y", 0) * scale;
+ point.rotation = this.getValue(map, "rotation", 0);
+ var color = this.getValue(map, "color", null);
+ if (color != null)
+ point.color.setFromString(color);
+ return point;
+ }
+ case "clipping": {
+ var clip = this.attachmentLoader.newClippingAttachment(skin, name);
+ if (clip == null)
+ return null;
+ var end = this.getValue(map, "end", null);
+ if (end != null) {
+ var slot = skeletonData.findSlot(end);
+ if (slot == null)
+ throw new Error("Clipping end slot not found: " + end);
+ clip.endSlot = slot;
+ }
+ var vertexCount = map.vertexCount;
+ this.readVertices(map, clip, vertexCount << 1);
+ var color = this.getValue(map, "color", null);
+ if (color != null)
+ clip.color.setFromString(color);
+ return clip;
+ }
+ }
+ return null;
+ };
+ SkeletonJson.prototype.readVertices = function (map, attachment, verticesLength) {
+ var scale = this.scale;
+ attachment.worldVerticesLength = verticesLength;
+ var vertices = map.vertices;
+ if (verticesLength == vertices.length) {
+ var scaledVertices = spine.Utils.toFloatArray(vertices);
+ if (scale != 1) {
+ for (var i = 0, n = vertices.length; i < n; i++)
+ scaledVertices[i] *= scale;
+ }
+ attachment.vertices = scaledVertices;
+ return;
+ }
+ var weights = new Array();
+ var bones = new Array();
+ for (var i = 0, n = vertices.length; i < n;) {
+ var boneCount = vertices[i++];
+ bones.push(boneCount);
+ for (var nn = i + boneCount * 4; i < nn; i += 4) {
+ bones.push(vertices[i]);
+ weights.push(vertices[i + 1] * scale);
+ weights.push(vertices[i + 2] * scale);
+ weights.push(vertices[i + 3]);
+ }
+ }
+ attachment.bones = bones;
+ attachment.vertices = spine.Utils.toFloatArray(weights);
+ };
+ SkeletonJson.prototype.readAnimation = function (map, name, skeletonData) {
+ var scale = this.scale;
+ var timelines = new Array();
+ var duration = 0;
+ if (map.slots) {
+ for (var slotName in map.slots) {
+ var slotMap = map.slots[slotName];
+ var slotIndex = skeletonData.findSlotIndex(slotName);
+ if (slotIndex == -1)
+ throw new Error("Slot not found: " + slotName);
+ for (var timelineName in slotMap) {
+ var timelineMap = slotMap[timelineName];
+ if (timelineName == "attachment") {
+ var timeline = new spine.AttachmentTimeline(timelineMap.length);
+ timeline.slotIndex = slotIndex;
+ var frameIndex = 0;
+ for (var i = 0; i < timelineMap.length; i++) {
+ var valueMap = timelineMap[i];
+ timeline.setFrame(frameIndex++, valueMap.time, valueMap.name);
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
+ }
+ else if (timelineName == "color") {
+ var timeline = new spine.ColorTimeline(timelineMap.length);
+ timeline.slotIndex = slotIndex;
+ var frameIndex = 0;
+ for (var i = 0; i < timelineMap.length; i++) {
+ var valueMap = timelineMap[i];
+ var color = new spine.Color();
+ color.setFromString(valueMap.color);
+ timeline.setFrame(frameIndex, valueMap.time, color.r, color.g, color.b, color.a);
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]);
+ }
+ else if (timelineName == "twoColor") {
+ var timeline = new spine.TwoColorTimeline(timelineMap.length);
+ timeline.slotIndex = slotIndex;
+ var frameIndex = 0;
+ for (var i = 0; i < timelineMap.length; i++) {
+ var valueMap = timelineMap[i];
+ var light = new spine.Color();
+ var dark = new spine.Color();
+ light.setFromString(valueMap.light);
+ dark.setFromString(valueMap.dark);
+ timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b);
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TwoColorTimeline.ENTRIES]);
+ }
+ else
+ throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
+ }
+ }
+ }
+ if (map.bones) {
+ for (var boneName in map.bones) {
+ var boneMap = map.bones[boneName];
+ var boneIndex = skeletonData.findBoneIndex(boneName);
+ if (boneIndex == -1)
+ throw new Error("Bone not found: " + boneName);
+ for (var timelineName in boneMap) {
+ var timelineMap = boneMap[timelineName];
+ if (timelineName === "rotate") {
+ var timeline = new spine.RotateTimeline(timelineMap.length);
+ timeline.boneIndex = boneIndex;
+ var frameIndex = 0;
+ for (var i = 0; i < timelineMap.length; i++) {
+ var valueMap = timelineMap[i];
+ timeline.setFrame(frameIndex, valueMap.time, valueMap.angle);
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.RotateTimeline.ENTRIES]);
+ }
+ else if (timelineName === "translate" || timelineName === "scale" || timelineName === "shear") {
+ var timeline = null;
+ var timelineScale = 1;
+ if (timelineName === "scale")
+ timeline = new spine.ScaleTimeline(timelineMap.length);
+ else if (timelineName === "shear")
+ timeline = new spine.ShearTimeline(timelineMap.length);
+ else {
+ timeline = new spine.TranslateTimeline(timelineMap.length);
+ timelineScale = scale;
+ }
+ timeline.boneIndex = boneIndex;
+ var frameIndex = 0;
+ for (var i = 0; i < timelineMap.length; i++) {
+ var valueMap = timelineMap[i];
+ var x = this.getValue(valueMap, "x", 0), y = this.getValue(valueMap, "y", 0);
+ timeline.setFrame(frameIndex, valueMap.time, x * timelineScale, y * timelineScale);
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TranslateTimeline.ENTRIES]);
+ }
+ else
+ throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
+ }
+ }
+ }
+ if (map.ik) {
+ for (var constraintName in map.ik) {
+ var constraintMap = map.ik[constraintName];
+ var constraint = skeletonData.findIkConstraint(constraintName);
+ var timeline = new spine.IkConstraintTimeline(constraintMap.length);
+ timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(constraint);
+ var frameIndex = 0;
+ for (var i = 0; i < constraintMap.length; i++) {
+ var valueMap = constraintMap[i];
+ timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "mix", 1), this.getValue(valueMap, "bendPositive", true) ? 1 : -1);
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.IkConstraintTimeline.ENTRIES]);
+ }
+ }
+ if (map.transform) {
+ for (var constraintName in map.transform) {
+ var constraintMap = map.transform[constraintName];
+ var constraint = skeletonData.findTransformConstraint(constraintName);
+ var timeline = new spine.TransformConstraintTimeline(constraintMap.length);
+ timeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(constraint);
+ var frameIndex = 0;
+ for (var i = 0; i < constraintMap.length; i++) {
+ var valueMap = constraintMap[i];
+ timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1), this.getValue(valueMap, "scaleMix", 1), this.getValue(valueMap, "shearMix", 1));
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TransformConstraintTimeline.ENTRIES]);
+ }
+ }
+ if (map.paths) {
+ for (var constraintName in map.paths) {
+ var constraintMap = map.paths[constraintName];
+ var index = skeletonData.findPathConstraintIndex(constraintName);
+ if (index == -1)
+ throw new Error("Path constraint not found: " + constraintName);
+ var data = skeletonData.pathConstraints[index];
+ for (var timelineName in constraintMap) {
+ var timelineMap = constraintMap[timelineName];
+ if (timelineName === "position" || timelineName === "spacing") {
+ var timeline = null;
+ var timelineScale = 1;
+ if (timelineName === "spacing") {
+ timeline = new spine.PathConstraintSpacingTimeline(timelineMap.length);
+ if (data.spacingMode == spine.SpacingMode.Length || data.spacingMode == spine.SpacingMode.Fixed)
+ timelineScale = scale;
+ }
+ else {
+ timeline = new spine.PathConstraintPositionTimeline(timelineMap.length);
+ if (data.positionMode == spine.PositionMode.Fixed)
+ timelineScale = scale;
+ }
+ timeline.pathConstraintIndex = index;
+ var frameIndex = 0;
+ for (var i = 0; i < timelineMap.length; i++) {
+ var valueMap = timelineMap[i];
+ timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, timelineName, 0) * timelineScale);
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintPositionTimeline.ENTRIES]);
+ }
+ else if (timelineName === "mix") {
+ var timeline = new spine.PathConstraintMixTimeline(timelineMap.length);
+ timeline.pathConstraintIndex = index;
+ var frameIndex = 0;
+ for (var i = 0; i < timelineMap.length; i++) {
+ var valueMap = timelineMap[i];
+ timeline.setFrame(frameIndex, valueMap.time, this.getValue(valueMap, "rotateMix", 1), this.getValue(valueMap, "translateMix", 1));
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.PathConstraintMixTimeline.ENTRIES]);
+ }
+ }
+ }
+ }
+ if (map.deform) {
+ for (var deformName in map.deform) {
+ var deformMap = map.deform[deformName];
+ var skin = skeletonData.findSkin(deformName);
+ if (skin == null)
+ throw new Error("Skin not found: " + deformName);
+ for (var slotName in deformMap) {
+ var slotMap = deformMap[slotName];
+ var slotIndex = skeletonData.findSlotIndex(slotName);
+ if (slotIndex == -1)
+ throw new Error("Slot not found: " + slotMap.name);
+ for (var timelineName in slotMap) {
+ var timelineMap = slotMap[timelineName];
+ var attachment = skin.getAttachment(slotIndex, timelineName);
+ if (attachment == null)
+ throw new Error("Deform attachment not found: " + timelineMap.name);
+ var weighted = attachment.bones != null;
+ var vertices = attachment.vertices;
+ var deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;
+ var timeline = new spine.DeformTimeline(timelineMap.length);
+ timeline.slotIndex = slotIndex;
+ timeline.attachment = attachment;
+ var frameIndex = 0;
+ for (var j = 0; j < timelineMap.length; j++) {
+ var valueMap = timelineMap[j];
+ var deform = void 0;
+ var verticesValue = this.getValue(valueMap, "vertices", null);
+ if (verticesValue == null)
+ deform = weighted ? spine.Utils.newFloatArray(deformLength) : vertices;
+ else {
+ deform = spine.Utils.newFloatArray(deformLength);
+ var start = this.getValue(valueMap, "offset", 0);
+ spine.Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length);
+ if (scale != 1) {
+ for (var i = start, n = i + verticesValue.length; i < n; i++)
+ deform[i] *= scale;
+ }
+ if (!weighted) {
+ for (var i = 0; i < deformLength; i++)
+ deform[i] += vertices[i];
+ }
+ }
+ timeline.setFrame(frameIndex, valueMap.time, deform);
+ this.readCurve(valueMap, timeline, frameIndex);
+ frameIndex++;
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
+ }
+ }
+ }
+ }
+ var drawOrderNode = map.drawOrder;
+ if (drawOrderNode == null)
+ drawOrderNode = map.draworder;
+ if (drawOrderNode != null) {
+ var timeline = new spine.DrawOrderTimeline(drawOrderNode.length);
+ var slotCount = skeletonData.slots.length;
+ var frameIndex = 0;
+ for (var j = 0; j < drawOrderNode.length; j++) {
+ var drawOrderMap = drawOrderNode[j];
+ var drawOrder = null;
+ var offsets = this.getValue(drawOrderMap, "offsets", null);
+ if (offsets != null) {
+ drawOrder = spine.Utils.newArray(slotCount, -1);
+ var unchanged = spine.Utils.newArray(slotCount - offsets.length, 0);
+ var originalIndex = 0, unchangedIndex = 0;
+ for (var i = 0; i < offsets.length; i++) {
+ var offsetMap = offsets[i];
+ var slotIndex = skeletonData.findSlotIndex(offsetMap.slot);
+ if (slotIndex == -1)
+ throw new Error("Slot not found: " + offsetMap.slot);
+ while (originalIndex != slotIndex)
+ unchanged[unchangedIndex++] = originalIndex++;
+ drawOrder[originalIndex + offsetMap.offset] = originalIndex++;
+ }
+ while (originalIndex < slotCount)
+ unchanged[unchangedIndex++] = originalIndex++;
+ for (var i = slotCount - 1; i >= 0; i--)
+ if (drawOrder[i] == -1)
+ drawOrder[i] = unchanged[--unchangedIndex];
+ }
+ timeline.setFrame(frameIndex++, drawOrderMap.time, drawOrder);
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
+ }
+ if (map.events) {
+ var timeline = new spine.EventTimeline(map.events.length);
+ var frameIndex = 0;
+ for (var i = 0; i < map.events.length; i++) {
+ var eventMap = map.events[i];
+ var eventData = skeletonData.findEvent(eventMap.name);
+ if (eventData == null)
+ throw new Error("Event not found: " + eventMap.name);
+ var event_5 = new spine.Event(spine.Utils.toSinglePrecision(eventMap.time), eventData);
+ event_5.intValue = this.getValue(eventMap, "int", eventData.intValue);
+ event_5.floatValue = this.getValue(eventMap, "float", eventData.floatValue);
+ event_5.stringValue = this.getValue(eventMap, "string", eventData.stringValue);
+ timeline.setFrame(frameIndex++, event_5);
+ }
+ timelines.push(timeline);
+ duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
+ }
+ if (isNaN(duration)) {
+ throw new Error("Error while parsing animation, duration is NaN");
+ }
+ skeletonData.animations.push(new spine.Animation(name, timelines, duration));
+ };
+ SkeletonJson.prototype.readCurve = function (map, timeline, frameIndex) {
+ if (!map.curve)
+ return;
+ if (map.curve === "stepped")
+ timeline.setStepped(frameIndex);
+ else if (Object.prototype.toString.call(map.curve) === '[object Array]') {
+ var curve = map.curve;
+ timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]);
+ }
+ };
+ SkeletonJson.prototype.getValue = function (map, prop, defaultValue) {
+ return map[prop] !== undefined ? map[prop] : defaultValue;
+ };
+ SkeletonJson.blendModeFromString = function (str) {
+ str = str.toLowerCase();
+ if (str == "normal")
+ return spine.BlendMode.Normal;
+ if (str == "additive")
+ return spine.BlendMode.Additive;
+ if (str == "multiply")
+ return spine.BlendMode.Multiply;
+ if (str == "screen")
+ return spine.BlendMode.Screen;
+ throw new Error("Unknown blend mode: " + str);
+ };
+ SkeletonJson.positionModeFromString = function (str) {
+ str = str.toLowerCase();
+ if (str == "fixed")
+ return spine.PositionMode.Fixed;
+ if (str == "percent")
+ return spine.PositionMode.Percent;
+ throw new Error("Unknown position mode: " + str);
+ };
+ SkeletonJson.spacingModeFromString = function (str) {
+ str = str.toLowerCase();
+ if (str == "length")
+ return spine.SpacingMode.Length;
+ if (str == "fixed")
+ return spine.SpacingMode.Fixed;
+ if (str == "percent")
+ return spine.SpacingMode.Percent;
+ throw new Error("Unknown position mode: " + str);
+ };
+ SkeletonJson.rotateModeFromString = function (str) {
+ str = str.toLowerCase();
+ if (str == "tangent")
+ return spine.RotateMode.Tangent;
+ if (str == "chain")
+ return spine.RotateMode.Chain;
+ if (str == "chainscale")
+ return spine.RotateMode.ChainScale;
+ throw new Error("Unknown rotate mode: " + str);
+ };
+ SkeletonJson.transformModeFromString = function (str) {
+ str = str.toLowerCase();
+ if (str == "normal")
+ return spine.TransformMode.Normal;
+ if (str == "onlytranslation")
+ return spine.TransformMode.OnlyTranslation;
+ if (str == "norotationorreflection")
+ return spine.TransformMode.NoRotationOrReflection;
+ if (str == "noscale")
+ return spine.TransformMode.NoScale;
+ if (str == "noscaleorreflection")
+ return spine.TransformMode.NoScaleOrReflection;
+ throw new Error("Unknown transform mode: " + str);
+ };
+ return SkeletonJson;
+ }());
+ spine.SkeletonJson = SkeletonJson;
+ var LinkedMesh = (function () {
+ function LinkedMesh(mesh, skin, slotIndex, parent) {
+ this.mesh = mesh;
+ this.skin = skin;
+ this.slotIndex = slotIndex;
+ this.parent = parent;
+ }
+ return LinkedMesh;
+ }());
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Skin = (function () {
+ function Skin(name) {
+ this.attachments = new Array();
+ if (name == null)
+ throw new Error("name cannot be null.");
+ this.name = name;
+ }
+ Skin.prototype.addAttachment = function (slotIndex, name, attachment) {
+ if (attachment == null)
+ throw new Error("attachment cannot be null.");
+ var attachments = this.attachments;
+ if (slotIndex >= attachments.length)
+ attachments.length = slotIndex + 1;
+ if (!attachments[slotIndex])
+ attachments[slotIndex] = {};
+ attachments[slotIndex][name] = attachment;
+ };
+ Skin.prototype.getAttachment = function (slotIndex, name) {
+ var dictionary = this.attachments[slotIndex];
+ return dictionary ? dictionary[name] : null;
+ };
+ Skin.prototype.attachAll = function (skeleton, oldSkin) {
+ var slotIndex = 0;
+ for (var i = 0; i < skeleton.slots.length; i++) {
+ var slot = skeleton.slots[i];
+ var slotAttachment = slot.getAttachment();
+ if (slotAttachment && slotIndex < oldSkin.attachments.length) {
+ var dictionary = oldSkin.attachments[slotIndex];
+ for (var key in dictionary) {
+ var skinAttachment = dictionary[key];
+ if (slotAttachment == skinAttachment) {
+ var attachment = this.getAttachment(slotIndex, key);
+ if (attachment != null)
+ slot.setAttachment(attachment);
+ break;
+ }
+ }
+ }
+ slotIndex++;
+ }
+ };
+ return Skin;
+ }());
+ spine.Skin = Skin;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Slot = (function () {
+ function Slot(data, bone) {
+ this.attachmentVertices = new Array();
+ if (data == null)
+ throw new Error("data cannot be null.");
+ if (bone == null)
+ throw new Error("bone cannot be null.");
+ this.data = data;
+ this.bone = bone;
+ this.color = new spine.Color();
+ this.darkColor = data.darkColor == null ? null : new spine.Color();
+ this.setToSetupPose();
+ }
+ Slot.prototype.getAttachment = function () {
+ return this.attachment;
+ };
+ Slot.prototype.setAttachment = function (attachment) {
+ if (this.attachment == attachment)
+ return;
+ this.attachment = attachment;
+ this.attachmentTime = this.bone.skeleton.time;
+ this.attachmentVertices.length = 0;
+ };
+ Slot.prototype.setAttachmentTime = function (time) {
+ this.attachmentTime = this.bone.skeleton.time - time;
+ };
+ Slot.prototype.getAttachmentTime = function () {
+ return this.bone.skeleton.time - this.attachmentTime;
+ };
+ Slot.prototype.setToSetupPose = function () {
+ this.color.setFromColor(this.data.color);
+ if (this.darkColor != null)
+ this.darkColor.setFromColor(this.data.darkColor);
+ if (this.data.attachmentName == null)
+ this.attachment = null;
+ else {
+ this.attachment = null;
+ this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName));
+ }
+ };
+ return Slot;
+ }());
+ spine.Slot = Slot;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var SlotData = (function () {
+ function SlotData(index, name, boneData) {
+ this.color = new spine.Color(1, 1, 1, 1);
+ if (index < 0)
+ throw new Error("index must be >= 0.");
+ if (name == null)
+ throw new Error("name cannot be null.");
+ if (boneData == null)
+ throw new Error("boneData cannot be null.");
+ this.index = index;
+ this.name = name;
+ this.boneData = boneData;
+ }
+ return SlotData;
+ }());
+ spine.SlotData = SlotData;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Texture = (function () {
+ function Texture(image) {
+ this._image = image;
+ }
+ Texture.prototype.getImage = function () {
+ return this._image;
+ };
+ Texture.filterFromString = function (text) {
+ switch (text.toLowerCase()) {
+ case "nearest": return TextureFilter.Nearest;
+ case "linear": return TextureFilter.Linear;
+ case "mipmap": return TextureFilter.MipMap;
+ case "mipmapnearestnearest": return TextureFilter.MipMapNearestNearest;
+ case "mipmaplinearnearest": return TextureFilter.MipMapLinearNearest;
+ case "mipmapnearestlinear": return TextureFilter.MipMapNearestLinear;
+ case "mipmaplinearlinear": return TextureFilter.MipMapLinearLinear;
+ default: throw new Error("Unknown texture filter " + text);
+ }
+ };
+ Texture.wrapFromString = function (text) {
+ switch (text.toLowerCase()) {
+ case "mirroredtepeat": return TextureWrap.MirroredRepeat;
+ case "clamptoedge": return TextureWrap.ClampToEdge;
+ case "repeat": return TextureWrap.Repeat;
+ default: throw new Error("Unknown texture wrap " + text);
+ }
+ };
+ return Texture;
+ }());
+ spine.Texture = Texture;
+ var TextureFilter;
+ (function (TextureFilter) {
+ TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest";
+ TextureFilter[TextureFilter["Linear"] = 9729] = "Linear";
+ TextureFilter[TextureFilter["MipMap"] = 9987] = "MipMap";
+ TextureFilter[TextureFilter["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest";
+ TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest";
+ TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear";
+ TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear";
+ })(TextureFilter = spine.TextureFilter || (spine.TextureFilter = {}));
+ var TextureWrap;
+ (function (TextureWrap) {
+ TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat";
+ TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge";
+ TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat";
+ })(TextureWrap = spine.TextureWrap || (spine.TextureWrap = {}));
+ var TextureRegion = (function () {
+ function TextureRegion() {
+ this.u = 0;
+ this.v = 0;
+ this.u2 = 0;
+ this.v2 = 0;
+ this.width = 0;
+ this.height = 0;
+ this.rotate = false;
+ this.offsetX = 0;
+ this.offsetY = 0;
+ this.originalWidth = 0;
+ this.originalHeight = 0;
+ }
+ return TextureRegion;
+ }());
+ spine.TextureRegion = TextureRegion;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var TextureAtlas = (function () {
+ function TextureAtlas(atlasText, textureLoader) {
+ this.pages = new Array();
+ this.regions = new Array();
+ this.load(atlasText, textureLoader);
+ }
+ TextureAtlas.prototype.load = function (atlasText, textureLoader) {
+ if (textureLoader == null)
+ throw new Error("textureLoader cannot be null.");
+ var reader = new TextureAtlasReader(atlasText);
+ var tuple = new Array(4);
+ var page = null;
+ while (true) {
+ var line = reader.readLine();
+ if (line == null)
+ break;
+ line = line.trim();
+ if (line.length == 0)
+ page = null;
+ else if (!page) {
+ page = new TextureAtlasPage();
+ page.name = line;
+ if (reader.readTuple(tuple) == 2) {
+ page.width = parseInt(tuple[0]);
+ page.height = parseInt(tuple[1]);
+ reader.readTuple(tuple);
+ }
+ reader.readTuple(tuple);
+ page.minFilter = spine.Texture.filterFromString(tuple[0]);
+ page.magFilter = spine.Texture.filterFromString(tuple[1]);
+ var direction = reader.readValue();
+ page.uWrap = spine.TextureWrap.ClampToEdge;
+ page.vWrap = spine.TextureWrap.ClampToEdge;
+ if (direction == "x")
+ page.uWrap = spine.TextureWrap.Repeat;
+ else if (direction == "y")
+ page.vWrap = spine.TextureWrap.Repeat;
+ else if (direction == "xy")
+ page.uWrap = page.vWrap = spine.TextureWrap.Repeat;
+ page.texture = textureLoader(line);
+ page.texture.setFilters(page.minFilter, page.magFilter);
+ page.texture.setWraps(page.uWrap, page.vWrap);
+ page.width = page.texture.getImage().width;
+ page.height = page.texture.getImage().height;
+ this.pages.push(page);
+ }
+ else {
+ var region = new TextureAtlasRegion();
+ 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) {
+ if (reader.readTuple(tuple) == 4) {
+ 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());
+ region.texture = page.texture;
+ this.regions.push(region);
+ }
+ }
+ };
+ TextureAtlas.prototype.findRegion = function (name) {
+ for (var i = 0; i < this.regions.length; i++) {
+ if (this.regions[i].name == name) {
+ return this.regions[i];
+ }
+ }
+ return null;
+ };
+ TextureAtlas.prototype.dispose = function () {
+ for (var i = 0; i < this.pages.length; i++) {
+ this.pages[i].texture.dispose();
+ }
+ };
+ return TextureAtlas;
+ }());
+ spine.TextureAtlas = TextureAtlas;
+ var TextureAtlasReader = (function () {
+ function TextureAtlasReader(text) {
+ this.index = 0;
+ this.lines = text.split(/\r\n|\r|\n/);
+ }
+ TextureAtlasReader.prototype.readLine = function () {
+ if (this.index >= this.lines.length)
+ return null;
+ return this.lines[this.index++];
+ };
+ TextureAtlasReader.prototype.readValue = function () {
+ var line = this.readLine();
+ var colon = line.indexOf(":");
+ if (colon == -1)
+ throw new Error("Invalid line: " + line);
+ return line.substring(colon + 1).trim();
+ };
+ TextureAtlasReader.prototype.readTuple = function (tuple) {
+ var line = this.readLine();
+ var colon = line.indexOf(":");
+ if (colon == -1)
+ throw new Error("Invalid line: " + line);
+ var i = 0, lastMatch = colon + 1;
+ for (; i < 3; i++) {
+ var comma = line.indexOf(",", lastMatch);
+ if (comma == -1)
+ break;
+ tuple[i] = line.substr(lastMatch, comma - lastMatch).trim();
+ lastMatch = comma + 1;
+ }
+ tuple[i] = line.substring(lastMatch).trim();
+ return i + 1;
+ };
+ return TextureAtlasReader;
+ }());
+ var TextureAtlasPage = (function () {
+ function TextureAtlasPage() {
+ }
+ return TextureAtlasPage;
+ }());
+ spine.TextureAtlasPage = TextureAtlasPage;
+ var TextureAtlasRegion = (function (_super) {
+ __extends(TextureAtlasRegion, _super);
+ function TextureAtlasRegion() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return TextureAtlasRegion;
+ }(spine.TextureRegion));
+ spine.TextureAtlasRegion = TextureAtlasRegion;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var TransformConstraint = (function () {
+ function TransformConstraint(data, skeleton) {
+ this.rotateMix = 0;
+ this.translateMix = 0;
+ this.scaleMix = 0;
+ this.shearMix = 0;
+ this.temp = new spine.Vector2();
+ if (data == null)
+ throw new Error("data cannot be null.");
+ if (skeleton == null)
+ throw new Error("skeleton cannot be null.");
+ this.data = data;
+ this.rotateMix = data.rotateMix;
+ this.translateMix = data.translateMix;
+ this.scaleMix = data.scaleMix;
+ this.shearMix = data.shearMix;
+ this.bones = new Array();
+ for (var i = 0; i < data.bones.length; i++)
+ this.bones.push(skeleton.findBone(data.bones[i].name));
+ this.target = skeleton.findBone(data.target.name);
+ }
+ TransformConstraint.prototype.apply = function () {
+ this.update();
+ };
+ TransformConstraint.prototype.update = function () {
+ if (this.data.local) {
+ if (this.data.relative)
+ this.applyRelativeLocal();
+ else
+ this.applyAbsoluteLocal();
+ }
+ else {
+ if (this.data.relative)
+ this.applyRelativeWorld();
+ else
+ this.applyAbsoluteWorld();
+ }
+ };
+ TransformConstraint.prototype.applyAbsoluteWorld = function () {
+ var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+ var target = this.target;
+ var ta = target.a, tb = target.b, tc = target.c, td = target.d;
+ var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad;
+ var offsetRotation = this.data.offsetRotation * degRadReflect;
+ var offsetShearY = this.data.offsetShearY * degRadReflect;
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ var modified = false;
+ if (rotateMix != 0) {
+ var a = bone.a, b = bone.b, c = bone.c, d = bone.d;
+ var r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation;
+ if (r > spine.MathUtils.PI)
+ r -= spine.MathUtils.PI2;
+ else if (r < -spine.MathUtils.PI)
+ r += spine.MathUtils.PI2;
+ r *= rotateMix;
+ var cos = Math.cos(r), sin = Math.sin(r);
+ bone.a = cos * a - sin * c;
+ bone.b = cos * b - sin * d;
+ bone.c = sin * a + cos * c;
+ bone.d = sin * b + cos * d;
+ modified = true;
+ }
+ if (translateMix != 0) {
+ var temp = this.temp;
+ target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));
+ bone.worldX += (temp.x - bone.worldX) * translateMix;
+ bone.worldY += (temp.y - bone.worldY) * translateMix;
+ modified = true;
+ }
+ if (scaleMix > 0) {
+ var s = Math.sqrt(bone.a * bone.a + bone.c * bone.c);
+ var ts = Math.sqrt(ta * ta + tc * tc);
+ if (s > 0.00001)
+ s = (s + (ts - s + this.data.offsetScaleX) * scaleMix) / s;
+ bone.a *= s;
+ bone.c *= s;
+ s = Math.sqrt(bone.b * bone.b + bone.d * bone.d);
+ ts = Math.sqrt(tb * tb + td * td);
+ if (s > 0.00001)
+ s = (s + (ts - s + this.data.offsetScaleY) * scaleMix) / s;
+ bone.b *= s;
+ bone.d *= s;
+ modified = true;
+ }
+ if (shearMix > 0) {
+ var b = bone.b, d = bone.d;
+ var by = Math.atan2(d, b);
+ var r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a));
+ if (r > spine.MathUtils.PI)
+ r -= spine.MathUtils.PI2;
+ else if (r < -spine.MathUtils.PI)
+ r += spine.MathUtils.PI2;
+ r = by + (r + offsetShearY) * shearMix;
+ var s = Math.sqrt(b * b + d * d);
+ bone.b = Math.cos(r) * s;
+ bone.d = Math.sin(r) * s;
+ modified = true;
+ }
+ if (modified)
+ bone.appliedValid = false;
+ }
+ };
+ TransformConstraint.prototype.applyRelativeWorld = function () {
+ var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+ var target = this.target;
+ var ta = target.a, tb = target.b, tc = target.c, td = target.d;
+ var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad;
+ var offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect;
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ var modified = false;
+ if (rotateMix != 0) {
+ var a = bone.a, b = bone.b, c = bone.c, d = bone.d;
+ var r = Math.atan2(tc, ta) + offsetRotation;
+ if (r > spine.MathUtils.PI)
+ r -= spine.MathUtils.PI2;
+ else if (r < -spine.MathUtils.PI)
+ r += spine.MathUtils.PI2;
+ r *= rotateMix;
+ var cos = Math.cos(r), sin = Math.sin(r);
+ bone.a = cos * a - sin * c;
+ bone.b = cos * b - sin * d;
+ bone.c = sin * a + cos * c;
+ bone.d = sin * b + cos * d;
+ modified = true;
+ }
+ if (translateMix != 0) {
+ var temp = this.temp;
+ target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));
+ bone.worldX += temp.x * translateMix;
+ bone.worldY += temp.y * translateMix;
+ modified = true;
+ }
+ if (scaleMix > 0) {
+ var s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1;
+ bone.a *= s;
+ bone.c *= s;
+ s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1;
+ bone.b *= s;
+ bone.d *= s;
+ modified = true;
+ }
+ if (shearMix > 0) {
+ var r = Math.atan2(td, tb) - Math.atan2(tc, ta);
+ if (r > spine.MathUtils.PI)
+ r -= spine.MathUtils.PI2;
+ else if (r < -spine.MathUtils.PI)
+ r += spine.MathUtils.PI2;
+ var b = bone.b, d = bone.d;
+ r = Math.atan2(d, b) + (r - spine.MathUtils.PI / 2 + offsetShearY) * shearMix;
+ var s = Math.sqrt(b * b + d * d);
+ bone.b = Math.cos(r) * s;
+ bone.d = Math.sin(r) * s;
+ modified = true;
+ }
+ if (modified)
+ bone.appliedValid = false;
+ }
+ };
+ TransformConstraint.prototype.applyAbsoluteLocal = function () {
+ var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+ var target = this.target;
+ if (!target.appliedValid)
+ target.updateAppliedTransform();
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ if (!bone.appliedValid)
+ bone.updateAppliedTransform();
+ var rotation = bone.arotation;
+ if (rotateMix != 0) {
+ var r = target.arotation - rotation + this.data.offsetRotation;
+ r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
+ rotation += r * rotateMix;
+ }
+ var x = bone.ax, y = bone.ay;
+ if (translateMix != 0) {
+ x += (target.ax - x + this.data.offsetX) * translateMix;
+ y += (target.ay - y + this.data.offsetY) * translateMix;
+ }
+ var scaleX = bone.ascaleX, scaleY = bone.ascaleY;
+ if (scaleMix > 0) {
+ if (scaleX > 0.00001)
+ scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX;
+ if (scaleY > 0.00001)
+ scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY;
+ }
+ var shearY = bone.ashearY;
+ if (shearMix > 0) {
+ var r = target.ashearY - shearY + this.data.offsetShearY;
+ r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360;
+ bone.shearY += r * shearMix;
+ }
+ bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
+ }
+ };
+ TransformConstraint.prototype.applyRelativeLocal = function () {
+ var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix;
+ var target = this.target;
+ if (!target.appliedValid)
+ target.updateAppliedTransform();
+ var bones = this.bones;
+ for (var i = 0, n = bones.length; i < n; i++) {
+ var bone = bones[i];
+ if (!bone.appliedValid)
+ bone.updateAppliedTransform();
+ var rotation = bone.arotation;
+ if (rotateMix != 0)
+ rotation += (target.arotation + this.data.offsetRotation) * rotateMix;
+ var x = bone.ax, y = bone.ay;
+ if (translateMix != 0) {
+ x += (target.ax + this.data.offsetX) * translateMix;
+ y += (target.ay + this.data.offsetY) * translateMix;
+ }
+ var scaleX = bone.ascaleX, scaleY = bone.ascaleY;
+ if (scaleMix > 0) {
+ if (scaleX > 0.00001)
+ scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1;
+ if (scaleY > 0.00001)
+ scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1;
+ }
+ var shearY = bone.ashearY;
+ if (shearMix > 0)
+ shearY += (target.ashearY + this.data.offsetShearY) * shearMix;
+ bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
+ }
+ };
+ TransformConstraint.prototype.getOrder = function () {
+ return this.data.order;
+ };
+ return TransformConstraint;
+ }());
+ spine.TransformConstraint = TransformConstraint;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var TransformConstraintData = (function () {
+ function TransformConstraintData(name) {
+ this.order = 0;
+ this.bones = new Array();
+ this.rotateMix = 0;
+ this.translateMix = 0;
+ this.scaleMix = 0;
+ this.shearMix = 0;
+ this.offsetRotation = 0;
+ this.offsetX = 0;
+ this.offsetY = 0;
+ this.offsetScaleX = 0;
+ this.offsetScaleY = 0;
+ this.offsetShearY = 0;
+ this.relative = false;
+ this.local = false;
+ if (name == null)
+ throw new Error("name cannot be null.");
+ this.name = name;
+ }
+ return TransformConstraintData;
+ }());
+ spine.TransformConstraintData = TransformConstraintData;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Triangulator = (function () {
+ function Triangulator() {
+ this.convexPolygons = new Array();
+ this.convexPolygonsIndices = new Array();
+ this.indicesArray = new Array();
+ this.isConcaveArray = new Array();
+ this.triangles = new Array();
+ this.polygonPool = new spine.Pool(function () {
+ return new Array();
+ });
+ this.polygonIndicesPool = new spine.Pool(function () {
+ return new Array();
+ });
+ }
+ Triangulator.prototype.triangulate = function (verticesArray) {
+ var vertices = verticesArray;
+ var vertexCount = verticesArray.length >> 1;
+ var indices = this.indicesArray;
+ indices.length = 0;
+ for (var i = 0; i < vertexCount; i++)
+ indices[i] = i;
+ var isConcave = this.isConcaveArray;
+ isConcave.length = 0;
+ for (var i = 0, n = vertexCount; i < n; ++i)
+ isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices);
+ var triangles = this.triangles;
+ triangles.length = 0;
+ while (vertexCount > 3) {
+ var previous = vertexCount - 1, i = 0, next = 1;
+ while (true) {
+ outer: if (!isConcave[i]) {
+ var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
+ var p1x = vertices[p1], p1y = vertices[p1 + 1];
+ var p2x = vertices[p2], p2y = vertices[p2 + 1];
+ var p3x = vertices[p3], p3y = vertices[p3 + 1];
+ for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
+ if (!isConcave[ii])
+ continue;
+ var v = indices[ii] << 1;
+ var vx = vertices[v], vy = vertices[v + 1];
+ if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
+ if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
+ if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
+ break outer;
+ }
+ }
+ }
+ break;
+ }
+ if (next == 0) {
+ do {
+ if (!isConcave[i])
+ break;
+ i--;
+ } while (i > 0);
+ break;
+ }
+ previous = i;
+ i = next;
+ next = (next + 1) % vertexCount;
+ }
+ triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
+ triangles.push(indices[i]);
+ triangles.push(indices[(i + 1) % vertexCount]);
+ indices.splice(i, 1);
+ isConcave.splice(i, 1);
+ vertexCount--;
+ var previousIndex = (vertexCount + i - 1) % vertexCount;
+ var nextIndex = i == vertexCount ? 0 : i;
+ isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices);
+ isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices);
+ }
+ if (vertexCount == 3) {
+ triangles.push(indices[2]);
+ triangles.push(indices[0]);
+ triangles.push(indices[1]);
+ }
+ return triangles;
+ };
+ Triangulator.prototype.decompose = function (verticesArray, triangles) {
+ var vertices = verticesArray;
+ var convexPolygons = this.convexPolygons;
+ this.polygonPool.freeAll(convexPolygons);
+ convexPolygons.length = 0;
+ var convexPolygonsIndices = this.convexPolygonsIndices;
+ this.polygonIndicesPool.freeAll(convexPolygonsIndices);
+ convexPolygonsIndices.length = 0;
+ var polygonIndices = this.polygonIndicesPool.obtain();
+ polygonIndices.length = 0;
+ var polygon = this.polygonPool.obtain();
+ polygon.length = 0;
+ var fanBaseIndex = -1, lastWinding = 0;
+ for (var i = 0, n = triangles.length; i < n; i += 3) {
+ var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
+ var x1 = vertices[t1], y1 = vertices[t1 + 1];
+ var x2 = vertices[t2], y2 = vertices[t2 + 1];
+ var x3 = vertices[t3], y3 = vertices[t3 + 1];
+ var merged = false;
+ if (fanBaseIndex == t1) {
+ var o = polygon.length - 4;
+ var winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
+ var winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
+ if (winding1 == lastWinding && winding2 == lastWinding) {
+ polygon.push(x3);
+ polygon.push(y3);
+ polygonIndices.push(t3);
+ merged = true;
+ }
+ }
+ if (!merged) {
+ if (polygon.length > 0) {
+ convexPolygons.push(polygon);
+ convexPolygonsIndices.push(polygonIndices);
+ }
+ else {
+ this.polygonPool.free(polygon);
+ this.polygonIndicesPool.free(polygonIndices);
+ }
+ polygon = this.polygonPool.obtain();
+ polygon.length = 0;
+ polygon.push(x1);
+ polygon.push(y1);
+ polygon.push(x2);
+ polygon.push(y2);
+ polygon.push(x3);
+ polygon.push(y3);
+ polygonIndices = this.polygonIndicesPool.obtain();
+ polygonIndices.length = 0;
+ polygonIndices.push(t1);
+ polygonIndices.push(t2);
+ polygonIndices.push(t3);
+ lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3);
+ fanBaseIndex = t1;
+ }
+ }
+ if (polygon.length > 0) {
+ convexPolygons.push(polygon);
+ convexPolygonsIndices.push(polygonIndices);
+ }
+ for (var i = 0, n = convexPolygons.length; i < n; i++) {
+ polygonIndices = convexPolygonsIndices[i];
+ if (polygonIndices.length == 0)
+ continue;
+ var firstIndex = polygonIndices[0];
+ var lastIndex = polygonIndices[polygonIndices.length - 1];
+ polygon = convexPolygons[i];
+ var o = polygon.length - 4;
+ var prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
+ var prevX = polygon[o + 2], prevY = polygon[o + 3];
+ var firstX = polygon[0], firstY = polygon[1];
+ var secondX = polygon[2], secondY = polygon[3];
+ var winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
+ for (var ii = 0; ii < n; ii++) {
+ if (ii == i)
+ continue;
+ var otherIndices = convexPolygonsIndices[ii];
+ if (otherIndices.length != 3)
+ continue;
+ var otherFirstIndex = otherIndices[0];
+ var otherSecondIndex = otherIndices[1];
+ var otherLastIndex = otherIndices[2];
+ var otherPoly = convexPolygons[ii];
+ var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
+ if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
+ continue;
+ var winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
+ var winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY);
+ if (winding1 == winding && winding2 == winding) {
+ otherPoly.length = 0;
+ otherIndices.length = 0;
+ polygon.push(x3);
+ polygon.push(y3);
+ polygonIndices.push(otherLastIndex);
+ prevPrevX = prevX;
+ prevPrevY = prevY;
+ prevX = x3;
+ prevY = y3;
+ ii = 0;
+ }
+ }
+ }
+ for (var i = convexPolygons.length - 1; i >= 0; i--) {
+ polygon = convexPolygons[i];
+ if (polygon.length == 0) {
+ convexPolygons.splice(i, 1);
+ this.polygonPool.free(polygon);
+ polygonIndices = convexPolygonsIndices[i];
+ convexPolygonsIndices.splice(i, 1);
+ this.polygonIndicesPool.free(polygonIndices);
+ }
+ }
+ return convexPolygons;
+ };
+ Triangulator.isConcave = function (index, vertexCount, vertices, indices) {
+ var previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
+ var current = indices[index] << 1;
+ var next = indices[(index + 1) % vertexCount] << 1;
+ return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]);
+ };
+ Triangulator.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) {
+ return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
+ };
+ Triangulator.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) {
+ var px = p2x - p1x, py = p2y - p1y;
+ return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
+ };
+ return Triangulator;
+ }());
+ spine.Triangulator = Triangulator;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var IntSet = (function () {
+ function IntSet() {
+ this.array = new Array();
+ }
+ IntSet.prototype.add = function (value) {
+ var contains = this.contains(value);
+ this.array[value | 0] = value | 0;
+ return !contains;
+ };
+ IntSet.prototype.contains = function (value) {
+ return this.array[value | 0] != undefined;
+ };
+ IntSet.prototype.remove = function (value) {
+ this.array[value | 0] = undefined;
+ };
+ IntSet.prototype.clear = function () {
+ this.array.length = 0;
+ };
+ return IntSet;
+ }());
+ spine.IntSet = IntSet;
+ var Color = (function () {
+ function Color(r, g, b, a) {
+ if (r === void 0) { r = 0; }
+ if (g === void 0) { g = 0; }
+ if (b === void 0) { b = 0; }
+ if (a === void 0) { a = 0; }
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ }
+ Color.prototype.set = function (r, g, b, a) {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ this.clamp();
+ return this;
+ };
+ Color.prototype.setFromColor = function (c) {
+ this.r = c.r;
+ this.g = c.g;
+ this.b = c.b;
+ this.a = c.a;
+ return this;
+ };
+ Color.prototype.setFromString = function (hex) {
+ hex = hex.charAt(0) == '#' ? hex.substr(1) : hex;
+ this.r = parseInt(hex.substr(0, 2), 16) / 255.0;
+ this.g = parseInt(hex.substr(2, 2), 16) / 255.0;
+ this.b = parseInt(hex.substr(4, 2), 16) / 255.0;
+ this.a = (hex.length != 8 ? 255 : parseInt(hex.substr(6, 2), 16)) / 255.0;
+ return this;
+ };
+ Color.prototype.add = function (r, g, b, a) {
+ this.r += r;
+ this.g += g;
+ this.b += b;
+ this.a += a;
+ this.clamp();
+ return this;
+ };
+ Color.prototype.clamp = function () {
+ if (this.r < 0)
+ this.r = 0;
+ else if (this.r > 1)
+ this.r = 1;
+ if (this.g < 0)
+ this.g = 0;
+ else if (this.g > 1)
+ this.g = 1;
+ if (this.b < 0)
+ this.b = 0;
+ else if (this.b > 1)
+ this.b = 1;
+ if (this.a < 0)
+ this.a = 0;
+ else if (this.a > 1)
+ this.a = 1;
+ return this;
+ };
+ return Color;
+ }());
+ Color.WHITE = new Color(1, 1, 1, 1);
+ Color.RED = new Color(1, 0, 0, 1);
+ Color.GREEN = new Color(0, 1, 0, 1);
+ Color.BLUE = new Color(0, 0, 1, 1);
+ Color.MAGENTA = new Color(1, 0, 1, 1);
+ spine.Color = Color;
+ var MathUtils = (function () {
+ function MathUtils() {
+ }
+ MathUtils.clamp = function (value, min, max) {
+ if (value < min)
+ return min;
+ if (value > max)
+ return max;
+ return value;
+ };
+ MathUtils.cosDeg = function (degrees) {
+ return Math.cos(degrees * MathUtils.degRad);
+ };
+ MathUtils.sinDeg = function (degrees) {
+ return Math.sin(degrees * MathUtils.degRad);
+ };
+ MathUtils.signum = function (value) {
+ return value > 0 ? 1 : value < 0 ? -1 : 0;
+ };
+ MathUtils.toInt = function (x) {
+ return x > 0 ? Math.floor(x) : Math.ceil(x);
+ };
+ MathUtils.cbrt = function (x) {
+ var y = Math.pow(Math.abs(x), 1 / 3);
+ return x < 0 ? -y : y;
+ };
+ MathUtils.randomTriangular = function (min, max) {
+ return MathUtils.randomTriangularWith(min, max, (min + max) * 0.5);
+ };
+ MathUtils.randomTriangularWith = function (min, max, mode) {
+ var u = Math.random();
+ var d = max - min;
+ if (u <= (mode - min) / d)
+ return min + Math.sqrt(u * d * (mode - min));
+ return max - Math.sqrt((1 - u) * d * (max - mode));
+ };
+ return MathUtils;
+ }());
+ MathUtils.PI = 3.1415927;
+ MathUtils.PI2 = MathUtils.PI * 2;
+ MathUtils.radiansToDegrees = 180 / MathUtils.PI;
+ MathUtils.radDeg = MathUtils.radiansToDegrees;
+ MathUtils.degreesToRadians = MathUtils.PI / 180;
+ MathUtils.degRad = MathUtils.degreesToRadians;
+ spine.MathUtils = MathUtils;
+ var Interpolation = (function () {
+ function Interpolation() {
+ }
+ Interpolation.prototype.apply = function (start, end, a) {
+ return start + (end - start) * this.applyInternal(a);
+ };
+ return Interpolation;
+ }());
+ spine.Interpolation = Interpolation;
+ var Pow = (function (_super) {
+ __extends(Pow, _super);
+ function Pow(power) {
+ var _this = _super.call(this) || this;
+ _this.power = 2;
+ _this.power = power;
+ return _this;
+ }
+ Pow.prototype.applyInternal = function (a) {
+ if (a <= 0.5)
+ return Math.pow(a * 2, this.power) / 2;
+ return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1;
+ };
+ return Pow;
+ }(Interpolation));
+ spine.Pow = Pow;
+ var PowOut = (function (_super) {
+ __extends(PowOut, _super);
+ function PowOut(power) {
+ return _super.call(this, power) || this;
+ }
+ PowOut.prototype.applyInternal = function (a) {
+ return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1;
+ };
+ return PowOut;
+ }(Pow));
+ spine.PowOut = PowOut;
+ var Utils = (function () {
+ function Utils() {
+ }
+ Utils.arrayCopy = function (source, sourceStart, dest, destStart, numElements) {
+ for (var i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) {
+ dest[j] = source[i];
+ }
+ };
+ Utils.setArraySize = function (array, size, value) {
+ if (value === void 0) { value = 0; }
+ var oldSize = array.length;
+ if (oldSize == size)
+ return array;
+ array.length = size;
+ if (oldSize < size) {
+ for (var i = oldSize; i < size; i++)
+ array[i] = value;
+ }
+ return array;
+ };
+ Utils.ensureArrayCapacity = function (array, size, value) {
+ if (value === void 0) { value = 0; }
+ if (array.length >= size)
+ return array;
+ return Utils.setArraySize(array, size, value);
+ };
+ Utils.newArray = function (size, defaultValue) {
+ var array = new Array(size);
+ for (var i = 0; i < size; i++)
+ array[i] = defaultValue;
+ return array;
+ };
+ Utils.newFloatArray = function (size) {
+ if (Utils.SUPPORTS_TYPED_ARRAYS) {
+ return new Float32Array(size);
+ }
+ else {
+ var array = new Array(size);
+ for (var i = 0; i < array.length; i++)
+ array[i] = 0;
+ return array;
+ }
+ };
+ Utils.newShortArray = function (size) {
+ if (Utils.SUPPORTS_TYPED_ARRAYS) {
+ return new Int16Array(size);
+ }
+ else {
+ var array = new Array(size);
+ for (var i = 0; i < array.length; i++)
+ array[i] = 0;
+ return array;
+ }
+ };
+ Utils.toFloatArray = function (array) {
+ return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
+ };
+ Utils.toSinglePrecision = function (value) {
+ return Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value;
+ };
+ return Utils;
+ }());
+ Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined";
+ spine.Utils = Utils;
+ var DebugUtils = (function () {
+ function DebugUtils() {
+ }
+ DebugUtils.logBones = function (skeleton) {
+ for (var i = 0; i < skeleton.bones.length; i++) {
+ var bone = skeleton.bones[i];
+ console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY);
+ }
+ };
+ return DebugUtils;
+ }());
+ spine.DebugUtils = DebugUtils;
+ var Pool = (function () {
+ function Pool(instantiator) {
+ this.items = new Array();
+ this.instantiator = instantiator;
+ }
+ Pool.prototype.obtain = function () {
+ return this.items.length > 0 ? this.items.pop() : this.instantiator();
+ };
+ Pool.prototype.free = function (item) {
+ if (item.reset)
+ item.reset();
+ this.items.push(item);
+ };
+ Pool.prototype.freeAll = function (items) {
+ for (var i = 0; i < items.length; i++) {
+ if (items[i].reset)
+ items[i].reset();
+ this.items[i] = items[i];
+ }
+ };
+ Pool.prototype.clear = function () {
+ this.items.length = 0;
+ };
+ return Pool;
+ }());
+ spine.Pool = Pool;
+ var Vector2 = (function () {
+ function Vector2(x, y) {
+ if (x === void 0) { x = 0; }
+ if (y === void 0) { y = 0; }
+ this.x = x;
+ this.y = y;
+ }
+ Vector2.prototype.set = function (x, y) {
+ this.x = x;
+ this.y = y;
+ return this;
+ };
+ Vector2.prototype.length = function () {
+ var x = this.x;
+ var y = this.y;
+ return Math.sqrt(x * x + y * y);
+ };
+ Vector2.prototype.normalize = function () {
+ var len = this.length();
+ if (len != 0) {
+ this.x /= len;
+ this.y /= len;
+ }
+ return this;
+ };
+ return Vector2;
+ }());
+ spine.Vector2 = Vector2;
+ var TimeKeeper = (function () {
+ function TimeKeeper() {
+ this.maxDelta = 0.064;
+ this.framesPerSecond = 0;
+ this.delta = 0;
+ this.totalTime = 0;
+ this.lastTime = Date.now() / 1000;
+ this.frameCount = 0;
+ this.frameTime = 0;
+ }
+ TimeKeeper.prototype.update = function () {
+ var now = Date.now() / 1000;
+ this.delta = now - this.lastTime;
+ this.frameTime += this.delta;
+ this.totalTime += this.delta;
+ if (this.delta > this.maxDelta)
+ this.delta = this.maxDelta;
+ this.lastTime = now;
+ this.frameCount++;
+ if (this.frameTime > 1) {
+ this.framesPerSecond = this.frameCount / this.frameTime;
+ this.frameTime = 0;
+ this.frameCount = 0;
+ }
+ };
+ return TimeKeeper;
+ }());
+ spine.TimeKeeper = TimeKeeper;
+ var WindowedMean = (function () {
+ function WindowedMean(windowSize) {
+ if (windowSize === void 0) { windowSize = 32; }
+ this.addedValues = 0;
+ this.lastValue = 0;
+ this.mean = 0;
+ this.dirty = true;
+ this.values = new Array(windowSize);
+ }
+ WindowedMean.prototype.hasEnoughData = function () {
+ return this.addedValues >= this.values.length;
+ };
+ WindowedMean.prototype.addValue = function (value) {
+ if (this.addedValues < this.values.length)
+ this.addedValues++;
+ this.values[this.lastValue++] = value;
+ if (this.lastValue > this.values.length - 1)
+ this.lastValue = 0;
+ this.dirty = true;
+ };
+ WindowedMean.prototype.getMean = function () {
+ if (this.hasEnoughData()) {
+ if (this.dirty) {
+ var mean = 0;
+ for (var i = 0; i < this.values.length; i++) {
+ mean += this.values[i];
+ }
+ this.mean = mean / this.values.length;
+ this.dirty = false;
+ }
+ return this.mean;
+ }
+ else {
+ return 0;
+ }
+ };
+ return WindowedMean;
+ }());
+ spine.WindowedMean = WindowedMean;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var Attachment = (function () {
+ function Attachment(name) {
+ if (name == null)
+ throw new Error("name cannot be null.");
+ this.name = name;
+ }
+ return Attachment;
+ }());
+ spine.Attachment = Attachment;
+ var VertexAttachment = (function (_super) {
+ __extends(VertexAttachment, _super);
+ function VertexAttachment(name) {
+ var _this = _super.call(this, name) || this;
+ _this.id = (VertexAttachment.nextID++ & 65535) << 11;
+ _this.worldVerticesLength = 0;
+ return _this;
+ }
+ VertexAttachment.prototype.computeWorldVertices = function (slot, start, count, worldVertices, offset, stride) {
+ count = offset + (count >> 1) * stride;
+ var skeleton = slot.bone.skeleton;
+ var deformArray = slot.attachmentVertices;
+ var vertices = this.vertices;
+ var bones = this.bones;
+ if (bones == null) {
+ if (deformArray.length > 0)
+ vertices = deformArray;
+ var bone = slot.bone;
+ var x = bone.worldX;
+ var y = bone.worldY;
+ var a = bone.a, b = bone.b, c = bone.c, d = bone.d;
+ for (var v_1 = start, w = offset; w < count; v_1 += 2, w += stride) {
+ var vx = vertices[v_1], vy = vertices[v_1 + 1];
+ worldVertices[w] = vx * a + vy * b + x;
+ worldVertices[w + 1] = vx * c + vy * d + y;
+ }
+ return;
+ }
+ var v = 0, skip = 0;
+ for (var i = 0; i < start; i += 2) {
+ var n = bones[v];
+ v += n + 1;
+ skip += n;
+ }
+ var skeletonBones = skeleton.bones;
+ if (deformArray.length == 0) {
+ for (var w = offset, b = skip * 3; w < count; w += stride) {
+ var wx = 0, wy = 0;
+ var n = bones[v++];
+ n += v;
+ for (; v < n; v++, b += 3) {
+ var bone = skeletonBones[bones[v]];
+ var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
+ wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
+ wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
+ }
+ worldVertices[w] = wx;
+ worldVertices[w + 1] = wy;
+ }
+ }
+ else {
+ var deform = deformArray;
+ for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {
+ var wx = 0, wy = 0;
+ var n = bones[v++];
+ n += v;
+ for (; v < n; v++, b += 3, f += 2) {
+ var bone = skeletonBones[bones[v]];
+ var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
+ wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
+ wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
+ }
+ worldVertices[w] = wx;
+ worldVertices[w + 1] = wy;
+ }
+ }
+ };
+ VertexAttachment.prototype.applyDeform = function (sourceAttachment) {
+ return this == sourceAttachment;
+ };
+ return VertexAttachment;
+ }(Attachment));
+ VertexAttachment.nextID = 0;
+ spine.VertexAttachment = VertexAttachment;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var AttachmentType;
+ (function (AttachmentType) {
+ AttachmentType[AttachmentType["Region"] = 0] = "Region";
+ AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox";
+ AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh";
+ AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh";
+ AttachmentType[AttachmentType["Path"] = 4] = "Path";
+ AttachmentType[AttachmentType["Point"] = 5] = "Point";
+ })(AttachmentType = spine.AttachmentType || (spine.AttachmentType = {}));
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var BoundingBoxAttachment = (function (_super) {
+ __extends(BoundingBoxAttachment, _super);
+ function BoundingBoxAttachment(name) {
+ var _this = _super.call(this, name) || this;
+ _this.color = new spine.Color(1, 1, 1, 1);
+ return _this;
+ }
+ return BoundingBoxAttachment;
+ }(spine.VertexAttachment));
+ spine.BoundingBoxAttachment = BoundingBoxAttachment;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var ClippingAttachment = (function (_super) {
+ __extends(ClippingAttachment, _super);
+ function ClippingAttachment(name) {
+ var _this = _super.call(this, name) || this;
+ _this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1);
+ return _this;
+ }
+ return ClippingAttachment;
+ }(spine.VertexAttachment));
+ spine.ClippingAttachment = ClippingAttachment;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var MeshAttachment = (function (_super) {
+ __extends(MeshAttachment, _super);
+ function MeshAttachment(name) {
+ var _this = _super.call(this, name) || this;
+ _this.color = new spine.Color(1, 1, 1, 1);
+ _this.inheritDeform = false;
+ _this.tempColor = new spine.Color(0, 0, 0, 0);
+ return _this;
+ }
+ MeshAttachment.prototype.updateUVs = function () {
+ var u = 0, v = 0, width = 0, height = 0;
+ if (this.region == null) {
+ u = v = 0;
+ width = height = 1;
+ }
+ else {
+ u = this.region.u;
+ v = this.region.v;
+ width = this.region.u2 - u;
+ height = this.region.v2 - v;
+ }
+ var regionUVs = this.regionUVs;
+ if (this.uvs == null || this.uvs.length != regionUVs.length)
+ this.uvs = spine.Utils.newFloatArray(regionUVs.length);
+ var uvs = this.uvs;
+ if (this.region.rotate) {
+ for (var i = 0, n = uvs.length; i < n; i += 2) {
+ uvs[i] = u + regionUVs[i + 1] * width;
+ uvs[i + 1] = v + height - regionUVs[i] * height;
+ }
+ }
+ else {
+ for (var i = 0, n = uvs.length; i < n; i += 2) {
+ uvs[i] = u + regionUVs[i] * width;
+ uvs[i + 1] = v + regionUVs[i + 1] * height;
+ }
+ }
+ };
+ MeshAttachment.prototype.applyDeform = function (sourceAttachment) {
+ return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment);
+ };
+ MeshAttachment.prototype.getParentMesh = function () {
+ return this.parentMesh;
+ };
+ MeshAttachment.prototype.setParentMesh = function (parentMesh) {
+ this.parentMesh = parentMesh;
+ if (parentMesh != null) {
+ this.bones = parentMesh.bones;
+ this.vertices = parentMesh.vertices;
+ this.worldVerticesLength = parentMesh.worldVerticesLength;
+ this.regionUVs = parentMesh.regionUVs;
+ this.triangles = parentMesh.triangles;
+ this.hullLength = parentMesh.hullLength;
+ this.worldVerticesLength = parentMesh.worldVerticesLength;
+ }
+ };
+ return MeshAttachment;
+ }(spine.VertexAttachment));
+ spine.MeshAttachment = MeshAttachment;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var PathAttachment = (function (_super) {
+ __extends(PathAttachment, _super);
+ function PathAttachment(name) {
+ var _this = _super.call(this, name) || this;
+ _this.closed = false;
+ _this.constantSpeed = false;
+ _this.color = new spine.Color(1, 1, 1, 1);
+ return _this;
+ }
+ return PathAttachment;
+ }(spine.VertexAttachment));
+ spine.PathAttachment = PathAttachment;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var PointAttachment = (function (_super) {
+ __extends(PointAttachment, _super);
+ function PointAttachment(name) {
+ var _this = _super.call(this, name) || this;
+ _this.color = new spine.Color(0.38, 0.94, 0, 1);
+ return _this;
+ }
+ PointAttachment.prototype.computeWorldPosition = function (bone, point) {
+ point.x = this.x * bone.a + this.y * bone.b + bone.worldX;
+ point.y = this.x * bone.c + this.y * bone.d + bone.worldY;
+ return point;
+ };
+ PointAttachment.prototype.computeWorldRotation = function (bone) {
+ var cos = spine.MathUtils.cosDeg(this.rotation), sin = spine.MathUtils.sinDeg(this.rotation);
+ var x = cos * bone.a + sin * bone.b;
+ var y = cos * bone.c + sin * bone.d;
+ return Math.atan2(y, x) * spine.MathUtils.radDeg;
+ };
+ return PointAttachment;
+ }(spine.VertexAttachment));
+ spine.PointAttachment = PointAttachment;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var RegionAttachment = (function (_super) {
+ __extends(RegionAttachment, _super);
+ function RegionAttachment(name) {
+ var _this = _super.call(this, name) || this;
+ _this.x = 0;
+ _this.y = 0;
+ _this.scaleX = 1;
+ _this.scaleY = 1;
+ _this.rotation = 0;
+ _this.width = 0;
+ _this.height = 0;
+ _this.color = new spine.Color(1, 1, 1, 1);
+ _this.offset = spine.Utils.newFloatArray(8);
+ _this.uvs = spine.Utils.newFloatArray(8);
+ _this.tempColor = new spine.Color(1, 1, 1, 1);
+ return _this;
+ }
+ RegionAttachment.prototype.updateOffset = function () {
+ var regionScaleX = this.width / this.region.originalWidth * this.scaleX;
+ var regionScaleY = this.height / this.region.originalHeight * this.scaleY;
+ var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX;
+ var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY;
+ var localX2 = localX + this.region.width * regionScaleX;
+ var localY2 = localY + this.region.height * 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[RegionAttachment.OX1] = localXCos - localYSin;
+ offset[RegionAttachment.OY1] = localYCos + localXSin;
+ offset[RegionAttachment.OX2] = localXCos - localY2Sin;
+ offset[RegionAttachment.OY2] = localY2Cos + localXSin;
+ offset[RegionAttachment.OX3] = localX2Cos - localY2Sin;
+ offset[RegionAttachment.OY3] = localY2Cos + localX2Sin;
+ offset[RegionAttachment.OX4] = localX2Cos - localYSin;
+ offset[RegionAttachment.OY4] = localYCos + localX2Sin;
+ };
+ RegionAttachment.prototype.setRegion = function (region) {
+ this.region = region;
+ var uvs = this.uvs;
+ if (region.rotate) {
+ uvs[2] = region.u;
+ uvs[3] = region.v2;
+ uvs[4] = region.u;
+ uvs[5] = region.v;
+ uvs[6] = region.u2;
+ uvs[7] = region.v;
+ uvs[0] = region.u2;
+ uvs[1] = region.v2;
+ }
+ else {
+ uvs[0] = region.u;
+ uvs[1] = region.v2;
+ uvs[2] = region.u;
+ uvs[3] = region.v;
+ uvs[4] = region.u2;
+ uvs[5] = region.v;
+ uvs[6] = region.u2;
+ uvs[7] = region.v2;
+ }
+ };
+ RegionAttachment.prototype.computeWorldVertices = function (bone, worldVertices, offset, stride) {
+ var vertexOffset = this.offset;
+ var x = bone.worldX, y = bone.worldY;
+ var a = bone.a, b = bone.b, c = bone.c, d = bone.d;
+ var offsetX = 0, offsetY = 0;
+ offsetX = vertexOffset[RegionAttachment.OX1];
+ offsetY = vertexOffset[RegionAttachment.OY1];
+ worldVertices[offset] = offsetX * a + offsetY * b + x;
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
+ offset += stride;
+ offsetX = vertexOffset[RegionAttachment.OX2];
+ offsetY = vertexOffset[RegionAttachment.OY2];
+ worldVertices[offset] = offsetX * a + offsetY * b + x;
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
+ offset += stride;
+ offsetX = vertexOffset[RegionAttachment.OX3];
+ offsetY = vertexOffset[RegionAttachment.OY3];
+ worldVertices[offset] = offsetX * a + offsetY * b + x;
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
+ offset += stride;
+ offsetX = vertexOffset[RegionAttachment.OX4];
+ offsetY = vertexOffset[RegionAttachment.OY4];
+ worldVertices[offset] = offsetX * a + offsetY * b + x;
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
+ };
+ return RegionAttachment;
+ }(spine.Attachment));
+ RegionAttachment.OX1 = 0;
+ RegionAttachment.OY1 = 1;
+ RegionAttachment.OX2 = 2;
+ RegionAttachment.OY2 = 3;
+ RegionAttachment.OX3 = 4;
+ RegionAttachment.OY3 = 5;
+ RegionAttachment.OX4 = 6;
+ RegionAttachment.OY4 = 7;
+ RegionAttachment.X1 = 0;
+ RegionAttachment.Y1 = 1;
+ RegionAttachment.C1R = 2;
+ RegionAttachment.C1G = 3;
+ RegionAttachment.C1B = 4;
+ RegionAttachment.C1A = 5;
+ RegionAttachment.U1 = 6;
+ RegionAttachment.V1 = 7;
+ RegionAttachment.X2 = 8;
+ RegionAttachment.Y2 = 9;
+ RegionAttachment.C2R = 10;
+ RegionAttachment.C2G = 11;
+ RegionAttachment.C2B = 12;
+ RegionAttachment.C2A = 13;
+ RegionAttachment.U2 = 14;
+ RegionAttachment.V2 = 15;
+ RegionAttachment.X3 = 16;
+ RegionAttachment.Y3 = 17;
+ RegionAttachment.C3R = 18;
+ RegionAttachment.C3G = 19;
+ RegionAttachment.C3B = 20;
+ RegionAttachment.C3A = 21;
+ RegionAttachment.U3 = 22;
+ RegionAttachment.V3 = 23;
+ RegionAttachment.X4 = 24;
+ RegionAttachment.Y4 = 25;
+ RegionAttachment.C4R = 26;
+ RegionAttachment.C4G = 27;
+ RegionAttachment.C4B = 28;
+ RegionAttachment.C4A = 29;
+ RegionAttachment.U4 = 30;
+ RegionAttachment.V4 = 31;
+ spine.RegionAttachment = RegionAttachment;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var JitterEffect = (function () {
+ function JitterEffect(jitterX, jitterY) {
+ this.jitterX = 0;
+ this.jitterY = 0;
+ this.jitterX = jitterX;
+ this.jitterY = jitterY;
+ }
+ JitterEffect.prototype.begin = function (skeleton) {
+ };
+ JitterEffect.prototype.transform = function (position, uv, light, dark) {
+ position.x += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY);
+ position.y += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY);
+ };
+ JitterEffect.prototype.end = function () {
+ };
+ return JitterEffect;
+ }());
+ spine.JitterEffect = JitterEffect;
+})(spine || (spine = {}));
+var spine;
+(function (spine) {
+ var SwirlEffect = (function () {
+ function SwirlEffect(radius) {
+ this.centerX = 0;
+ this.centerY = 0;
+ this.radius = 0;
+ this.angle = 0;
+ this.worldX = 0;
+ this.worldY = 0;
+ this.radius = radius;
+ }
+ SwirlEffect.prototype.begin = function (skeleton) {
+ this.worldX = skeleton.x + this.centerX;
+ this.worldY = skeleton.y + this.centerY;
+ };
+ SwirlEffect.prototype.transform = function (position, uv, light, dark) {
+ var radAngle = this.angle * spine.MathUtils.degreesToRadians;
+ var x = position.x - this.worldX;
+ var y = position.y - this.worldY;
+ var dist = Math.sqrt(x * x + y * y);
+ if (dist < this.radius) {
+ var theta = SwirlEffect.interpolation.apply(0, radAngle, (this.radius - dist) / this.radius);
+ var cos = Math.cos(theta);
+ var sin = Math.sin(theta);
+ position.x = cos * x - sin * y + this.worldX;
+ position.y = sin * x + cos * y + this.worldY;
+ }
+ };
+ SwirlEffect.prototype.end = function () {
+ };
+ return SwirlEffect;
+ }());
+ SwirlEffect.interpolation = new spine.PowOut(2);
+ spine.SwirlEffect = SwirlEffect;
+})(spine || (spine = {}));
+
+var sp = sp || {};
+sp.spine = spine;
diff --git a/box2d/box2d.js b/external/box2d/box2d.js
similarity index 99%
rename from box2d/box2d.js
rename to external/box2d/box2d.js
index 8ca0c416ff..2f9447d28d 100644
--- a/box2d/box2d.js
+++ b/external/box2d/box2d.js
@@ -2140,7 +2140,7 @@ Box2D.postDefs = [];
var localPointB;
var pointA;
var pointB;
- var seperation = 0;
+ var separation = 0;
var normal;
switch (this.m_type) {
case b2SeparationFunction.e_points:
@@ -2151,8 +2151,8 @@ Box2D.postDefs = [];
localPointB = this.m_proxyB.GetSupportVertex(axisB);
pointA = b2Math.MulX(transformA, localPointA);
pointB = b2Math.MulX(transformB, localPointB);
- seperation = (pointB.x - pointA.x) * this.m_axis.x + (pointB.y - pointA.y) * this.m_axis.y;
- return seperation;
+ separation = (pointB.x - pointA.x) * this.m_axis.x + (pointB.y - pointA.y) * this.m_axis.y;
+ return separation;
}
case b2SeparationFunction.e_faceA:
{
@@ -2161,8 +2161,8 @@ Box2D.postDefs = [];
axisB = b2Math.MulTMV(transformB.R, normal.GetNegative());
localPointB = this.m_proxyB.GetSupportVertex(axisB);
pointB = b2Math.MulX(transformB, localPointB);
- seperation = (pointB.x - pointA.x) * normal.x + (pointB.y - pointA.y) * normal.y;
- return seperation;
+ separation = (pointB.x - pointA.x) * normal.x + (pointB.y - pointA.y) * normal.y;
+ return separation;
}
case b2SeparationFunction.e_faceB:
{
@@ -2171,8 +2171,8 @@ Box2D.postDefs = [];
axisA = b2Math.MulTMV(transformA.R, normal.GetNegative());
localPointA = this.m_proxyA.GetSupportVertex(axisA);
pointA = b2Math.MulX(transformA, localPointA);
- seperation = (pointA.x - pointB.x) * normal.x + (pointA.y - pointB.y) * normal.y;
- return seperation;
+ separation = (pointA.x - pointB.x) * normal.x + (pointA.y - pointB.y) * normal.y;
+ return separation;
}
default:
b2Settings.b2Assert(false);
@@ -10877,6 +10877,6 @@ var i;
for (i = 0; i < Box2D.postDefs.length; ++i) Box2D.postDefs[i]();
delete Box2D.postDefs;
-if (typeof require !== 'undefined') {
+if (typeof require !== 'undefined' && typeof module !== 'undefined') {
module.exports = Box2D;
}
diff --git a/external/chipmunk/chipmunk.js b/external/chipmunk/chipmunk.js
new file mode 100644
index 0000000000..0101792e4b
--- /dev/null
+++ b/external/chipmunk/chipmunk.js
@@ -0,0 +1,6236 @@
+(function(){
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+Object.create = Object.create || function(o) {
+ function F() {}
+ F.prototype = o;
+ return new F();
+};
+
+//var VERSION = CP_VERSION_MAJOR + "." + CP_VERSION_MINOR + "." + CP_VERSION_RELEASE;
+
+var cp;
+if(typeof exports === 'undefined'){
+ cp = {};
+
+ if(typeof window === 'object'){
+ window["cp"] = cp;
+ }
+} else {
+ cp = exports;
+}
+
+var assert = function(value, message)
+{
+ if (!value) {
+ throw new Error('Assertion failed: ' + message);
+ }
+};
+
+var assertSoft = function(value, message)
+{
+ if(!value && console && console.warn) {
+ console.warn("ASSERTION FAILED: " + message);
+ if(console.trace) {
+ console.trace();
+ }
+ }
+};
+
+var mymin = function(a, b)
+{
+ return a < b ? a : b;
+};
+var mymax = function(a, b)
+{
+ return a > b ? a : b;
+};
+
+var min, max;
+if (typeof window === 'object' && window.navigator.userAgent.indexOf('Firefox') > -1){
+ // On firefox, Math.min and Math.max are really fast:
+ // http://jsperf.com/math-vs-greater-than/8
+ min = Math.min;
+ max = Math.max;
+} else {
+ // On chrome and safari, Math.min / max are slooow. The ternery operator above is faster
+ // than the builtins because we only have to deal with 2 arguments that are always numbers.
+ min = mymin;
+ max = mymax;
+}
+
+/* The hashpair function takes two numbers and returns a hash code for them.
+ * Required that hashPair(a, b) === hashPair(b, a).
+ * Chipmunk's hashPair function is defined as:
+ * #define CP_HASH_COEF (3344921057ul)
+ * #define CP_HASH_PAIR(A, B) ((cpHashValue)(A)*CP_HASH_COEF ^ (cpHashValue)(B)*CP_HASH_COEF)
+ * But thats not suitable in javascript because multiplying by a large number will make the number
+ * a large float.
+ *
+ * The result of hashPair is used as the key in objects, so it returns a string.
+ */
+var hashPair = function(a, b)
+{
+ //assert(typeof(a) === 'number', "HashPair used on something not a number");
+ return a < b ? a + ' ' + b : b + ' ' + a;
+};
+
+var deleteObjFromList = function(arr, obj)
+{
+ for(var i=0; i> 1;
+ for(var i=1; i maxx || (x == maxx && y > maxy)){
+ maxx = x;
+ maxy = y;
+ end = i;
+ }
+ }
+ return [start, end];
+};
+
+var SWAP = function(arr, idx1, idx2)
+{
+ var tmp = arr[idx1*2];
+ arr[idx1*2] = arr[idx2*2];
+ arr[idx2*2] = tmp;
+
+ tmp = arr[idx1*2+1];
+ arr[idx1*2+1] = arr[idx2*2+1];
+ arr[idx2*2+1] = tmp;
+};
+
+var QHullPartition = function(verts, offs, count, a, b, tol)
+{
+ if(count === 0) return 0;
+
+ var max = 0;
+ var pivot = offs;
+
+ var delta = vsub(b, a);
+ var valueTol = tol * vlength(delta);
+
+ var head = offs;
+ for(var tail = offs+count-1; head <= tail;){
+ var v = new Vect(verts[head * 2], verts[head * 2 + 1]);
+ var value = vcross(delta, vsub(v, a));
+ if(value > valueTol){
+ if(value > max){
+ max = value;
+ pivot = head;
+ }
+
+ head++;
+ } else {
+ SWAP(verts, head, tail);
+ tail--;
+ }
+ }
+
+ // move the new pivot to the front if it's not already there.
+ if(pivot != offs) SWAP(verts, offs, pivot);
+ return head - offs;
+};
+
+var QHullReduce = function(tol, verts, offs, count, a, pivot, b, resultPos)
+{
+ if(count < 0){
+ return 0;
+ } else if(count == 0) {
+ verts[resultPos*2] = pivot.x;
+ verts[resultPos*2+1] = pivot.y;
+ return 1;
+ } else {
+ var left_count = QHullPartition(verts, offs, count, a, pivot, tol);
+ var left = new Vect(verts[offs*2], verts[offs*2+1]);
+ var index = QHullReduce(tol, verts, offs + 1, left_count - 1, a, left, pivot, resultPos);
+
+ var pivotPos = resultPos + index++;
+ verts[pivotPos*2] = pivot.x;
+ verts[pivotPos*2+1] = pivot.y;
+
+ var right_count = QHullPartition(verts, offs + left_count, count - left_count, pivot, b, tol);
+ var right = new Vect(verts[(offs+left_count)*2], verts[(offs+left_count)*2+1]);
+ return index + QHullReduce(tol, verts, offs + left_count + 1, right_count - 1, pivot, right, b, resultPos + index);
+ }
+};
+
+// QuickHull seemed like a neat algorithm, and efficient-ish for large input sets.
+// My implementation performs an in place reduction using the result array as scratch space.
+//
+// Pass an Array into result to put the result of the calculation there. Otherwise, pass null
+// and the verts list will be edited in-place.
+//
+// Expects the verts to be described in the same way as cpPolyShape - which is to say, it should
+// be a list of [x1,y1,x2,y2,x3,y3,...].
+//
+// tolerance is in world coordinates. Eg, 2.
+cp.convexHull = function(verts, result, tolerance)
+{
+ if(result){
+ // Copy the line vertexes into the empty part of the result polyline to use as a scratch buffer.
+ for (var i = 0; i < verts.length; i++){
+ result[i] = verts[i];
+ }
+ } else {
+ // If a result array was not specified, reduce the input instead.
+ result = verts;
+ }
+
+ // Degenerate case, all points are the same.
+ var indexes = loopIndexes(verts);
+ var start = indexes[0], end = indexes[1];
+ if(start == end){
+ //if(first) (*first) = 0;
+ result.length = 2;
+ return result;
+ }
+
+ SWAP(result, 0, start);
+ SWAP(result, 1, end == 0 ? start : end);
+
+ var a = new Vect(result[0], result[1]);
+ var b = new Vect(result[2], result[3]);
+
+ var count = verts.length >> 1;
+ //if(first) (*first) = start;
+ var resultCount = QHullReduce(tolerance, result, 2, count - 2, a, b, a, 1) + 1;
+ result.length = resultCount*2;
+
+ assertSoft(polyValidate(result),
+ "Internal error: cpConvexHull() and cpPolyValidate() did not agree." +
+ "Please report this error with as much info as you can.");
+ return result;
+};
+
+/// Clamp @c f to be between @c min and @c max.
+var clamp = function(f, minv, maxv)
+{
+ return min(max(f, minv), maxv);
+};
+
+/// Clamp @c f to be between 0 and 1.
+var clamp01 = function(f)
+{
+ return max(0, min(f, 1));
+};
+
+/// Linearly interpolate (or extrapolate) between @c f1 and @c f2 by @c t percent.
+var lerp = function(f1, f2, t)
+{
+ return f1*(1 - t) + f2*t;
+};
+
+/// Linearly interpolate from @c f1 to @c f2 by no more than @c d.
+var lerpconst = function(f1, f2, d)
+{
+ return f1 + clamp(f2 - f1, -d, d);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+// I'm using an array tuple here because (at time of writing) its about 3x faster
+// than an object on firefox, and the same speed on chrome.
+
+//var numVects = 0;
+
+var Vect = cp.Vect = function(x, y)
+{
+ this.x = x;
+ this.y = y;
+ //numVects++;
+
+// var s = new Error().stack;
+// traces[s] = traces[s] ? traces[s]+1 : 1;
+};
+
+cp.v = function (x,y) { return new Vect(x, y) };
+
+var vzero = cp.vzero = new Vect(0,0);
+
+// The functions below *could* be rewritten to be instance methods on Vect. I don't
+// know how that would effect performance. For now, I'm keeping the JS similar to
+// the original C code.
+
+/// Vector dot product.
+var vdot = cp.v.dot = function(v1, v2)
+{
+ return v1.x*v2.x + v1.y*v2.y;
+};
+
+var vdot2 = function(x1, y1, x2, y2)
+{
+ return x1*x2 + y1*y2;
+};
+
+/// Returns the length of v.
+var vlength = cp.v.len = function(v)
+{
+ return Math.sqrt(vdot(v, v));
+};
+
+var vlength2 = cp.v.len2 = function(x, y)
+{
+ return Math.sqrt(x*x + y*y);
+};
+
+/// Check if two vectors are equal. (Be careful when comparing floating point numbers!)
+var veql = cp.v.eql = function(v1, v2)
+{
+ return (v1.x === v2.x && v1.y === v2.y);
+};
+
+/// Add two vectors
+var vadd = cp.v.add = function(v1, v2)
+{
+ return new Vect(v1.x + v2.x, v1.y + v2.y);
+};
+
+Vect.prototype.add = function(v2)
+{
+ this.x += v2.x;
+ this.y += v2.y;
+ return this;
+};
+
+/// Subtract two vectors.
+var vsub = cp.v.sub = function(v1, v2)
+{
+ return new Vect(v1.x - v2.x, v1.y - v2.y);
+};
+
+Vect.prototype.sub = function(v2)
+{
+ this.x -= v2.x;
+ this.y -= v2.y;
+ return this;
+};
+
+/// Negate a vector.
+var vneg = cp.v.neg = function(v)
+{
+ return new Vect(-v.x, -v.y);
+};
+
+Vect.prototype.neg = function()
+{
+ this.x = -this.x;
+ this.y = -this.y;
+ return this;
+};
+
+/// Scalar multiplication.
+var vmult = cp.v.mult = function(v, s)
+{
+ return new Vect(v.x*s, v.y*s);
+};
+
+Vect.prototype.mult = function(s)
+{
+ this.x *= s;
+ this.y *= s;
+ return this;
+};
+
+/// 2D vector cross product analog.
+/// The cross product of 2D vectors results in a 3D vector with only a z component.
+/// This function returns the magnitude of the z value.
+var vcross = cp.v.cross = function(v1, v2)
+{
+ return v1.x*v2.y - v1.y*v2.x;
+};
+
+var vcross2 = function(x1, y1, x2, y2)
+{
+ return x1*y2 - y1*x2;
+};
+
+/// Returns a perpendicular vector. (90 degree rotation)
+var vperp = cp.v.perp = function(v)
+{
+ return new Vect(-v.y, v.x);
+};
+
+/// Returns a perpendicular vector. (-90 degree rotation)
+var vpvrperp = cp.v.pvrperp = function(v)
+{
+ return new Vect(v.y, -v.x);
+};
+
+/// Returns the vector projection of v1 onto v2.
+var vproject = cp.v.project = function(v1, v2)
+{
+ return vmult(v2, vdot(v1, v2)/vlengthsq(v2));
+};
+
+Vect.prototype.project = function(v2)
+{
+ this.mult(vdot(this, v2) / vlengthsq(v2));
+ return this;
+};
+
+/// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector.
+var vrotate = cp.v.rotate = function(v1, v2)
+{
+ return new Vect(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
+};
+
+Vect.prototype.rotate = function(v2)
+{
+ this.x = this.x * v2.x - this.y * v2.y;
+ this.y = this.x * v2.y + this.y * v2.x;
+ return this;
+};
+
+/// Inverse of vrotate().
+var vunrotate = cp.v.unrotate = function(v1, v2)
+{
+ return new Vect(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
+};
+
+/// Returns the squared length of v. Faster than vlength() when you only need to compare lengths.
+var vlengthsq = cp.v.lengthsq = function(v)
+{
+ return vdot(v, v);
+};
+
+var vlengthsq2 = cp.v.lengthsq2 = function(x, y)
+{
+ return x*x + y*y;
+};
+
+/// Linearly interpolate between v1 and v2.
+var vlerp = cp.v.lerp = function(v1, v2, t)
+{
+ return vadd(vmult(v1, 1 - t), vmult(v2, t));
+};
+
+/// Returns a normalized copy of v.
+var vnormalize = cp.v.normalize = function(v)
+{
+ return vmult(v, 1/vlength(v));
+};
+
+/// Returns a normalized copy of v or vzero if v was already vzero. Protects against divide by zero errors.
+var vnormalize_safe = cp.v.normalize_safe = function(v)
+{
+ return (v.x === 0 && v.y === 0 ? vzero : vnormalize(v));
+};
+
+/// Clamp v to length len.
+var vclamp = cp.v.clamp = function(v, len)
+{
+ return (vdot(v,v) > len*len) ? vmult(vnormalize(v), len) : v;
+};
+
+/// Linearly interpolate between v1 towards v2 by distance d.
+var vlerpconst = cp.v.lerpconst = function(v1, v2, d)
+{
+ return vadd(v1, vclamp(vsub(v2, v1), d));
+};
+
+/// Returns the distance between v1 and v2.
+var vdist = cp.v.dist = function(v1, v2)
+{
+ return vlength(vsub(v1, v2));
+};
+
+/// Returns the squared distance between v1 and v2. Faster than vdist() when you only need to compare distances.
+var vdistsq = cp.v.distsq = function(v1, v2)
+{
+ return vlengthsq(vsub(v1, v2));
+};
+
+/// Returns true if the distance between v1 and v2 is less than dist.
+var vnear = cp.v.near = function(v1, v2, dist)
+{
+ return vdistsq(v1, v2) < dist*dist;
+};
+
+/// Spherical linearly interpolate between v1 and v2.
+var vslerp = cp.v.slerp = function(v1, v2, t)
+{
+ var omega = Math.acos(vdot(v1, v2));
+
+ if(omega) {
+ var denom = 1/Math.sin(omega);
+ return vadd(vmult(v1, Math.sin((1 - t)*omega)*denom), vmult(v2, Math.sin(t*omega)*denom));
+ } else {
+ return v1;
+ }
+};
+
+/// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians
+var vslerpconst = cp.v.slerpconst = function(v1, v2, a)
+{
+ var angle = Math.acos(vdot(v1, v2));
+ return vslerp(v1, v2, min(a, angle)/angle);
+};
+
+/// Returns the unit length vector for the given angle (in radians).
+var vforangle = cp.v.forangle = function(a)
+{
+ return new Vect(Math.cos(a), Math.sin(a));
+};
+
+/// Returns the angular direction v is pointing in (in radians).
+var vtoangle = cp.v.toangle = function(v)
+{
+ return Math.atan2(v.y, v.x);
+};
+
+/// Returns a string representation of v. Intended mostly for debugging purposes and not production use.
+var vstr = cp.v.str = function(v)
+{
+ return "(" + v.x.toFixed(3) + ", " + v.y.toFixed(3) + ")";
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+/// Chipmunk's axis-aligned 2D bounding box type along with a few handy routines.
+
+var numBB = 0;
+
+// Bounding boxes are JS objects with {l, b, r, t} = left, bottom, right, top, respectively.
+var BB = cp.BB = function(l, b, r, t)
+{
+ this.l = l;
+ this.b = b;
+ this.r = r;
+ this.t = t;
+
+ numBB++;
+};
+
+cp.bb = function(l, b, r, t) { return new BB(l, b, r, t); };
+
+var bbNewForCircle = function(p, r)
+{
+ return new BB(
+ p.x - r,
+ p.y - r,
+ p.x + r,
+ p.y + r
+ );
+};
+
+/// Returns true if @c a and @c b intersect.
+var bbIntersects = function(a, b)
+{
+ return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t);
+};
+var bbIntersects2 = function(bb, l, b, r, t)
+{
+ return (bb.l <= r && l <= bb.r && bb.b <= t && b <= bb.t);
+};
+
+/// Returns true if @c other lies completely within @c bb.
+var bbContainsBB = function(bb, other)
+{
+ return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t);
+};
+
+/// Returns true if @c bb contains @c v.
+var bbContainsVect = function(bb, v)
+{
+ return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y);
+};
+var bbContainsVect2 = function(l, b, r, t, v)
+{
+ return (l <= v.x && r >= v.x && b <= v.y && t >= v.y);
+};
+
+/// Returns a bounding box that holds both bounding boxes.
+var bbMerge = function(a, b){
+ return new BB(
+ min(a.l, b.l),
+ min(a.b, b.b),
+ max(a.r, b.r),
+ max(a.t, b.t)
+ );
+};
+
+/// Returns a bounding box that holds both @c bb and @c v.
+var bbExpand = function(bb, v){
+ return new BB(
+ min(bb.l, v.x),
+ min(bb.b, v.y),
+ max(bb.r, v.x),
+ max(bb.t, v.y)
+ );
+};
+
+/// Returns the area of the bounding box.
+var bbArea = function(bb)
+{
+ return (bb.r - bb.l)*(bb.t - bb.b);
+};
+
+/// Merges @c a and @c b and returns the area of the merged bounding box.
+var bbMergedArea = function(a, b)
+{
+ return (max(a.r, b.r) - min(a.l, b.l))*(max(a.t, b.t) - min(a.b, b.b));
+};
+
+var bbMergedArea2 = function(bb, l, b, r, t)
+{
+ return (max(bb.r, r) - min(bb.l, l))*(max(bb.t, t) - min(bb.b, b));
+};
+
+/// Return true if the bounding box intersects the line segment with ends @c a and @c b.
+var bbIntersectsSegment = function(bb, a, b)
+{
+ return (bbSegmentQuery(bb, a, b) != Infinity);
+};
+
+/// Clamp a vector to a bounding box.
+var bbClampVect = function(bb, v)
+{
+ var x = min(max(bb.l, v.x), bb.r);
+ var y = min(max(bb.b, v.y), bb.t);
+ return new Vect(x, y);
+};
+
+// TODO edge case issue
+/// Wrap a vector to a bounding box.
+var bbWrapVect = function(bb, v)
+{
+ var ix = Math.abs(bb.r - bb.l);
+ var modx = (v.x - bb.l) % ix;
+ var x = (modx > 0) ? modx : modx + ix;
+
+ var iy = Math.abs(bb.t - bb.b);
+ var mody = (v.y - bb.b) % iy;
+ var y = (mody > 0) ? mody : mody + iy;
+
+ return new Vect(x + bb.l, y + bb.b);
+};
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+/// Segment query info struct.
+/* These are created using literals where needed.
+typedef struct cpSegmentQueryInfo {
+ /// The shape that was hit, null if no collision occurred.
+ cpShape *shape;
+ /// The normalized distance along the query segment in the range [0, 1].
+ cpFloat t;
+ /// The normal of the surface hit.
+ cpVect n;
+} cpSegmentQueryInfo;
+*/
+
+var shapeIDCounter = 0;
+
+var CP_NO_GROUP = cp.NO_GROUP = 0;
+var CP_ALL_LAYERS = cp.ALL_LAYERS = ~0;
+var CP_ALL_CATEGORIES = cp.ALL_CATEGORIES = ~0; // Chipmunk v7.0 compatibility
+
+cp.resetShapeIdCounter = function()
+{
+ shapeIDCounter = 0;
+};
+
+/// The cpShape struct defines the shape of a rigid body.
+//
+/// Opaque collision shape struct. Do not create directly - instead use
+/// PolyShape, CircleShape and SegmentShape.
+var Shape = cp.Shape = function(body) {
+ /// The rigid body this collision shape is attached to.
+ this.body = body;
+
+ /// The current bounding box of the shape.
+ this.bb_l = this.bb_b = this.bb_r = this.bb_t = 0;
+
+ this.hashid = shapeIDCounter++;
+
+ /// Sensor flag.
+ /// Sensor shapes call collision callbacks but don't produce collisions.
+ this.sensor = false;
+
+ /// Coefficient of restitution. (elasticity)
+ this.e = 0;
+ /// Coefficient of friction.
+ this.u = 0;
+ /// Surface velocity used when solving for friction.
+ this.surface_v = vzero;
+
+ /// Collision type of this shape used when picking collision handlers.
+ this.collision_type = 0;
+ /// Group of this shape. Shapes in the same group don't collide.
+ this.group = 0;
+ // Layer bitmask for this shape. Shapes only collide if the bitwise and of their layers is non-zero.
+ this.layers = CP_ALL_LAYERS;
+
+ this.space = null;
+
+ // Copy the collision code from the prototype into the actual object. This makes collision
+ // function lookups slightly faster.
+ this.collisionCode = this.collisionCode;
+};
+
+Shape.prototype.setElasticity = function(e) { this.e = e; };
+Shape.prototype.setFriction = function(u) { this.body.activate(); this.u = u; };
+Shape.prototype.setLayers = function(layers) { this.body.activate(); this.layers = layers; };
+Shape.prototype.setSensor = function(sensor) { this.body.activate(); this.sensor = sensor; };
+Shape.prototype.setCollisionType = function(collision_type) { this.body.activate(); this.collision_type = collision_type; };
+Shape.prototype.getBody = function() { return this.body; };
+
+Shape.prototype.active = function()
+{
+// return shape->prev || (shape->body && shape->body->shapeList == shape);
+ return this.body && this.body.shapeList.indexOf(this) !== -1;
+};
+
+Shape.prototype.setBody = function(body)
+{
+ assert(!this.active(), "You cannot change the body on an active shape. You must remove the shape from the space before changing the body.");
+ this.body = body;
+};
+
+Shape.prototype.cacheBB = function()
+{
+ return this.update(this.body.p, this.body.rot);
+};
+
+Shape.prototype.update = function(pos, rot)
+{
+ assert(!isNaN(rot.x), 'Rotation is NaN');
+ assert(!isNaN(pos.x), 'Position is NaN');
+ this.cacheData(pos, rot);
+};
+
+Shape.prototype.pointQuery = function(p)
+{
+ var info = this.nearestPointQuery(p);
+ if (info.d < 0) return info;
+};
+
+Shape.prototype.getBB = function()
+{
+ return new BB(this.bb_l, this.bb_b, this.bb_r, this.bb_t);
+};
+
+/* Not implemented - all these getters and setters. Just edit the object directly.
+CP_DefineShapeStructGetter(cpBody*, body, Body);
+void cpShapeSetBody(cpShape *shape, cpBody *body);
+
+CP_DefineShapeStructGetter(cpBB, bb, BB);
+CP_DefineShapeStructProperty(cpBool, sensor, Sensor, cpTrue);
+CP_DefineShapeStructProperty(cpFloat, e, Elasticity, cpFalse);
+CP_DefineShapeStructProperty(cpFloat, u, Friction, cpTrue);
+CP_DefineShapeStructProperty(cpVect, surface_v, SurfaceVelocity, cpTrue);
+CP_DefineShapeStructProperty(cpDataPointer, data, UserData, cpFalse);
+CP_DefineShapeStructProperty(cpCollisionType, collision_type, CollisionType, cpTrue);
+CP_DefineShapeStructProperty(cpGroup, group, Group, cpTrue);
+CP_DefineShapeStructProperty(cpLayers, layers, Layers, cpTrue);
+*/
+
+/// Extended point query info struct. Returned from calling pointQuery on a shape.
+var PointQueryExtendedInfo = function(shape)
+{
+ /// Shape that was hit, NULL if no collision occurred.
+ this.shape = shape;
+ /// Depth of the point inside the shape.
+ this.d = Infinity;
+ /// Direction of minimum norm to the shape's surface.
+ this.n = vzero;
+};
+
+var NearestPointQueryInfo = function(shape, p, d)
+{
+ /// The nearest shape, NULL if no shape was within range.
+ this.shape = shape;
+ /// The closest point on the shape's surface. (in world space coordinates)
+ this.p = p;
+ /// The distance to the point. The distance is negative if the point is inside the shape.
+ this.d = d;
+};
+
+var SegmentQueryInfo = function(shape, t, n)
+{
+ /// The shape that was hit, NULL if no collision occurred.
+ this.shape = shape;
+ /// The normalized distance along the query segment in the range [0, 1].
+ this.t = t;
+ /// The normal of the surface hit.
+ this.n = n;
+};
+
+/// Get the hit point for a segment query.
+SegmentQueryInfo.prototype.hitPoint = function(start, end)
+{
+ return vlerp(start, end, this.t);
+};
+
+/// Get the hit distance for a segment query.
+SegmentQueryInfo.prototype.hitDist = function(start, end)
+{
+ return vdist(start, end) * this.t;
+};
+
+// Circles.
+
+var CircleShape = cp.CircleShape = function(body, radius, offset)
+{
+ this.c = this.tc = offset;
+ this.r = radius;
+
+ this.type = 'circle';
+
+ Shape.call(this, body);
+};
+
+CircleShape.prototype = Object.create(Shape.prototype);
+
+CircleShape.prototype.cacheData = function(p, rot)
+{
+ //var c = this.tc = vadd(p, vrotate(this.c, rot));
+ var c = this.tc = vrotate(this.c, rot).add(p);
+ //this.bb = bbNewForCircle(c, this.r);
+ var r = this.r;
+ this.bb_l = c.x - r;
+ this.bb_b = c.y - r;
+ this.bb_r = c.x + r;
+ this.bb_t = c.y + r;
+};
+
+/// Test if a point lies within a shape.
+/*CircleShape.prototype.pointQuery = function(p)
+{
+ var delta = vsub(p, this.tc);
+ var distsq = vlengthsq(delta);
+ var r = this.r;
+
+ if(distsq < r*r){
+ var info = new PointQueryExtendedInfo(this);
+
+ var dist = Math.sqrt(distsq);
+ info.d = r - dist;
+ info.n = vmult(delta, 1/dist);
+ return info;
+ }
+};*/
+
+CircleShape.prototype.nearestPointQuery = function(p)
+{
+ var deltax = p.x - this.tc.x;
+ var deltay = p.y - this.tc.y;
+ var d = vlength2(deltax, deltay);
+ var r = this.r;
+
+ var nearestp = new Vect(this.tc.x + deltax * r/d, this.tc.y + deltay * r/d);
+ return new NearestPointQueryInfo(this, nearestp, d - r);
+};
+
+var circleSegmentQuery = function(shape, center, r, a, b, info)
+{
+ // offset the line to be relative to the circle
+ a = vsub(a, center);
+ b = vsub(b, center);
+
+ var qa = vdot(a, a) - 2*vdot(a, b) + vdot(b, b);
+ var qb = -2*vdot(a, a) + 2*vdot(a, b);
+ var qc = vdot(a, a) - r*r;
+
+ var det = qb*qb - 4*qa*qc;
+
+ if(det >= 0)
+ {
+ var t = (-qb - Math.sqrt(det))/(2*qa);
+ if(0 <= t && t <= 1){
+ return new SegmentQueryInfo(shape, t, vnormalize(vlerp(a, b, t)));
+ }
+ }
+};
+
+CircleShape.prototype.segmentQuery = function(a, b)
+{
+ return circleSegmentQuery(this, this.tc, this.r, a, b);
+};
+
+// The C API has these, and also getters. Its not idiomatic to
+// write getters and setters in JS.
+/*
+CircleShape.prototype.setRadius = function(radius)
+{
+ this.r = radius;
+}
+
+CircleShape.prototype.setOffset = function(offset)
+{
+ this.c = offset;
+}*/
+
+// Segment shape
+
+var SegmentShape = cp.SegmentShape = function(body, a, b, r)
+{
+ this.a = a;
+ this.b = b;
+ this.n = vperp(vnormalize(vsub(b, a)));
+
+ this.ta = this.tb = this.tn = null;
+
+ this.r = r;
+
+ this.a_tangent = vzero;
+ this.b_tangent = vzero;
+
+ this.type = 'segment';
+ Shape.call(this, body);
+};
+
+SegmentShape.prototype = Object.create(Shape.prototype);
+
+SegmentShape.prototype.cacheData = function(p, rot)
+{
+ this.ta = vadd(p, vrotate(this.a, rot));
+ this.tb = vadd(p, vrotate(this.b, rot));
+ this.tn = vrotate(this.n, rot);
+
+ var l,r,b,t;
+
+ if(this.ta.x < this.tb.x){
+ l = this.ta.x;
+ r = this.tb.x;
+ } else {
+ l = this.tb.x;
+ r = this.ta.x;
+ }
+
+ if(this.ta.y < this.tb.y){
+ b = this.ta.y;
+ t = this.tb.y;
+ } else {
+ b = this.tb.y;
+ t = this.ta.y;
+ }
+
+ var rad = this.r;
+
+ this.bb_l = l - rad;
+ this.bb_b = b - rad;
+ this.bb_r = r + rad;
+ this.bb_t = t + rad;
+};
+
+SegmentShape.prototype.nearestPointQuery = function(p)
+{
+ var closest = closestPointOnSegment(p, this.ta, this.tb);
+
+ var deltax = p.x - closest.x;
+ var deltay = p.y - closest.y;
+ var d = vlength2(deltax, deltay);
+ var r = this.r;
+
+ var nearestp = (d ? vadd(closest, vmult(new Vect(deltax, deltay), r/d)) : closest);
+ return new NearestPointQueryInfo(this, nearestp, d - r);
+};
+
+SegmentShape.prototype.segmentQuery = function(a, b)
+{
+ var n = this.tn;
+ var d = vdot(vsub(this.ta, a), n);
+ var r = this.r;
+
+ var flipped_n = (d > 0 ? vneg(n) : n);
+ var n_offset = vsub(vmult(flipped_n, r), a);
+
+ var seg_a = vadd(this.ta, n_offset);
+ var seg_b = vadd(this.tb, n_offset);
+ var delta = vsub(b, a);
+
+ if(vcross(delta, seg_a)*vcross(delta, seg_b) <= 0){
+ var d_offset = d + (d > 0 ? -r : r);
+ var ad = -d_offset;
+ var bd = vdot(delta, n) - d_offset;
+
+ if(ad*bd < 0){
+ return new SegmentQueryInfo(this, ad/(ad - bd), flipped_n);
+ }
+ } else if(r !== 0){
+ var info1 = circleSegmentQuery(this, this.ta, this.r, a, b);
+ var info2 = circleSegmentQuery(this, this.tb, this.r, a, b);
+
+ if (info1){
+ return info2 && info2.t < info1.t ? info2 : info1;
+ } else {
+ return info2;
+ }
+ }
+};
+
+SegmentShape.prototype.setNeighbors = function(prev, next)
+{
+ this.a_tangent = vsub(prev, this.a);
+ this.b_tangent = vsub(next, this.b);
+};
+
+SegmentShape.prototype.setEndpoints = function(a, b)
+{
+ this.a = a;
+ this.b = b;
+ this.n = vperp(vnormalize(vsub(b, a)));
+};
+
+/*
+cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius)
+{
+ this.r = radius;
+}*/
+
+/*
+CP_DeclareShapeGetter(cpSegmentShape, cpVect, A);
+CP_DeclareShapeGetter(cpSegmentShape, cpVect, B);
+CP_DeclareShapeGetter(cpSegmentShape, cpVect, Normal);
+CP_DeclareShapeGetter(cpSegmentShape, cpFloat, Radius);
+*/
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+/// Check that a set of vertexes is convex and has a clockwise winding.
+var polyValidate = function(verts)
+{
+ var len = verts.length;
+ for(var i=0; i 0){
+ if(vcross2(bx - ax, by - ay, cx - bx, cy - by) > 0){
+ return false;
+ }
+ }
+
+ return true;
+};
+
+/// Initialize a polygon shape.
+/// The vertexes must be convex and have a clockwise winding.
+var PolyShape = cp.PolyShape = function(body, verts, offset)
+{
+ this.setVerts(verts, offset);
+ this.type = 'poly';
+ Shape.call(this, body);
+};
+
+PolyShape.prototype = Object.create(Shape.prototype);
+
+var SplittingPlane = function(n, d)
+{
+ this.n = n;
+ this.d = d;
+};
+
+SplittingPlane.prototype.compare = function(v)
+{
+ return vdot(this.n, v) - this.d;
+};
+
+PolyShape.prototype.setVerts = function(verts, offset)
+{
+ assert(verts.length >= 4, "Polygons require some verts");
+ assert(typeof(verts[0]) === 'number',
+ 'Polygon verticies should be specified in a flattened list (eg [x1,y1,x2,y2,x3,y3,...])');
+
+ // Fail if the user attempts to pass a concave poly, or a bad winding.
+ assert(polyValidate(verts), "Polygon is concave or has a reversed winding. Consider using cpConvexHull()");
+
+ var len = verts.length;
+ var numVerts = len >> 1;
+
+ // This a pretty bad way to do this in javascript. As a first pass, I want to keep
+ // the code similar to the C.
+ this.verts = new Array(len);
+ this.tVerts = new Array(len);
+ this.planes = new Array(numVerts);
+ this.tPlanes = new Array(numVerts);
+
+ for(var i=0; i>1] = new SplittingPlane(n, vdot2(n.x, n.y, ax, ay));
+ this.tPlanes[i>>1] = new SplittingPlane(new Vect(0,0), 0);
+ }
+};
+
+/// Initialize a box shaped polygon shape.
+var BoxShape = cp.BoxShape = function(body, width, height)
+{
+ var hw = width/2;
+ var hh = height/2;
+
+ return BoxShape2(body, new BB(-hw, -hh, hw, hh));
+};
+
+/// Initialize an offset box shaped polygon shape.
+var BoxShape2 = cp.BoxShape2 = function(body, box)
+{
+ var verts = [
+ box.l, box.b,
+ box.l, box.t,
+ box.r, box.t,
+ box.r, box.b
+ ];
+
+ return new PolyShape(body, verts, vzero);
+};
+
+PolyShape.prototype.transformVerts = function(p, rot)
+{
+ var src = this.verts;
+ var dst = this.tVerts;
+
+ var l = Infinity, r = -Infinity;
+ var b = Infinity, t = -Infinity;
+
+ for(var i=0; i (' + vx + ',' + vy + ')');
+
+ dst[i] = vx;
+ dst[i+1] = vy;
+
+ l = min(l, vx);
+ r = max(r, vx);
+ b = min(b, vy);
+ t = max(t, vy);
+ }
+
+ this.bb_l = l;
+ this.bb_b = b;
+ this.bb_r = r;
+ this.bb_t = t;
+};
+
+PolyShape.prototype.transformAxes = function(p, rot)
+{
+ var src = this.planes;
+ var dst = this.tPlanes;
+
+ for(var i=0; i 0) outside = true;
+
+ var v1x = verts[i*2];
+ var v1y = verts[i*2 + 1];
+ var closest = closestPointOnSegment2(p.x, p.y, v0x, v0y, v1x, v1y);
+
+ var dist = vdist(p, closest);
+ if(dist < minDist){
+ minDist = dist;
+ closestPoint = closest;
+ }
+
+ v0x = v1x;
+ v0y = v1y;
+ }
+
+ return new NearestPointQueryInfo(this, closestPoint, (outside ? minDist : -minDist));
+};
+
+PolyShape.prototype.segmentQuery = function(a, b)
+{
+ var axes = this.tPlanes;
+ var verts = this.tVerts;
+ var numVerts = axes.length;
+ var len = numVerts * 2;
+
+ for(var i=0; i an) continue;
+
+ var bn = vdot(b, n);
+ var t = (axes[i].d - an)/(bn - an);
+ if(t < 0 || 1 < t) continue;
+
+ var point = vlerp(a, b, t);
+ var dt = -vcross(n, point);
+ var dtMin = -vcross2(n.x, n.y, verts[i*2], verts[i*2+1]);
+ var dtMax = -vcross2(n.x, n.y, verts[(i*2+2)%len], verts[(i*2+3)%len]);
+
+ if(dtMin <= dt && dt <= dtMax){
+ // josephg: In the original C code, this function keeps
+ // looping through axes after finding a match. I *think*
+ // this code is equivalent...
+ return new SegmentQueryInfo(this, t, n);
+ }
+ }
+};
+
+PolyShape.prototype.valueOnAxis = function(n, d)
+{
+ var verts = this.tVerts;
+ var m = vdot2(n.x, n.y, verts[0], verts[1]);
+
+ for(var i=2; i 0) return false;
+ }
+
+ return true;
+};
+
+PolyShape.prototype.containsVertPartial = function(vx, vy, n)
+{
+ var planes = this.tPlanes;
+
+ for(var i=0; i 0) return false;
+ }
+
+ return true;
+};
+
+// These methods are provided for API compatibility with Chipmunk. I recommend against using
+// them - just access the poly.verts list directly.
+PolyShape.prototype.getNumVerts = function() { return this.verts.length / 2; };
+PolyShape.prototype.getCount = PolyShape.prototype.getNumVerts; // v7.0 compatibility
+PolyShape.prototype.getVert = function(i)
+{
+ return new Vect(this.verts[i * 2], this.verts[i * 2 + 1]);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+/// @defgroup cpBody cpBody
+/// Chipmunk's rigid body type. Rigid bodies hold the physical properties of an object like
+/// it's mass, and position and velocity of it's center of gravity. They don't have an shape on their own.
+/// They are given a shape by creating collision shapes (cpShape) that point to the body.
+/// @{
+
+var Body = cp.Body = function(m, i) {
+ /// Mass of the body.
+ /// Must agree with cpBody.m_inv! Use body.setMass() when changing the mass for this reason.
+ //this.m;
+ /// Mass inverse.
+ //this.m_inv;
+
+ /// Moment of inertia of the body.
+ /// Must agree with cpBody.i_inv! Use body.setMoment() when changing the moment for this reason.
+ //this.i;
+ /// Moment of inertia inverse.
+ //this.i_inv;
+
+ /// Position of the rigid body's center of gravity.
+ this.p = new Vect(0,0);
+ /// Velocity of the rigid body's center of gravity.
+ this.vx = this.vy = 0;
+ /// Force acting on the rigid body's center of gravity.
+ this.f = new Vect(0,0);
+
+ /// Rotation of the body around it's center of gravity in radians.
+ /// Must agree with cpBody.rot! Use cpBodySetAngle() when changing the angle for this reason.
+ //this.a;
+ /// Angular velocity of the body around it's center of gravity in radians/second.
+ this.w = 0;
+ /// Torque applied to the body around it's center of gravity.
+ this.t = 0;
+
+ /// Cached unit length vector representing the angle of the body.
+ /// Used for fast rotations using cpvrotate().
+ //cpVect rot;
+
+ /// Maximum velocity allowed when updating the velocity.
+ this.v_limit = Infinity;
+ /// Maximum rotational rate (in radians/second) allowed when updating the angular velocity.
+ this.w_limit = Infinity;
+
+ // This stuff is all private.
+ this.v_biasx = this.v_biasy = 0;
+ this.w_bias = 0;
+
+ this.space = null;
+
+ this.shapeList = [];
+ this.arbiterList = null; // These are both wacky linked lists.
+ this.constraintList = null;
+
+ // This stuff is used to track information on the collision graph.
+ this.nodeRoot = null;
+ this.nodeNext = null;
+ this.nodeIdleTime = 0;
+
+ // Set this.m and this.m_inv
+ this.setMass(m);
+
+ // Set this.i and this.i_inv
+ this.setMoment(i);
+
+ // Set this.a and this.rot
+ this.rot = new Vect(0,0);
+ this.setAngle(0);
+};
+
+// I wonder if this should use the constructor style like Body...
+var createStaticBody = function()
+{
+ var body = new Body(Infinity, Infinity);
+ body.nodeIdleTime = Infinity;
+
+ return body;
+};
+ cp.StaticBody = createStaticBody;
+
+if (typeof DEBUG !== 'undefined' && DEBUG) {
+ var v_assert_nan = function(v, message){assert(v.x == v.x && v.y == v.y, message); };
+ var v_assert_infinite = function(v, message){assert(Math.abs(v.x) !== Infinity && Math.abs(v.y) !== Infinity, message);};
+ var v_assert_sane = function(v, message){v_assert_nan(v, message); v_assert_infinite(v, message);};
+
+ Body.prototype.sanityCheck = function()
+ {
+ assert(this.m === this.m && this.m_inv === this.m_inv, "Body's mass is invalid.");
+ assert(this.i === this.i && this.i_inv === this.i_inv, "Body's moment is invalid.");
+
+ v_assert_sane(this.p, "Body's position is invalid.");
+ v_assert_sane(this.f, "Body's force is invalid.");
+ assert(this.vx === this.vx && Math.abs(this.vx) !== Infinity, "Body's velocity is invalid.");
+ assert(this.vy === this.vy && Math.abs(this.vy) !== Infinity, "Body's velocity is invalid.");
+
+ assert(this.a === this.a && Math.abs(this.a) !== Infinity, "Body's angle is invalid.");
+ assert(this.w === this.w && Math.abs(this.w) !== Infinity, "Body's angular velocity is invalid.");
+ assert(this.t === this.t && Math.abs(this.t) !== Infinity, "Body's torque is invalid.");
+
+ v_assert_sane(this.rot, "Body's rotation vector is invalid.");
+
+ assert(this.v_limit === this.v_limit, "Body's velocity limit is invalid.");
+ assert(this.w_limit === this.w_limit, "Body's angular velocity limit is invalid.");
+ };
+} else {
+ Body.prototype.sanityCheck = function(){};
+}
+
+Body.prototype.getPos = function() { return this.p; };
+Body.prototype.getVel = function() { return new Vect(this.vx, this.vy); };
+Body.prototype.getAngVel = function() { return this.w; };
+// chipmunk v7.0 compatibility
+Body.prototype.getPosition = Body.prototype.getPos;
+Body.prototype.getVelocity = Body.prototype.getVel;
+Body.prototype.getAngularVelocity = Body.prototype.getAngVel;
+Body.prototype.getCenterOfGravity = function() {
+ // FIXME: what is the best way to calculate the center of gravity?
+ // Needed for Chipmunk v7.0 compatibility
+ return this.p;
+};
+
+/// Returns true if the body is sleeping.
+Body.prototype.isSleeping = function()
+{
+ return this.nodeRoot !== null;
+};
+
+/// Returns true if the body is static.
+Body.prototype.isStatic = function()
+{
+ return this.nodeIdleTime === Infinity;
+};
+
+/// Returns true if the body has not been added to a space.
+Body.prototype.isRogue = function()
+{
+ return this.space === null;
+};
+
+// It would be nicer to use defineProperty for this, but its about 30x slower:
+// http://jsperf.com/defineproperty-vs-setter
+Body.prototype.setMass = function(mass)
+{
+ assert(mass > 0, "Mass must be positive and non-zero.");
+
+ //activate is defined in cpSpaceComponent
+ this.activate();
+ this.m = mass;
+ this.m_inv = 1/mass;
+};
+
+Body.prototype.setMoment = function(moment)
+{
+ assert(moment > 0, "Moment of Inertia must be positive and non-zero.");
+
+ this.activate();
+ this.i = moment;
+ this.i_inv = 1/moment;
+};
+
+Body.prototype.addShape = function(shape)
+{
+ this.shapeList.push(shape);
+};
+
+Body.prototype.removeShape = function(shape)
+{
+ // This implementation has a linear time complexity with the number of shapes.
+ // The original implementation used linked lists instead, which might be faster if
+ // you're constantly editing the shape of a body. I expect most bodies will never
+ // have their shape edited, so I'm just going to use the simplest possible implemention.
+ deleteObjFromList(this.shapeList, shape);
+};
+
+var filterConstraints = function(node, body, filter)
+{
+ if(node === filter){
+ return node.next(body);
+ } else if(node.a === body){
+ node.next_a = filterConstraints(node.next_a, body, filter);
+ } else {
+ node.next_b = filterConstraints(node.next_b, body, filter);
+ }
+
+ return node;
+};
+
+Body.prototype.removeConstraint = function(constraint)
+{
+ // The constraint must be in the constraints list when this is called.
+ this.constraintList = filterConstraints(this.constraintList, this, constraint);
+};
+
+Body.prototype.setPos = function(pos)
+{
+ this.activate();
+ this.sanityCheck();
+ // If I allow the position to be set to vzero, vzero will get changed.
+ if (pos === vzero) {
+ pos = cp.v(0,0);
+ }
+ this.p = pos;
+};
+
+Body.prototype.setVel = function(velocity)
+{
+ this.activate();
+ this.vx = velocity.x;
+ this.vy = velocity.y;
+};
+
+Body.prototype.setAngVel = function(w)
+{
+ this.activate();
+ this.w = w;
+};
+
+Body.prototype.setAngleInternal = function(angle)
+{
+ assert(!isNaN(angle), "Internal Error: Attempting to set body's angle to NaN");
+ this.a = angle;//fmod(a, (cpFloat)M_PI*2.0f);
+
+ //this.rot = vforangle(angle);
+ this.rot.x = Math.cos(angle);
+ this.rot.y = Math.sin(angle);
+};
+
+Body.prototype.setAngle = function(angle)
+{
+ this.activate();
+ this.sanityCheck();
+ this.setAngleInternal(angle);
+};
+
+Body.prototype.velocity_func = function(gravity, damping, dt)
+{
+ //this.v = vclamp(vadd(vmult(this.v, damping), vmult(vadd(gravity, vmult(this.f, this.m_inv)), dt)), this.v_limit);
+ var vx = this.vx * damping + (gravity.x + this.f.x * this.m_inv) * dt;
+ var vy = this.vy * damping + (gravity.y + this.f.y * this.m_inv) * dt;
+
+ //var v = vclamp(new Vect(vx, vy), this.v_limit);
+ //this.vx = v.x; this.vy = v.y;
+ var v_limit = this.v_limit;
+ var lensq = vx * vx + vy * vy;
+ var scale = (lensq > v_limit*v_limit) ? v_limit / Math.sqrt(lensq) : 1;
+ this.vx = vx * scale;
+ this.vy = vy * scale;
+
+ var w_limit = this.w_limit;
+ this.w = clamp(this.w*damping + this.t*this.i_inv*dt, -w_limit, w_limit);
+
+ this.sanityCheck();
+};
+
+Body.prototype.position_func = function(dt)
+{
+ //this.p = vadd(this.p, vmult(vadd(this.v, this.v_bias), dt));
+
+ //this.p = this.p + (this.v + this.v_bias) * dt;
+ this.p.x += (this.vx + this.v_biasx) * dt;
+ this.p.y += (this.vy + this.v_biasy) * dt;
+
+ this.setAngleInternal(this.a + (this.w + this.w_bias)*dt);
+
+ this.v_biasx = this.v_biasy = 0;
+ this.w_bias = 0;
+
+ this.sanityCheck();
+};
+
+Body.prototype.resetForces = function()
+{
+ this.activate();
+ this.f = new Vect(0,0);
+ this.t = 0;
+};
+
+Body.prototype.applyForce = function(force, r)
+{
+ this.activate();
+ this.f = vadd(this.f, force);
+ this.t += vcross(r, force);
+};
+
+Body.prototype.applyImpulse = function(j, r)
+{
+ this.activate();
+ apply_impulse(this, j.x, j.y, r);
+};
+
+Body.prototype.getVelAtPoint = function(r)
+{
+ return vadd(new Vect(this.vx, this.vy), vmult(vperp(r), this.w));
+};
+
+/// Get the velocity on a body (in world units) at a point on the body in world coordinates.
+Body.prototype.getVelAtWorldPoint = function(point)
+{
+ return this.getVelAtPoint(vsub(point, this.p));
+};
+
+/// Get the velocity on a body (in world units) at a point on the body in local coordinates.
+Body.prototype.getVelAtLocalPoint = function(point)
+{
+ return this.getVelAtPoint(vrotate(point, this.rot));
+};
+
+Body.prototype.eachShape = function(func)
+{
+ for(var i = 0, len = this.shapeList.length; i < len; i++) {
+ func(this.shapeList[i]);
+ }
+};
+
+Body.prototype.eachConstraint = function(func)
+{
+ var constraint = this.constraintList;
+ while(constraint) {
+ var next = constraint.next(this);
+ func(constraint);
+ constraint = next;
+ }
+};
+
+Body.prototype.eachArbiter = function(func)
+{
+ var arb = this.arbiterList;
+ while(arb){
+ var next = arb.next(this);
+
+ arb.swappedColl = (this === arb.body_b);
+ func(arb);
+
+ arb = next;
+ }
+};
+
+/// Convert body relative/local coordinates to absolute/world coordinates.
+Body.prototype.local2World = function(v)
+{
+ return vadd(this.p, vrotate(v, this.rot));
+};
+
+/// Convert body absolute/world coordinates to relative/local coordinates.
+Body.prototype.world2Local = function(v)
+{
+ return vunrotate(vsub(v, this.p), this.rot);
+};
+// chipmunk v7.0 compatibility
+Body.prototype.localToWorld = Body.prototype.local2World;
+Body.prototype.worldToLocal = Body.prototype.world2Local;
+
+/// Get the kinetic energy of a body.
+Body.prototype.kineticEnergy = function()
+{
+ // Need to do some fudging to avoid NaNs
+ var vsq = this.vx*this.vx + this.vy*this.vy;
+ var wsq = this.w * this.w;
+ return (vsq ? vsq*this.m : 0) + (wsq ? wsq*this.i : 0);
+};
+
+/* Copyright (c) 2010 Scott Lembcke
+ *
+ * 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.
+ */
+
+/**
+ @defgroup cpSpatialIndex cpSpatialIndex
+
+ Spatial indexes are data structures that are used to accelerate collision detection
+ and spatial queries. Chipmunk provides a number of spatial index algorithms to pick from
+ and they are programmed in a generic way so that you can use them for holding more than
+ just Shapes.
+
+ It works by using pointers to the objects you add and using a callback to ask your code
+ for bounding boxes when it needs them. Several types of queries can be performed an index as well
+ as reindexing and full collision information. All communication to the spatial indexes is performed
+ through callback functions.
+
+ Spatial indexes should be treated as opaque structs.
+ This means you shouldn't be reading any of the fields directly.
+
+ All spatial indexes define the following methods:
+
+ // The number of objects in the spatial index.
+ count = 0;
+
+ // Iterate the objects in the spatial index. @c func will be called once for each object.
+ each(func);
+
+ // Returns true if the spatial index contains the given object.
+ // Most spatial indexes use hashed storage, so you must provide a hash value too.
+ contains(obj, hashid);
+
+ // Add an object to a spatial index.
+ insert(obj, hashid);
+
+ // Remove an object from a spatial index.
+ remove(obj, hashid);
+
+ // Perform a full reindex of a spatial index.
+ reindex();
+
+ // Reindex a single object in the spatial index.
+ reindexObject(obj, hashid);
+
+ // Perform a point query against the spatial index, calling @c func for each potential match.
+ // A pointer to the point will be passed as @c obj1 of @c func.
+ // func(shape);
+ pointQuery(point, func);
+
+ // Perform a segment query against the spatial index, calling @c func for each potential match.
+ // func(shape);
+ segmentQuery(vect a, vect b, t_exit, func);
+
+ // Perform a rectangle query against the spatial index, calling @c func for each potential match.
+ // func(shape);
+ query(bb, func);
+
+ // Simultaneously reindex and find all colliding objects.
+ // @c func will be called once for each potentially overlapping pair of objects found.
+ // If the spatial index was initialized with a static index, it will collide it's objects against that as well.
+ reindexQuery(func);
+*/
+
+var SpatialIndex = cp.SpatialIndex = function(staticIndex)
+{
+ this.staticIndex = staticIndex;
+
+
+ if(staticIndex){
+ if(staticIndex.dynamicIndex){
+ throw new Error("This static index is already associated with a dynamic index.");
+ }
+ staticIndex.dynamicIndex = this;
+ }
+};
+
+// Collide the objects in an index against the objects in a staticIndex using the query callback function.
+SpatialIndex.prototype.collideStatic = function(staticIndex, func)
+{
+ if(staticIndex.count > 0){
+ var query = staticIndex.query;
+
+ this.each(function(obj) {
+ query(obj, new BB(obj.bb_l, obj.bb_b, obj.bb_r, obj.bb_t), func);
+ });
+ }
+};
+
+
+/* Copyright (c) 2009 Scott Lembcke
+ *
+ * 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 file implements a modified AABB tree for collision detection.
+
+var BBTree = cp.BBTree = function(staticIndex)
+{
+ SpatialIndex.call(this, staticIndex);
+
+ this.velocityFunc = null;
+
+ // This is a hash from object ID -> object for the objects stored in the BBTree.
+ this.leaves = {};
+ // A count of the number of leaves in the BBTree.
+ this.count = 0;
+
+ this.root = null;
+
+ // A linked list containing an object pool of tree nodes and pairs.
+ this.pooledNodes = null;
+ this.pooledPairs = null;
+
+ this.stamp = 0;
+};
+
+BBTree.prototype = Object.create(SpatialIndex.prototype);
+
+var numNodes = 0;
+
+var Node = function(tree, a, b)
+{
+ this.obj = null;
+ this.bb_l = min(a.bb_l, b.bb_l);
+ this.bb_b = min(a.bb_b, b.bb_b);
+ this.bb_r = max(a.bb_r, b.bb_r);
+ this.bb_t = max(a.bb_t, b.bb_t);
+ this.parent = null;
+
+ this.setA(a);
+ this.setB(b);
+};
+
+BBTree.prototype.makeNode = function(a, b)
+{
+ var node = this.pooledNodes;
+ if(node){
+ this.pooledNodes = node.parent;
+ node.constructor(this, a, b);
+ return node;
+ } else {
+ numNodes++;
+ return new Node(this, a, b);
+ }
+};
+
+var numLeaves = 0;
+var Leaf = function(tree, obj)
+{
+ this.obj = obj;
+ tree.getBB(obj, this);
+
+ this.parent = null;
+
+ this.stamp = 1;
+ this.pairs = null;
+ numLeaves++;
+};
+
+// **** Misc Functions
+
+BBTree.prototype.getBB = function(obj, dest)
+{
+ var velocityFunc = this.velocityFunc;
+ if(velocityFunc){
+ var coef = 0.1;
+ var x = (obj.bb_r - obj.bb_l)*coef;
+ var y = (obj.bb_t - obj.bb_b)*coef;
+
+ var v = vmult(velocityFunc(obj), 0.1);
+
+ dest.bb_l = obj.bb_l + min(-x, v.x);
+ dest.bb_b = obj.bb_b + min(-y, v.y);
+ dest.bb_r = obj.bb_r + max( x, v.x);
+ dest.bb_t = obj.bb_t + max( y, v.y);
+ } else {
+ dest.bb_l = obj.bb_l;
+ dest.bb_b = obj.bb_b;
+ dest.bb_r = obj.bb_r;
+ dest.bb_t = obj.bb_t;
+ }
+};
+
+BBTree.prototype.getStamp = function()
+{
+ var dynamic = this.dynamicIndex;
+ return (dynamic && dynamic.stamp ? dynamic.stamp : this.stamp);
+};
+
+BBTree.prototype.incrementStamp = function()
+{
+ if(this.dynamicIndex && this.dynamicIndex.stamp){
+ this.dynamicIndex.stamp++;
+ } else {
+ this.stamp++;
+ }
+}
+
+// **** Pair/Thread Functions
+
+var numPairs = 0;
+// Objects created with constructors are faster than object literals. :(
+var Pair = function(leafA, nextA, leafB, nextB)
+{
+ this.prevA = null;
+ this.leafA = leafA;
+ this.nextA = nextA;
+
+ this.prevB = null;
+ this.leafB = leafB;
+ this.nextB = nextB;
+};
+
+BBTree.prototype.makePair = function(leafA, nextA, leafB, nextB)
+{
+ //return new Pair(leafA, nextA, leafB, nextB);
+ var pair = this.pooledPairs;
+ if (pair)
+ {
+ this.pooledPairs = pair.prevA;
+
+ pair.prevA = null;
+ pair.leafA = leafA;
+ pair.nextA = nextA;
+
+ pair.prevB = null;
+ pair.leafB = leafB;
+ pair.nextB = nextB;
+
+ //pair.constructor(leafA, nextA, leafB, nextB);
+ return pair;
+ } else {
+ numPairs++;
+ return new Pair(leafA, nextA, leafB, nextB);
+ }
+};
+
+Pair.prototype.recycle = function(tree)
+{
+ this.prevA = tree.pooledPairs;
+ tree.pooledPairs = this;
+};
+
+var unlinkThread = function(prev, leaf, next)
+{
+ if(next){
+ if(next.leafA === leaf) next.prevA = prev; else next.prevB = prev;
+ }
+
+ if(prev){
+ if(prev.leafA === leaf) prev.nextA = next; else prev.nextB = next;
+ } else {
+ leaf.pairs = next;
+ }
+};
+
+Leaf.prototype.clearPairs = function(tree)
+{
+ var pair = this.pairs,
+ next;
+
+ this.pairs = null;
+
+ while(pair){
+ if(pair.leafA === this){
+ next = pair.nextA;
+ unlinkThread(pair.prevB, pair.leafB, pair.nextB);
+ } else {
+ next = pair.nextB;
+ unlinkThread(pair.prevA, pair.leafA, pair.nextA);
+ }
+ pair.recycle(tree);
+ pair = next;
+ }
+};
+
+var pairInsert = function(a, b, tree)
+{
+ var nextA = a.pairs, nextB = b.pairs;
+ var pair = tree.makePair(a, nextA, b, nextB);
+ a.pairs = b.pairs = pair;
+
+ if(nextA){
+ if(nextA.leafA === a) nextA.prevA = pair; else nextA.prevB = pair;
+ }
+
+ if(nextB){
+ if(nextB.leafA === b) nextB.prevA = pair; else nextB.prevB = pair;
+ }
+};
+
+// **** Node Functions
+
+Node.prototype.recycle = function(tree)
+{
+ this.parent = tree.pooledNodes;
+ tree.pooledNodes = this;
+};
+
+Leaf.prototype.recycle = function(tree)
+{
+ // Its not worth the overhead to recycle leaves.
+};
+
+Node.prototype.setA = function(value)
+{
+ this.A = value;
+ value.parent = this;
+};
+
+Node.prototype.setB = function(value)
+{
+ this.B = value;
+ value.parent = this;
+};
+
+Leaf.prototype.isLeaf = true;
+Node.prototype.isLeaf = false;
+
+Node.prototype.otherChild = function(child)
+{
+ return (this.A == child ? this.B : this.A);
+};
+
+Node.prototype.replaceChild = function(child, value, tree)
+{
+ assertSoft(child == this.A || child == this.B, "Node is not a child of parent.");
+
+ if(this.A == child){
+ this.A.recycle(tree);
+ this.setA(value);
+ } else {
+ this.B.recycle(tree);
+ this.setB(value);
+ }
+
+ for(var node=this; node; node = node.parent){
+ //node.bb = bbMerge(node.A.bb, node.B.bb);
+ var a = node.A;
+ var b = node.B;
+ node.bb_l = min(a.bb_l, b.bb_l);
+ node.bb_b = min(a.bb_b, b.bb_b);
+ node.bb_r = max(a.bb_r, b.bb_r);
+ node.bb_t = max(a.bb_t, b.bb_t);
+ }
+};
+
+Node.prototype.bbArea = Leaf.prototype.bbArea = function()
+{
+ return (this.bb_r - this.bb_l)*(this.bb_t - this.bb_b);
+};
+
+var bbTreeMergedArea = function(a, b)
+{
+ return (max(a.bb_r, b.bb_r) - min(a.bb_l, b.bb_l))*(max(a.bb_t, b.bb_t) - min(a.bb_b, b.bb_b));
+};
+
+// **** Subtree Functions
+
+// Would it be better to make these functions instance methods on Node and Leaf?
+
+var bbProximity = function(a, b)
+{
+ return Math.abs(a.bb_l + a.bb_r - b.bb_l - b.bb_r) + Math.abs(a.bb_b + a.bb_t - b.bb_b - b.bb_t);
+};
+
+var subtreeInsert = function(subtree, leaf, tree)
+{
+// var s = new Error().stack;
+// traces[s] = traces[s] ? traces[s]+1 : 1;
+
+ if(subtree == null){
+ return leaf;
+ } else if(subtree.isLeaf){
+ return tree.makeNode(leaf, subtree);
+ } else {
+ var cost_a = subtree.B.bbArea() + bbTreeMergedArea(subtree.A, leaf);
+ var cost_b = subtree.A.bbArea() + bbTreeMergedArea(subtree.B, leaf);
+
+ if(cost_a === cost_b){
+ cost_a = bbProximity(subtree.A, leaf);
+ cost_b = bbProximity(subtree.B, leaf);
+ }
+
+ if(cost_b < cost_a){
+ subtree.setB(subtreeInsert(subtree.B, leaf, tree));
+ } else {
+ subtree.setA(subtreeInsert(subtree.A, leaf, tree));
+ }
+
+// subtree.bb = bbMerge(subtree.bb, leaf.bb);
+ subtree.bb_l = min(subtree.bb_l, leaf.bb_l);
+ subtree.bb_b = min(subtree.bb_b, leaf.bb_b);
+ subtree.bb_r = max(subtree.bb_r, leaf.bb_r);
+ subtree.bb_t = max(subtree.bb_t, leaf.bb_t);
+
+ return subtree;
+ }
+};
+
+Node.prototype.intersectsBB = Leaf.prototype.intersectsBB = function(bb)
+{
+ return (this.bb_l <= bb.r && bb.l <= this.bb_r && this.bb_b <= bb.t && bb.b <= this.bb_t);
+};
+
+var subtreeQuery = function(subtree, bb, func)
+{
+ //if(bbIntersectsBB(subtree.bb, bb)){
+ if(subtree.intersectsBB(bb)){
+ if(subtree.isLeaf){
+ func(subtree.obj);
+ } else {
+ subtreeQuery(subtree.A, bb, func);
+ subtreeQuery(subtree.B, bb, func);
+ }
+ }
+};
+
+/// Returns the fraction along the segment query the node hits. Returns Infinity if it doesn't hit.
+var nodeSegmentQuery = function(node, a, b)
+{
+ var idx = 1/(b.x - a.x);
+ var tx1 = (node.bb_l == a.x ? -Infinity : (node.bb_l - a.x)*idx);
+ var tx2 = (node.bb_r == a.x ? Infinity : (node.bb_r - a.x)*idx);
+ var txmin = min(tx1, tx2);
+ var txmax = max(tx1, tx2);
+
+ var idy = 1/(b.y - a.y);
+ var ty1 = (node.bb_b == a.y ? -Infinity : (node.bb_b - a.y)*idy);
+ var ty2 = (node.bb_t == a.y ? Infinity : (node.bb_t - a.y)*idy);
+ var tymin = min(ty1, ty2);
+ var tymax = max(ty1, ty2);
+
+ if(tymin <= txmax && txmin <= tymax){
+ var min_ = max(txmin, tymin);
+ var max_ = min(txmax, tymax);
+
+ if(0.0 <= max_ && min_ <= 1.0) return max(min_, 0.0);
+ }
+
+ return Infinity;
+};
+
+var subtreeSegmentQuery = function(subtree, a, b, t_exit, func)
+{
+ if(subtree.isLeaf){
+ return func(subtree.obj);
+ } else {
+ var t_a = nodeSegmentQuery(subtree.A, a, b);
+ var t_b = nodeSegmentQuery(subtree.B, a, b);
+
+ if(t_a < t_b){
+ if(t_a < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.A, a, b, t_exit, func));
+ if(t_b < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.B, a, b, t_exit, func));
+ } else {
+ if(t_b < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.B, a, b, t_exit, func));
+ if(t_a < t_exit) t_exit = min(t_exit, subtreeSegmentQuery(subtree.A, a, b, t_exit, func));
+ }
+
+ return t_exit;
+ }
+};
+
+BBTree.prototype.subtreeRecycle = function(node)
+{
+ if(node.isLeaf){
+ this.subtreeRecycle(node.A);
+ this.subtreeRecycle(node.B);
+ node.recycle(this);
+ }
+};
+
+var subtreeRemove = function(subtree, leaf, tree)
+{
+ if(leaf == subtree){
+ return null;
+ } else {
+ var parent = leaf.parent;
+ if(parent == subtree){
+ var other = subtree.otherChild(leaf);
+ other.parent = subtree.parent;
+ subtree.recycle(tree);
+ return other;
+ } else {
+ parent.parent.replaceChild(parent, parent.otherChild(leaf), tree);
+ return subtree;
+ }
+ }
+};
+
+// **** Marking Functions
+
+/*
+typedef struct MarkContext {
+ bbTree *tree;
+ Node *staticRoot;
+ cpSpatialIndexQueryFunc func;
+} MarkContext;
+*/
+
+var bbTreeIntersectsNode = function(a, b)
+{
+ return (a.bb_l <= b.bb_r && b.bb_l <= a.bb_r && a.bb_b <= b.bb_t && b.bb_b <= a.bb_t);
+};
+
+Leaf.prototype.markLeafQuery = function(leaf, left, tree, func)
+{
+ if(bbTreeIntersectsNode(leaf, this)){
+ if(left){
+ pairInsert(leaf, this, tree);
+ } else {
+ if(this.stamp < leaf.stamp) pairInsert(this, leaf, tree);
+ if(func) func(leaf.obj, this.obj);
+ }
+ }
+};
+
+Node.prototype.markLeafQuery = function(leaf, left, tree, func)
+{
+ if(bbTreeIntersectsNode(leaf, this)){
+ this.A.markLeafQuery(leaf, left, tree, func);
+ this.B.markLeafQuery(leaf, left, tree, func);
+ }
+};
+
+Leaf.prototype.markSubtree = function(tree, staticRoot, func)
+{
+ if(this.stamp == tree.getStamp()){
+ if(staticRoot) staticRoot.markLeafQuery(this, false, tree, func);
+
+ for(var node = this; node.parent; node = node.parent){
+ if(node == node.parent.A){
+ node.parent.B.markLeafQuery(this, true, tree, func);
+ } else {
+ node.parent.A.markLeafQuery(this, false, tree, func);
+ }
+ }
+ } else {
+ var pair = this.pairs;
+ while(pair){
+ if(this === pair.leafB){
+ if(func) func(pair.leafA.obj, this.obj);
+ pair = pair.nextB;
+ } else {
+ pair = pair.nextA;
+ }
+ }
+ }
+};
+
+Node.prototype.markSubtree = function(tree, staticRoot, func)
+{
+ this.A.markSubtree(tree, staticRoot, func);
+ this.B.markSubtree(tree, staticRoot, func);
+};
+
+// **** Leaf Functions
+
+Leaf.prototype.containsObj = function(obj)
+{
+ return (this.bb_l <= obj.bb_l && this.bb_r >= obj.bb_r && this.bb_b <= obj.bb_b && this.bb_t >= obj.bb_t);
+};
+
+Leaf.prototype.update = function(tree)
+{
+ var root = tree.root;
+ var obj = this.obj;
+
+ //if(!bbContainsBB(this.bb, bb)){
+ if(!this.containsObj(obj)){
+ tree.getBB(this.obj, this);
+
+ root = subtreeRemove(root, this, tree);
+ tree.root = subtreeInsert(root, this, tree);
+
+ this.clearPairs(tree);
+ this.stamp = tree.getStamp();
+
+ return true;
+ }
+
+ return false;
+};
+
+Leaf.prototype.addPairs = function(tree)
+{
+ var dynamicIndex = tree.dynamicIndex;
+ if(dynamicIndex){
+ var dynamicRoot = dynamicIndex.root;
+ if(dynamicRoot){
+ dynamicRoot.markLeafQuery(this, true, dynamicIndex, null);
+ }
+ } else {
+ var staticRoot = tree.staticIndex.root;
+ this.markSubtree(tree, staticRoot, null);
+ }
+};
+
+// **** Insert/Remove
+
+BBTree.prototype.insert = function(obj, hashid)
+{
+ var leaf = new Leaf(this, obj);
+
+ this.leaves[hashid] = leaf;
+ this.root = subtreeInsert(this.root, leaf, this);
+ this.count++;
+
+ leaf.stamp = this.getStamp();
+ leaf.addPairs(this);
+ this.incrementStamp();
+};
+
+BBTree.prototype.remove = function(obj, hashid)
+{
+ var leaf = this.leaves[hashid];
+
+ delete this.leaves[hashid];
+ this.root = subtreeRemove(this.root, leaf, this);
+ this.count--;
+
+ leaf.clearPairs(this);
+ leaf.recycle(this);
+};
+
+BBTree.prototype.contains = function(obj, hashid)
+{
+ return this.leaves[hashid] != null;
+};
+
+// **** Reindex
+var voidQueryFunc = function(obj1, obj2){};
+
+BBTree.prototype.reindexQuery = function(func)
+{
+ if(!this.root) return;
+
+ // LeafUpdate() may modify this.root. Don't cache it.
+ var hashid,
+ leaves = this.leaves;
+ for (hashid in leaves)
+ {
+ leaves[hashid].update(this);
+ }
+
+ var staticIndex = this.staticIndex;
+ var staticRoot = staticIndex && staticIndex.root;
+
+ this.root.markSubtree(this, staticRoot, func);
+ if(staticIndex && !staticRoot) this.collideStatic(this, staticIndex, func);
+
+ this.incrementStamp();
+};
+
+BBTree.prototype.reindex = function()
+{
+ this.reindexQuery(voidQueryFunc);
+};
+
+BBTree.prototype.reindexObject = function(obj, hashid)
+{
+ var leaf = this.leaves[hashid];
+ if(leaf){
+ if(leaf.update(this)) leaf.addPairs(this);
+ this.incrementStamp();
+ }
+};
+
+// **** Query
+
+// This has since been removed from upstream Chipmunk - which recommends you just use query() below
+// directly.
+BBTree.prototype.pointQuery = function(point, func)
+{
+ this.query(new BB(point.x, point.y, point.x, point.y), func);
+};
+
+BBTree.prototype.segmentQuery = function(a, b, t_exit, func)
+{
+ if(this.root) subtreeSegmentQuery(this.root, a, b, t_exit, func);
+};
+
+BBTree.prototype.query = function(bb, func)
+{
+ if(this.root) subtreeQuery(this.root, bb, func);
+};
+
+// **** Misc
+
+BBTree.prototype.count = function()
+{
+ return this.count;
+};
+
+BBTree.prototype.each = function(func)
+{
+ var hashid;
+ for(hashid in this.leaves)
+ {
+ func(this.leaves[hashid].obj);
+ }
+};
+
+// **** Tree Optimization
+
+var bbTreeMergedArea2 = function(node, l, b, r, t)
+{
+ return (max(node.bb_r, r) - min(node.bb_l, l))*(max(node.bb_t, t) - min(node.bb_b, b));
+};
+
+var partitionNodes = function(tree, nodes, offset, count)
+{
+ if(count == 1){
+ return nodes[offset];
+ } else if(count == 2) {
+ return tree.makeNode(nodes[offset], nodes[offset + 1]);
+ }
+
+ // Find the AABB for these nodes
+ //var bb = nodes[offset].bb;
+ var node = nodes[offset];
+ var bb_l = node.bb_l,
+ bb_b = node.bb_b,
+ bb_r = node.bb_r,
+ bb_t = node.bb_t;
+
+ var end = offset + count;
+ for(var i=offset + 1; i bb_t - bb_b);
+
+ // Sort the bounds and use the median as the splitting point
+ var bounds = new Array(count*2);
+ if(splitWidth){
+ for(var i=offset; inext = next;
+ if(prev.body_a === body) {
+ prev.thread_a_next = next;
+ } else {
+ prev.thread_b_next = next;
+ }
+ } else {
+ body.arbiterList = next;
+ }
+
+ if(next){
+ // cpArbiterThreadForBody(next, body)->prev = prev;
+ if(next.body_a === body){
+ next.thread_a_prev = prev;
+ } else {
+ next.thread_b_prev = prev;
+ }
+ }
+};
+
+Arbiter.prototype.unthread = function()
+{
+ unthreadHelper(this, this.body_a, this.thread_a_prev, this.thread_a_next);
+ unthreadHelper(this, this.body_b, this.thread_b_prev, this.thread_b_next);
+ this.thread_a_prev = this.thread_a_next = null;
+ this.thread_b_prev = this.thread_b_next = null;
+};
+
+//cpFloat
+//cpContactsEstimateCrushingImpulse(cpContact *contacts, int numContacts)
+//{
+// cpFloat fsum = 0;
+// cpVect vsum = vzero;
+//
+// for(int i=0; i= mindist*mindist) return;
+
+ var dist = Math.sqrt(distsq);
+
+ // Allocate and initialize the contact.
+ return new Contact(
+ vadd(p1, vmult(delta, 0.5 + (r1 - 0.5*mindist)/(dist ? dist : Infinity))),
+ (dist ? vmult(delta, 1/dist) : new Vect(1, 0)),
+ dist - mindist,
+ 0
+ );
+};
+
+// Collide circle shapes.
+var circle2circle = function(circ1, circ2)
+{
+ var contact = circle2circleQuery(circ1.tc, circ2.tc, circ1.r, circ2.r);
+ return contact ? [contact] : NONE;
+};
+
+var circle2segment = function(circleShape, segmentShape)
+{
+ var seg_a = segmentShape.ta;
+ var seg_b = segmentShape.tb;
+ var center = circleShape.tc;
+
+ var seg_delta = vsub(seg_b, seg_a);
+ var closest_t = clamp01(vdot(seg_delta, vsub(center, seg_a))/vlengthsq(seg_delta));
+ var closest = vadd(seg_a, vmult(seg_delta, closest_t));
+
+ var contact = circle2circleQuery(center, closest, circleShape.r, segmentShape.r);
+ if(contact){
+ var n = contact.n;
+
+ // Reject endcap collisions if tangents are provided.
+ return (
+ (closest_t === 0 && vdot(n, segmentShape.a_tangent) < 0) ||
+ (closest_t === 1 && vdot(n, segmentShape.b_tangent) < 0)
+ ) ? NONE : [contact];
+ } else {
+ return NONE;
+ }
+}
+
+// Find the minimum separating axis for the given poly and axis list.
+//
+// This function needs to return two values - the index of the min. separating axis and
+// the value itself. Short of inlining MSA, returning values through a global like this
+// is the fastest implementation.
+//
+// See: http://jsperf.com/return-two-values-from-function/2
+var last_MSA_min = 0;
+var findMSA = function(poly, planes)
+{
+ var min_index = 0;
+ var min = poly.valueOnAxis(planes[0].n, planes[0].d);
+ if(min > 0) return -1;
+
+ for(var i=1; i 0) {
+ return -1;
+ } else if(dist > min){
+ min = dist;
+ min_index = i;
+ }
+ }
+
+ last_MSA_min = min;
+ return min_index;
+};
+
+// Add contacts for probably penetrating vertexes.
+// This handles the degenerate case where an overlap was detected, but no vertexes fall inside
+// the opposing polygon. (like a star of david)
+var findVertsFallback = function(poly1, poly2, n, dist)
+{
+ var arr = [];
+
+ var verts1 = poly1.tVerts;
+ for(var i=0; i>1)));
+ }
+ }
+
+ var verts2 = poly2.tVerts;
+ for(var i=0; i>1)));
+ }
+ }
+
+ return (arr.length ? arr : findVertsFallback(poly1, poly2, n, dist));
+};
+
+// Collide poly shapes together.
+var poly2poly = function(poly1, poly2)
+{
+ var mini1 = findMSA(poly2, poly1.tPlanes);
+ if(mini1 == -1) return NONE;
+ var min1 = last_MSA_min;
+
+ var mini2 = findMSA(poly1, poly2.tPlanes);
+ if(mini2 == -1) return NONE;
+ var min2 = last_MSA_min;
+
+ // There is overlap, find the penetrating verts
+ if(min1 > min2)
+ return findVerts(poly1, poly2, poly1.tPlanes[mini1].n, min1);
+ else
+ return findVerts(poly1, poly2, vneg(poly2.tPlanes[mini2].n), min2);
+};
+
+// Like cpPolyValueOnAxis(), but for segments.
+var segValueOnAxis = function(seg, n, d)
+{
+ var a = vdot(n, seg.ta) - seg.r;
+ var b = vdot(n, seg.tb) - seg.r;
+ return min(a, b) - d;
+};
+
+// Identify vertexes that have penetrated the segment.
+var findPointsBehindSeg = function(arr, seg, poly, pDist, coef)
+{
+ var dta = vcross(seg.tn, seg.ta);
+ var dtb = vcross(seg.tn, seg.tb);
+ var n = vmult(seg.tn, coef);
+
+ var verts = poly.tVerts;
+ for(var i=0; i= dt && dt >= dtb){
+ arr.push(new Contact(new Vect(vx, vy), n, pDist, hashPair(poly.hashid, i)));
+ }
+ }
+ }
+};
+
+// This one is complicated and gross. Just don't go there...
+// TODO: Comment me!
+var seg2poly = function(seg, poly)
+{
+ var arr = [];
+
+ var planes = poly.tPlanes;
+ var numVerts = planes.length;
+
+ var segD = vdot(seg.tn, seg.ta);
+ var minNorm = poly.valueOnAxis(seg.tn, segD) - seg.r;
+ var minNeg = poly.valueOnAxis(vneg(seg.tn), -segD) - seg.r;
+ if(minNeg > 0 || minNorm > 0) return NONE;
+
+ var mini = 0;
+ var poly_min = segValueOnAxis(seg, planes[0].n, planes[0].d);
+ if(poly_min > 0) return NONE;
+ for(var i=0; i 0){
+ return NONE;
+ } else if(dist > poly_min){
+ poly_min = dist;
+ mini = i;
+ }
+ }
+
+ var poly_n = vneg(planes[mini].n);
+
+ var va = vadd(seg.ta, vmult(poly_n, seg.r));
+ var vb = vadd(seg.tb, vmult(poly_n, seg.r));
+ if(poly.containsVert(va.x, va.y))
+ arr.push(new Contact(va, poly_n, poly_min, hashPair(seg.hashid, 0)));
+ if(poly.containsVert(vb.x, vb.y))
+ arr.push(new Contact(vb, poly_n, poly_min, hashPair(seg.hashid, 1)));
+
+ // Floating point precision problems here.
+ // This will have to do for now.
+// poly_min -= cp_collision_slop; // TODO is this needed anymore?
+
+ if(minNorm >= poly_min || minNeg >= poly_min) {
+ if(minNorm > minNeg)
+ findPointsBehindSeg(arr, seg, poly, minNorm, 1);
+ else
+ findPointsBehindSeg(arr, seg, poly, minNeg, -1);
+ }
+
+ // If no other collision points are found, try colliding endpoints.
+ if(arr.length === 0){
+ var mini2 = mini * 2;
+ var verts = poly.tVerts;
+
+ var poly_a = new Vect(verts[mini2], verts[mini2+1]);
+
+ var con;
+ if((con = circle2circleQuery(seg.ta, poly_a, seg.r, 0, arr))) return [con];
+ if((con = circle2circleQuery(seg.tb, poly_a, seg.r, 0, arr))) return [con];
+
+ var len = numVerts * 2;
+ var poly_b = new Vect(verts[(mini2+2)%len], verts[(mini2+3)%len]);
+ if((con = circle2circleQuery(seg.ta, poly_b, seg.r, 0, arr))) return [con];
+ if((con = circle2circleQuery(seg.tb, poly_b, seg.r, 0, arr))) return [con];
+ }
+
+// console.log(poly.tVerts, poly.tPlanes);
+// console.log('seg2poly', arr);
+ return arr;
+};
+
+// This one is less gross, but still gross.
+// TODO: Comment me!
+var circle2poly = function(circ, poly)
+{
+ var planes = poly.tPlanes;
+
+ var mini = 0;
+ var min = vdot(planes[0].n, circ.tc) - planes[0].d - circ.r;
+ for(var i=0; i 0){
+ return NONE;
+ } else if(dist > min) {
+ min = dist;
+ mini = i;
+ }
+ }
+
+ var n = planes[mini].n;
+
+ var verts = poly.tVerts;
+ var len = verts.length;
+ var mini2 = mini<<1;
+
+ //var a = poly.tVerts[mini];
+ //var b = poly.tVerts[(mini + 1)%poly.tVerts.length];
+ var ax = verts[mini2];
+ var ay = verts[mini2+1];
+ var bx = verts[(mini2+2)%len];
+ var by = verts[(mini2+3)%len];
+
+ var dta = vcross2(n.x, n.y, ax, ay);
+ var dtb = vcross2(n.x, n.y, bx, by);
+ var dt = vcross(n, circ.tc);
+
+ if(dt < dtb){
+ var con = circle2circleQuery(circ.tc, new Vect(bx, by), circ.r, 0, con);
+ return con ? [con] : NONE;
+ } else if(dt < dta) {
+ return [new Contact(
+ vsub(circ.tc, vmult(n, circ.r + min/2)),
+ vneg(n),
+ min,
+ 0
+ )];
+ } else {
+ var con = circle2circleQuery(circ.tc, new Vect(ax, ay), circ.r, 0, con);
+ return con ? [con] : NONE;
+ }
+};
+
+// The javascripty way to do this would be either nested object or methods on the prototypes.
+//
+// However, the *fastest* way is the method below.
+// See: http://jsperf.com/dispatch
+
+// These are copied from the prototypes into the actual objects in the Shape constructor.
+CircleShape.prototype.collisionCode = 0;
+SegmentShape.prototype.collisionCode = 1;
+PolyShape.prototype.collisionCode = 2;
+
+CircleShape.prototype.collisionTable = [
+ circle2circle,
+ circle2segment,
+ circle2poly
+];
+
+SegmentShape.prototype.collisionTable = [
+ null,
+ function(segA, segB) { return NONE; }, // seg2seg
+ seg2poly
+];
+
+PolyShape.prototype.collisionTable = [
+ null,
+ null,
+ poly2poly
+];
+
+var collideShapes = cp.collideShapes = function(a, b)
+{
+ assert(a.collisionCode <= b.collisionCode, 'Collided shapes must be sorted by type');
+ return a.collisionTable[b.collisionCode](a, b);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var defaultCollisionHandler = new CollisionHandler();
+
+/// Basic Unit of Simulation in Chipmunk
+var Space = cp.Space = function() {
+ this.stamp = 0;
+ this.curr_dt = 0;
+
+ this.bodies = [];
+ this.rousedBodies = [];
+ this.sleepingComponents = [];
+
+ this.staticShapes = new BBTree(null);
+ this.activeShapes = new BBTree(this.staticShapes);
+
+ this.arbiters = [];
+ this.contactBuffersHead = null;
+ this.cachedArbiters = {};
+ //this.pooledArbiters = [];
+
+ this.constraints = [];
+
+ this.locked = 0;
+
+ this.collisionHandlers = {};
+ this.defaultHandler = defaultCollisionHandler;
+
+ this.postStepCallbacks = [];
+
+ /// Number of iterations to use in the impulse solver to solve contacts.
+ this.iterations = 10;
+
+ /// Gravity to pass to rigid bodies when integrating velocity.
+ this.gravity = vzero;
+
+ /// Damping rate expressed as the fraction of velocity bodies retain each second.
+ /// A value of 0.9 would mean that each body's velocity will drop 10% per second.
+ /// The default value is 1.0, meaning no damping is applied.
+ /// @note This damping value is different than those of cpDampedSpring and cpDampedRotarySpring.
+ this.damping = 1;
+
+ /// Speed threshold for a body to be considered idle.
+ /// The default value of 0 means to let the space guess a good threshold based on gravity.
+ this.idleSpeedThreshold = 0;
+
+ /// Time a group of bodies must remain idle in order to fall asleep.
+ /// Enabling sleeping also implicitly enables the the contact graph.
+ /// The default value of Infinity disables the sleeping algorithm.
+ this.sleepTimeThreshold = Infinity;
+
+ /// Amount of encouraged penetration between colliding shapes..
+ /// Used to reduce oscillating contacts and keep the collision cache warm.
+ /// Defaults to 0.1. If you have poor simulation quality,
+ /// increase this number as much as possible without allowing visible amounts of overlap.
+ this.collisionSlop = 0.1;
+
+ /// Determines how fast overlapping shapes are pushed apart.
+ /// Expressed as a fraction of the error remaining after each second.
+ /// Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz.
+ this.collisionBias = Math.pow(1 - 0.1, 60);
+
+ /// Number of frames that contact information should persist.
+ /// Defaults to 3. There is probably never a reason to change this value.
+ this.collisionPersistence = 3;
+
+ /// Rebuild the contact graph during each step. Must be enabled to use the cpBodyEachArbiter() function.
+ /// Disabled by default for a small performance boost. Enabled implicitly when the sleeping feature is enabled.
+ this.enableContactGraph = false;
+
+ /// The designated static body for this space.
+ /// You can modify this body, or replace it with your own static body.
+ /// By default it points to a statically allocated cpBody in the cpSpace struct.
+ this.staticBody = new Body(Infinity, Infinity);
+ this.staticBody.nodeIdleTime = Infinity;
+
+ // Cache the collideShapes callback function for the space.
+ this.collideShapes = this.makeCollideShapes();
+};
+
+Space.prototype.getCurrentTimeStep = function() { return this.curr_dt; };
+
+Space.prototype.setIterations = function(iter) { this.iterations = iter; };
+
+/// returns true from inside a callback and objects cannot be added/removed.
+Space.prototype.isLocked = function()
+{
+ return this.locked;
+};
+
+var assertSpaceUnlocked = function(space)
+{
+ assert(!space.locked, "This addition/removal cannot be done safely during a call to cpSpaceStep() \
+ or during a query. Put these calls into a post-step callback.");
+};
+
+// **** Collision handler function management
+
+/// Set a collision handler to be used whenever the two shapes with the given collision types collide.
+/// You can pass null for any function you don't want to implement.
+Space.prototype.addCollisionHandler = function(a, b, begin, preSolve, postSolve, separate)
+{
+ assertSpaceUnlocked(this);
+
+ // Remove any old function so the new one will get added.
+ this.removeCollisionHandler(a, b);
+
+ var handler = new CollisionHandler();
+ handler.a = a;
+ handler.b = b;
+ if(begin) handler.begin = begin;
+ if(preSolve) handler.preSolve = preSolve;
+ if(postSolve) handler.postSolve = postSolve;
+ if(separate) handler.separate = separate;
+
+ this.collisionHandlers[hashPair(a, b)] = handler;
+};
+
+/// Unset a collision handler.
+Space.prototype.removeCollisionHandler = function(a, b)
+{
+ assertSpaceUnlocked(this);
+
+ delete this.collisionHandlers[hashPair(a, b)];
+};
+
+/// Set a default collision handler for this space.
+/// The default collision handler is invoked for each colliding pair of shapes
+/// that isn't explicitly handled by a specific collision handler.
+/// You can pass null for any function you don't want to implement.
+Space.prototype.setDefaultCollisionHandler = function(begin, preSolve, postSolve, separate)
+{
+ assertSpaceUnlocked(this);
+
+ var handler = new CollisionHandler();
+ if(begin) handler.begin = begin;
+ if(preSolve) handler.preSolve = preSolve;
+ if(postSolve) handler.postSolve = postSolve;
+ if(separate) handler.separate = separate;
+
+ this.defaultHandler = handler;
+};
+
+Space.prototype.lookupHandler = function(a, b)
+{
+ return this.collisionHandlers[hashPair(a, b)] || this.defaultHandler;
+};
+
+// **** Body, Shape, and Joint Management
+
+/// Add a collision shape to the simulation.
+/// If the shape is attached to a static body, it will be added as a static shape.
+Space.prototype.addShape = function(shape)
+{
+ var body = shape.body;
+ if(body.isStatic()) return this.addStaticShape(shape);
+
+ assert(!shape.space, "This shape is already added to a space and cannot be added to another.");
+ assertSpaceUnlocked(this);
+
+ body.activate();
+ body.addShape(shape);
+
+ shape.update(body.p, body.rot);
+ this.activeShapes.insert(shape, shape.hashid);
+ shape.space = this;
+
+ return shape;
+};
+
+/// Explicity add a shape as a static shape to the simulation.
+Space.prototype.addStaticShape = function(shape)
+{
+ assert(!shape.space, "This shape is already added to a space and cannot be added to another.");
+ assertSpaceUnlocked(this);
+
+ var body = shape.body;
+ body.addShape(shape);
+
+ shape.update(body.p, body.rot);
+ this.staticShapes.insert(shape, shape.hashid);
+ shape.space = this;
+
+ return shape;
+};
+
+/// Add a rigid body to the simulation.
+Space.prototype.addBody = function(body)
+{
+ assert(!body.isStatic(), "Static bodies cannot be added to a space as they are not meant to be simulated.");
+ assert(!body.space, "This body is already added to a space and cannot be added to another.");
+ assertSpaceUnlocked(this);
+
+ this.bodies.push(body);
+ body.space = this;
+
+ return body;
+};
+
+/// Add a constraint to the simulation.
+Space.prototype.addConstraint = function(constraint)
+{
+ assert(!constraint.space, "This shape is already added to a space and cannot be added to another.");
+ assertSpaceUnlocked(this);
+
+ var a = constraint.a, b = constraint.b;
+
+ a.activate();
+ b.activate();
+ this.constraints.push(constraint);
+
+ // Push onto the heads of the bodies' constraint lists
+ constraint.next_a = a.constraintList; a.constraintList = constraint;
+ constraint.next_b = b.constraintList; b.constraintList = constraint;
+ constraint.space = this;
+
+ return constraint;
+};
+
+Space.prototype.filterArbiters = function(body, filter)
+{
+ for (var hash in this.cachedArbiters)
+ {
+ var arb = this.cachedArbiters[hash];
+
+ // Match on the filter shape, or if it's null the filter body
+ if(
+ (body === arb.body_a && (filter === arb.a || filter === null)) ||
+ (body === arb.body_b && (filter === arb.b || filter === null))
+ ){
+ // Call separate when removing shapes.
+ if(filter && arb.state !== 'cached') arb.callSeparate(this);
+
+ arb.unthread();
+
+ deleteObjFromList(this.arbiters, arb);
+ //this.pooledArbiters.push(arb);
+
+ delete this.cachedArbiters[hash];
+ }
+ }
+};
+
+/// Remove a collision shape from the simulation.
+Space.prototype.removeShape = function(shape)
+{
+ var body = shape.body;
+ if(body.isStatic()){
+ this.removeStaticShape(shape);
+ } else {
+ assert(this.containsShape(shape),
+ "Cannot remove a shape that was not added to the space. (Removed twice maybe?)");
+ assertSpaceUnlocked(this);
+
+ body.activate();
+ body.removeShape(shape);
+ this.filterArbiters(body, shape);
+ this.activeShapes.remove(shape, shape.hashid);
+ shape.space = null;
+ }
+};
+
+/// Remove a collision shape added using addStaticShape() from the simulation.
+Space.prototype.removeStaticShape = function(shape)
+{
+ assert(this.containsShape(shape),
+ "Cannot remove a static or sleeping shape that was not added to the space. (Removed twice maybe?)");
+ assertSpaceUnlocked(this);
+
+ var body = shape.body;
+ if(body.isStatic()) body.activateStatic(shape);
+ body.removeShape(shape);
+ this.filterArbiters(body, shape);
+ this.staticShapes.remove(shape, shape.hashid);
+ shape.space = null;
+};
+
+/// Remove a rigid body from the simulation.
+Space.prototype.removeBody = function(body)
+{
+ assert(this.containsBody(body),
+ "Cannot remove a body that was not added to the space. (Removed twice maybe?)");
+ assertSpaceUnlocked(this);
+
+ body.activate();
+// this.filterArbiters(body, null);
+ deleteObjFromList(this.bodies, body);
+ body.space = null;
+};
+
+/// Remove a constraint from the simulation.
+Space.prototype.removeConstraint = function(constraint)
+{
+ assert(this.containsConstraint(constraint),
+ "Cannot remove a constraint that was not added to the space. (Removed twice maybe?)");
+ assertSpaceUnlocked(this);
+
+ constraint.a.activate();
+ constraint.b.activate();
+ deleteObjFromList(this.constraints, constraint);
+
+ constraint.a.removeConstraint(constraint);
+ constraint.b.removeConstraint(constraint);
+ constraint.space = null;
+};
+
+/// Test if a collision shape has been added to the space.
+Space.prototype.containsShape = function(shape)
+{
+ return (shape.space === this);
+};
+
+/// Test if a rigid body has been added to the space.
+Space.prototype.containsBody = function(body)
+{
+ return (body.space == this);
+};
+
+/// Test if a constraint has been added to the space.
+Space.prototype.containsConstraint = function(constraint)
+{
+ return (constraint.space == this);
+};
+
+Space.prototype.uncacheArbiter = function(arb)
+{
+ delete this.cachedArbiters[hashPair(arb.a.hashid, arb.b.hashid)];
+ deleteObjFromList(this.arbiters, arb);
+};
+
+
+// **** Iteration
+
+/// Call @c func for each body in the space.
+Space.prototype.eachBody = function(func)
+{
+ this.lock(); {
+ var bodies = this.bodies;
+
+ for(var i=0; i keThreshold ? 0 : body.nodeIdleTime + dt);
+ }
+ }
+
+ // Awaken any sleeping bodies found and then push arbiters to the bodies' lists.
+ var arbiters = this.arbiters;
+ for(var i=0, count=arbiters.length; i= 0, "Internal Error: Space lock underflow.");
+
+ if(this.locked === 0 && runPostStep){
+ var waking = this.rousedBodies;
+ for(var i=0; i this.collisionPersistence){
+ // The tail buffer is available, rotate the ring
+ var tail = head.next;
+ tail.stamp = stamp;
+ tail.contacts.length = 0;
+ this.contactBuffersHead = tail;
+ } else {
+ // Allocate a new buffer and push it into the ring
+ var buffer = new ContactBuffer(stamp, head);
+ this.contactBuffersHead = head.next = buffer;
+ }
+};
+
+cpContact *
+cpContactBufferGetArray(cpSpace *space)
+{
+ if(space.contactBuffersHead.numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE){
+ // contact buffer could overflow on the next collision, push a fresh one.
+ space.pushFreshContactBuffer();
+ }
+
+ cpContactBufferHeader *head = space.contactBuffersHead;
+ return ((cpContactBuffer *)head)->contacts + head.numContacts;
+}
+
+void
+cpSpacePushContacts(cpSpace *space, int count)
+{
+ cpAssertHard(count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal Error: Contact buffer overflow!");
+ space.contactBuffersHead.numContacts += count;
+}
+
+static void
+cpSpacePopContacts(cpSpace *space, int count){
+ space.contactBuffersHead.numContacts -= count;
+}
+*/
+
+// **** Collision Detection Functions
+
+/* Use this to re-enable object pools.
+static void *
+cpSpaceArbiterSetTrans(cpShape **shapes, cpSpace *space)
+{
+ if(space.pooledArbiters.num == 0){
+ // arbiter pool is exhausted, make more
+ int count = CP_BUFFER_BYTES/sizeof(cpArbiter);
+ cpAssertHard(count, "Internal Error: Buffer size too small.");
+
+ cpArbiter *buffer = (cpArbiter *)cpcalloc(1, CP_BUFFER_BYTES);
+ cpArrayPush(space.allocatedBuffers, buffer);
+
+ for(int i=0; i b.collisionCode){
+ var temp = a;
+ a = b;
+ b = temp;
+ }
+
+ // Narrow-phase collision detection.
+ //cpContact *contacts = cpContactBufferGetArray(space);
+ //int numContacts = cpCollideShapes(a, b, contacts);
+ var contacts = collideShapes(a, b);
+ if(contacts.length === 0) return; // Shapes are not colliding.
+ //cpSpacePushContacts(space, numContacts);
+
+ // Get an arbiter from space.arbiterSet for the two shapes.
+ // This is where the persistent contact magic comes from.
+ var arbHash = hashPair(a.hashid, b.hashid);
+ var arb = space.cachedArbiters[arbHash];
+ if (!arb){
+ arb = space.cachedArbiters[arbHash] = new Arbiter(a, b);
+ }
+
+ arb.update(contacts, handler, a, b);
+
+ // Call the begin function first if it's the first step
+ if(arb.state == 'first coll' && !handler.begin(arb, space)){
+ arb.ignore(); // permanently ignore the collision until separation
+ }
+
+ if(
+ // Ignore the arbiter if it has been flagged
+ (arb.state !== 'ignore') &&
+ // Call preSolve
+ handler.preSolve(arb, space) &&
+ // Process, but don't add collisions for sensors.
+ !sensor
+ ){
+ space.arbiters.push(arb);
+ } else {
+ //cpSpacePopContacts(space, numContacts);
+
+ arb.contacts = null;
+
+ // Normally arbiters are set as used after calling the post-solve callback.
+ // However, post-solve callbacks are not called for sensors or arbiters rejected from pre-solve.
+ if(arb.state !== 'ignore') arb.state = 'normal';
+ }
+
+ // Time stamp the arbiter so we know it was used recently.
+ arb.stamp = space.stamp;
+ };
+};
+
+// Hashset filter func to throw away old arbiters.
+Space.prototype.arbiterSetFilter = function(arb)
+{
+ var ticks = this.stamp - arb.stamp;
+
+ var a = arb.body_a, b = arb.body_b;
+
+ // TODO should make an arbiter state for this so it doesn't require filtering arbiters for
+ // dangling body pointers on body removal.
+ // Preserve arbiters on sensors and rejected arbiters for sleeping objects.
+ // This prevents errant separate callbacks from happenening.
+ if(
+ (a.isStatic() || a.isSleeping()) &&
+ (b.isStatic() || b.isSleeping())
+ ){
+ return true;
+ }
+
+ // Arbiter was used last frame, but not this one
+ if(ticks >= 1 && arb.state != 'cached'){
+ arb.callSeparate(this);
+ arb.state = 'cached';
+ }
+
+ if(ticks >= this.collisionPersistence){
+ arb.contacts = null;
+
+ //cpArrayPush(this.pooledArbiters, arb);
+ return false;
+ }
+
+ return true;
+};
+
+// **** All Important cpSpaceStep() Function
+
+var updateFunc = function(shape)
+{
+ var body = shape.body;
+ shape.update(body.p, body.rot);
+};
+
+/// Step the space forward in time by @c dt.
+Space.prototype.step = function(dt)
+{
+ // don't step if the timestep is 0!
+ if(dt === 0) return;
+
+ assert(vzero.x === 0 && vzero.y === 0, "vzero is invalid");
+
+ this.stamp++;
+
+ var prev_dt = this.curr_dt;
+ this.curr_dt = dt;
+
+ var i;
+ var j;
+ var hash;
+ var bodies = this.bodies;
+ var constraints = this.constraints;
+ var arbiters = this.arbiters;
+
+ // Reset and empty the arbiter lists.
+ for(i=0; imaxForce*(dt))
+
+// a and b are bodies.
+var relative_velocity = function(a, b, r1, r2){
+ //var v1_sum = vadd(a.v, vmult(vperp(r1), a.w));
+ var v1_sumx = a.vx + (-r1.y) * a.w;
+ var v1_sumy = a.vy + ( r1.x) * a.w;
+
+ //var v2_sum = vadd(b.v, vmult(vperp(r2), b.w));
+ var v2_sumx = b.vx + (-r2.y) * b.w;
+ var v2_sumy = b.vy + ( r2.x) * b.w;
+
+// return vsub(v2_sum, v1_sum);
+ return new Vect(v2_sumx - v1_sumx, v2_sumy - v1_sumy);
+};
+
+var normal_relative_velocity = function(a, b, r1, r2, n){
+ //return vdot(relative_velocity(a, b, r1, r2), n);
+ var v1_sumx = a.vx + (-r1.y) * a.w;
+ var v1_sumy = a.vy + ( r1.x) * a.w;
+ var v2_sumx = b.vx + (-r2.y) * b.w;
+ var v2_sumy = b.vy + ( r2.x) * b.w;
+
+ return vdot2(v2_sumx - v1_sumx, v2_sumy - v1_sumy, n.x, n.y);
+};
+
+/*
+var apply_impulse = function(body, j, r){
+ body.v = vadd(body.v, vmult(j, body.m_inv));
+ body.w += body.i_inv*vcross(r, j);
+};
+
+var apply_impulses = function(a, b, r1, r2, j)
+{
+ apply_impulse(a, vneg(j), r1);
+ apply_impulse(b, j, r2);
+};
+*/
+
+var apply_impulse = function(body, jx, jy, r){
+// body.v = body.v.add(vmult(j, body.m_inv));
+ body.vx += jx * body.m_inv;
+ body.vy += jy * body.m_inv;
+// body.w += body.i_inv*vcross(r, j);
+ body.w += body.i_inv*(r.x*jy - r.y*jx);
+};
+
+var apply_impulses = function(a, b, r1, r2, jx, jy)
+{
+ apply_impulse(a, -jx, -jy, r1);
+ apply_impulse(b, jx, jy, r2);
+};
+
+var apply_bias_impulse = function(body, jx, jy, r)
+{
+ //body.v_bias = vadd(body.v_bias, vmult(j, body.m_inv));
+ body.v_biasx += jx * body.m_inv;
+ body.v_biasy += jy * body.m_inv;
+ body.w_bias += body.i_inv*vcross2(r.x, r.y, jx, jy);
+};
+
+/*
+var apply_bias_impulses = function(a, b, r1, r2, j)
+{
+ apply_bias_impulse(a, vneg(j), r1);
+ apply_bias_impulse(b, j, r2);
+};*/
+
+var k_scalar_body = function(body, r, n)
+{
+ var rcn = vcross(r, n);
+ return body.m_inv + body.i_inv*rcn*rcn;
+};
+
+var k_scalar = function(a, b, r1, r2, n)
+{
+ var value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n);
+ assertSoft(value !== 0, "Unsolvable collision or constraint.");
+
+ return value;
+};
+
+// k1 and k2 are modified by the function to contain the outputs.
+var k_tensor = function(a, b, r1, r2, k1, k2)
+{
+ // calculate mass matrix
+ // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross...
+ var k11, k12, k21, k22;
+ var m_sum = a.m_inv + b.m_inv;
+
+ // start with I*m_sum
+ k11 = m_sum; k12 = 0;
+ k21 = 0; k22 = m_sum;
+
+ // add the influence from r1
+ var a_i_inv = a.i_inv;
+ var r1xsq = r1.x * r1.x * a_i_inv;
+ var r1ysq = r1.y * r1.y * a_i_inv;
+ var r1nxy = -r1.x * r1.y * a_i_inv;
+ k11 += r1ysq; k12 += r1nxy;
+ k21 += r1nxy; k22 += r1xsq;
+
+ // add the influnce from r2
+ var b_i_inv = b.i_inv;
+ var r2xsq = r2.x * r2.x * b_i_inv;
+ var r2ysq = r2.y * r2.y * b_i_inv;
+ var r2nxy = -r2.x * r2.y * b_i_inv;
+ k11 += r2ysq; k12 += r2nxy;
+ k21 += r2nxy; k22 += r2xsq;
+
+ // invert
+ var determinant = k11*k22 - k12*k21;
+ assertSoft(determinant !== 0, "Unsolvable constraint.");
+
+ var det_inv = 1/determinant;
+
+ k1.x = k22*det_inv; k1.y = -k12*det_inv;
+ k2.x = -k21*det_inv; k2.y = k11*det_inv;
+};
+
+var mult_k = function(vr, k1, k2)
+{
+ return new Vect(vdot(vr, k1), vdot(vr, k2));
+};
+
+var bias_coef = function(errorBias, dt)
+{
+ return 1 - Math.pow(errorBias, dt);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+// TODO: Comment me!
+
+// a and b are bodies that the constraint applies to.
+var Constraint = cp.Constraint = function(a, b)
+{
+ /// The first body connected to this constraint.
+ this.a = a;
+ /// The second body connected to this constraint.
+ this.b = b;
+
+ this.space = null;
+
+ this.next_a = null;
+ this.next_b = null;
+
+ /// The maximum force that this constraint is allowed to use.
+ this.maxForce = Infinity;
+ /// The rate at which joint error is corrected.
+ /// Defaults to pow(1 - 0.1, 60) meaning that it will
+ /// correct 10% of the error every 1/60th of a second.
+ this.errorBias = Math.pow(1 - 0.1, 60);
+ /// The maximum rate at which joint error is corrected.
+ this.maxBias = Infinity;
+};
+
+Constraint.prototype.activateBodies = function()
+{
+ if(this.a) this.a.activate();
+ if(this.b) this.b.activate();
+};
+
+/// These methods are overridden by the constraint itself.
+Constraint.prototype.preStep = function(dt) {};
+Constraint.prototype.applyCachedImpulse = function(dt_coef) {};
+Constraint.prototype.applyImpulse = function() {};
+Constraint.prototype.getImpulse = function() { return 0; };
+
+/// Function called before the solver runs. This can be overridden by the user
+/// to customize the constraint.
+/// Animate your joint anchors, update your motor torque, etc.
+Constraint.prototype.preSolve = function(space) {};
+
+/// Function called after the solver runs. This can be overridden by the user
+/// to customize the constraint.
+/// Use the applied impulse to perform effects like breakable joints.
+Constraint.prototype.postSolve = function(space) {};
+
+Constraint.prototype.next = function(body)
+{
+ return (this.a === body ? this.next_a : this.next_b);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var PinJoint = cp.PinJoint = function(a, b, anchr1, anchr2)
+{
+ Constraint.call(this, a, b);
+
+ this.anchr1 = anchr1;
+ this.anchr2 = anchr2;
+
+ // STATIC_BODY_CHECK
+ var p1 = (a ? vadd(a.p, vrotate(anchr1, a.rot)) : anchr1);
+ var p2 = (b ? vadd(b.p, vrotate(anchr2, b.rot)) : anchr2);
+ this.dist = vlength(vsub(p2, p1));
+
+ assertSoft(this.dist > 0, "You created a 0 length pin joint. A pivot joint will be much more stable.");
+
+ this.r1 = this.r2 = null;
+ this.n = null;
+ this.nMass = 0;
+
+ this.jnAcc = this.jnMax = 0;
+ this.bias = 0;
+};
+
+PinJoint.prototype = Object.create(Constraint.prototype);
+
+PinJoint.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ this.r1 = vrotate(this.anchr1, a.rot);
+ this.r2 = vrotate(this.anchr2, b.rot);
+
+ var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
+ var dist = vlength(delta);
+ this.n = vmult(delta, 1/(dist ? dist : Infinity));
+
+ // calculate mass normal
+ this.nMass = 1/k_scalar(a, b, this.r1, this.r2, this.n);
+
+ // calculate bias velocity
+ var maxBias = this.maxBias;
+ this.bias = clamp(-bias_coef(this.errorBias, dt)*(dist - this.dist)/dt, -maxBias, maxBias);
+
+ // compute max impulse
+ this.jnMax = this.maxForce * dt;
+};
+
+PinJoint.prototype.applyCachedImpulse = function(dt_coef)
+{
+ var j = vmult(this.n, this.jnAcc*dt_coef);
+ apply_impulses(this.a, this.b, this.r1, this.r2, j.x, j.y);
+};
+
+PinJoint.prototype.applyImpulse = function()
+{
+ var a = this.a;
+ var b = this.b;
+ var n = this.n;
+
+ // compute relative velocity
+ var vrn = normal_relative_velocity(a, b, this.r1, this.r2, n);
+
+ // compute normal impulse
+ var jn = (this.bias - vrn)*this.nMass;
+ var jnOld = this.jnAcc;
+ this.jnAcc = clamp(jnOld + jn, -this.jnMax, this.jnMax);
+ jn = this.jnAcc - jnOld;
+
+ // apply impulse
+ apply_impulses(a, b, this.r1, this.r2, n.x*jn, n.y*jn);
+};
+
+PinJoint.prototype.getImpulse = function()
+{
+ return Math.abs(this.jnAcc);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var SlideJoint = cp.SlideJoint = function(a, b, anchr1, anchr2, min, max)
+{
+ Constraint.call(this, a, b);
+
+ this.anchr1 = anchr1;
+ this.anchr2 = anchr2;
+ this.min = min;
+ this.max = max;
+
+ this.r1 = this.r2 = this.n = null;
+ this.nMass = 0;
+
+ this.jnAcc = this.jnMax = 0;
+ this.bias = 0;
+};
+
+SlideJoint.prototype = Object.create(Constraint.prototype);
+
+SlideJoint.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ this.r1 = vrotate(this.anchr1, a.rot);
+ this.r2 = vrotate(this.anchr2, b.rot);
+
+ var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
+ var dist = vlength(delta);
+ var pdist = 0;
+ if(dist > this.max) {
+ pdist = dist - this.max;
+ this.n = vnormalize_safe(delta);
+ } else if(dist < this.min) {
+ pdist = this.min - dist;
+ this.n = vneg(vnormalize_safe(delta));
+ } else {
+ this.n = vzero;
+ this.jnAcc = 0;
+ }
+
+ // calculate mass normal
+ this.nMass = 1/k_scalar(a, b, this.r1, this.r2, this.n);
+
+ // calculate bias velocity
+ var maxBias = this.maxBias;
+ this.bias = clamp(-bias_coef(this.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+
+ // compute max impulse
+ this.jnMax = this.maxForce * dt;
+};
+
+SlideJoint.prototype.applyCachedImpulse = function(dt_coef)
+{
+ var jn = this.jnAcc * dt_coef;
+ apply_impulses(this.a, this.b, this.r1, this.r2, this.n.x * jn, this.n.y * jn);
+};
+
+SlideJoint.prototype.applyImpulse = function()
+{
+ if(this.n.x === 0 && this.n.y === 0) return; // early exit
+
+ var a = this.a;
+ var b = this.b;
+
+ var n = this.n;
+ var r1 = this.r1;
+ var r2 = this.r2;
+
+ // compute relative velocity
+ var vr = relative_velocity(a, b, r1, r2);
+ var vrn = vdot(vr, n);
+
+ // compute normal impulse
+ var jn = (this.bias - vrn)*this.nMass;
+ var jnOld = this.jnAcc;
+ this.jnAcc = clamp(jnOld + jn, -this.jnMax, 0);
+ jn = this.jnAcc - jnOld;
+
+ // apply impulse
+ apply_impulses(a, b, this.r1, this.r2, n.x * jn, n.y * jn);
+};
+
+SlideJoint.prototype.getImpulse = function()
+{
+ return Math.abs(this.jnAcc);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+// Pivot joints can also be created with (a, b, pivot);
+var PivotJoint = cp.PivotJoint = function(a, b, anchr1, anchr2)
+{
+ Constraint.call(this, a, b);
+
+ if(typeof anchr2 === 'undefined') {
+ var pivot = anchr1;
+
+ anchr1 = (a ? a.world2Local(pivot) : pivot);
+ anchr2 = (b ? b.world2Local(pivot) : pivot);
+ }
+
+ this.anchr1 = anchr1;
+ this.anchr2 = anchr2;
+
+ this.r1 = this.r2 = vzero;
+
+ this.k1 = new Vect(0,0); this.k2 = new Vect(0,0);
+
+ this.jAcc = vzero;
+
+ this.jMaxLen = 0;
+ this.bias = vzero;
+};
+
+PivotJoint.prototype = Object.create(Constraint.prototype);
+
+PivotJoint.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ this.r1 = vrotate(this.anchr1, a.rot);
+ this.r2 = vrotate(this.anchr2, b.rot);
+
+ // Calculate mass tensor. Result is stored into this.k1 & this.k2.
+ k_tensor(a, b, this.r1, this.r2, this.k1, this.k2);
+
+ // compute max impulse
+ this.jMaxLen = this.maxForce * dt;
+
+ // calculate bias velocity
+ var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
+ this.bias = vclamp(vmult(delta, -bias_coef(this.errorBias, dt)/dt), this.maxBias);
+};
+
+PivotJoint.prototype.applyCachedImpulse = function(dt_coef)
+{
+ apply_impulses(this.a, this.b, this.r1, this.r2, this.jAcc.x * dt_coef, this.jAcc.y * dt_coef);
+};
+
+PivotJoint.prototype.applyImpulse = function()
+{
+ var a = this.a;
+ var b = this.b;
+
+ var r1 = this.r1;
+ var r2 = this.r2;
+
+ // compute relative velocity
+ var vr = relative_velocity(a, b, r1, r2);
+
+ // compute normal impulse
+ var j = mult_k(vsub(this.bias, vr), this.k1, this.k2);
+ var jOld = this.jAcc;
+ this.jAcc = vclamp(vadd(this.jAcc, j), this.jMaxLen);
+
+ // apply impulse
+ apply_impulses(a, b, this.r1, this.r2, this.jAcc.x - jOld.x, this.jAcc.y - jOld.y);
+};
+
+PivotJoint.prototype.getImpulse = function()
+{
+ return vlength(this.jAcc);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var GrooveJoint = cp.GrooveJoint = function(a, b, groove_a, groove_b, anchr2)
+{
+ Constraint.call(this, a, b);
+
+ this.grv_a = groove_a;
+ this.grv_b = groove_b;
+ this.grv_n = vperp(vnormalize(vsub(groove_b, groove_a)));
+ this.anchr2 = anchr2;
+
+ this.grv_tn = null;
+ this.clamp = 0;
+ this.r1 = this.r2 = null;
+
+ this.k1 = new Vect(0,0);
+ this.k2 = new Vect(0,0);
+
+ this.jAcc = vzero;
+ this.jMaxLen = 0;
+ this.bias = null;
+};
+
+GrooveJoint.prototype = Object.create(Constraint.prototype);
+
+GrooveJoint.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ // calculate endpoints in worldspace
+ var ta = a.local2World(this.grv_a);
+ var tb = a.local2World(this.grv_b);
+
+ // calculate axis
+ var n = vrotate(this.grv_n, a.rot);
+ var d = vdot(ta, n);
+
+ this.grv_tn = n;
+ this.r2 = vrotate(this.anchr2, b.rot);
+
+ // calculate tangential distance along the axis of r2
+ var td = vcross(vadd(b.p, this.r2), n);
+ // calculate clamping factor and r2
+ if(td <= vcross(ta, n)){
+ this.clamp = 1;
+ this.r1 = vsub(ta, a.p);
+ } else if(td >= vcross(tb, n)){
+ this.clamp = -1;
+ this.r1 = vsub(tb, a.p);
+ } else {
+ this.clamp = 0;
+ this.r1 = vsub(vadd(vmult(vperp(n), -td), vmult(n, d)), a.p);
+ }
+
+ // Calculate mass tensor
+ k_tensor(a, b, this.r1, this.r2, this.k1, this.k2);
+
+ // compute max impulse
+ this.jMaxLen = this.maxForce * dt;
+
+ // calculate bias velocity
+ var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
+ this.bias = vclamp(vmult(delta, -bias_coef(this.errorBias, dt)/dt), this.maxBias);
+};
+
+GrooveJoint.prototype.applyCachedImpulse = function(dt_coef)
+{
+ apply_impulses(this.a, this.b, this.r1, this.r2, this.jAcc.x * dt_coef, this.jAcc.y * dt_coef);
+};
+
+GrooveJoint.prototype.grooveConstrain = function(j){
+ var n = this.grv_tn;
+ var jClamp = (this.clamp*vcross(j, n) > 0) ? j : vproject(j, n);
+ return vclamp(jClamp, this.jMaxLen);
+};
+
+GrooveJoint.prototype.applyImpulse = function()
+{
+ var a = this.a;
+ var b = this.b;
+
+ var r1 = this.r1;
+ var r2 = this.r2;
+
+ // compute impulse
+ var vr = relative_velocity(a, b, r1, r2);
+
+ var j = mult_k(vsub(this.bias, vr), this.k1, this.k2);
+ var jOld = this.jAcc;
+ this.jAcc = this.grooveConstrain(vadd(jOld, j));
+
+ // apply impulse
+ apply_impulses(a, b, this.r1, this.r2, this.jAcc.x - jOld.x, this.jAcc.y - jOld.y);
+};
+
+GrooveJoint.prototype.getImpulse = function()
+{
+ return vlength(this.jAcc);
+};
+
+GrooveJoint.prototype.setGrooveA = function(value)
+{
+ this.grv_a = value;
+ this.grv_n = vperp(vnormalize(vsub(this.grv_b, value)));
+
+ this.activateBodies();
+};
+
+GrooveJoint.prototype.setGrooveB = function(value)
+{
+ this.grv_b = value;
+ this.grv_n = vperp(vnormalize(vsub(value, this.grv_a)));
+
+ this.activateBodies();
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var defaultSpringForce = function(spring, dist){
+ return (spring.restLength - dist)*spring.stiffness;
+};
+
+var DampedSpring = cp.DampedSpring = function(a, b, anchr1, anchr2, restLength, stiffness, damping)
+{
+ Constraint.call(this, a, b);
+
+ this.anchr1 = anchr1;
+ this.anchr2 = anchr2;
+
+ this.restLength = restLength;
+ this.stiffness = stiffness;
+ this.damping = damping;
+ this.springForceFunc = defaultSpringForce;
+
+ this.target_vrn = this.v_coef = 0;
+
+ this.r1 = this.r2 = null;
+ this.nMass = 0;
+ this.n = null;
+};
+
+DampedSpring.prototype = Object.create(Constraint.prototype);
+
+DampedSpring.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ this.r1 = vrotate(this.anchr1, a.rot);
+ this.r2 = vrotate(this.anchr2, b.rot);
+
+ var delta = vsub(vadd(b.p, this.r2), vadd(a.p, this.r1));
+ var dist = vlength(delta);
+ this.n = vmult(delta, 1/(dist ? dist : Infinity));
+
+ var k = k_scalar(a, b, this.r1, this.r2, this.n);
+ assertSoft(k !== 0, "Unsolvable this.");
+ this.nMass = 1/k;
+
+ this.target_vrn = 0;
+ this.v_coef = 1 - Math.exp(-this.damping*dt*k);
+
+ // apply this force
+ var f_spring = this.springForceFunc(this, dist);
+ apply_impulses(a, b, this.r1, this.r2, this.n.x * f_spring * dt, this.n.y * f_spring * dt);
+};
+
+DampedSpring.prototype.applyCachedImpulse = function(dt_coef){};
+
+DampedSpring.prototype.applyImpulse = function()
+{
+ var a = this.a;
+ var b = this.b;
+
+ var n = this.n;
+ var r1 = this.r1;
+ var r2 = this.r2;
+
+ // compute relative velocity
+ var vrn = normal_relative_velocity(a, b, r1, r2, n);
+
+ // compute velocity loss from drag
+ var v_damp = (this.target_vrn - vrn)*this.v_coef;
+ this.target_vrn = vrn + v_damp;
+
+ v_damp *= this.nMass;
+ apply_impulses(a, b, this.r1, this.r2, this.n.x * v_damp, this.n.y * v_damp);
+};
+
+DampedSpring.prototype.getImpulse = function()
+{
+ return 0;
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var defaultSpringTorque = function(spring, relativeAngle){
+ return (relativeAngle - spring.restAngle)*spring.stiffness;
+}
+
+var DampedRotarySpring = cp.DampedRotarySpring = function(a, b, restAngle, stiffness, damping)
+{
+ Constraint.call(this, a, b);
+
+ this.restAngle = restAngle;
+ this.stiffness = stiffness;
+ this.damping = damping;
+ this.springTorqueFunc = defaultSpringTorque;
+
+ this.target_wrn = 0;
+ this.w_coef = 0;
+ this.iSum = 0;
+};
+
+DampedRotarySpring.prototype = Object.create(Constraint.prototype);
+
+DampedRotarySpring.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ var moment = a.i_inv + b.i_inv;
+ assertSoft(moment !== 0, "Unsolvable spring.");
+ this.iSum = 1/moment;
+
+ this.w_coef = 1 - Math.exp(-this.damping*dt*moment);
+ this.target_wrn = 0;
+
+ // apply this torque
+ var j_spring = this.springTorqueFunc(this, a.a - b.a)*dt;
+ a.w -= j_spring*a.i_inv;
+ b.w += j_spring*b.i_inv;
+};
+
+// DampedRotarySpring.prototype.applyCachedImpulse = function(dt_coef){};
+
+DampedRotarySpring.prototype.applyImpulse = function()
+{
+ var a = this.a;
+ var b = this.b;
+
+ // compute relative velocity
+ var wrn = a.w - b.w;//normal_relative_velocity(a, b, r1, r2, n) - this.target_vrn;
+
+ // compute velocity loss from drag
+ // not 100% certain spring is derived correctly, though it makes sense
+ var w_damp = (this.target_wrn - wrn)*this.w_coef;
+ this.target_wrn = wrn + w_damp;
+
+ //apply_impulses(a, b, this.r1, this.r2, vmult(this.n, v_damp*this.nMass));
+ var j_damp = w_damp*this.iSum;
+ a.w += j_damp*a.i_inv;
+ b.w -= j_damp*b.i_inv;
+};
+
+// DampedRotarySpring.prototype.getImpulse = function(){ return 0; };
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var RotaryLimitJoint = cp.RotaryLimitJoint = function(a, b, min, max)
+{
+ Constraint.call(this, a, b);
+
+ this.min = min;
+ this.max = max;
+
+ this.jAcc = 0;
+
+ this.iSum = this.bias = this.jMax = 0;
+};
+
+RotaryLimitJoint.prototype = Object.create(Constraint.prototype);
+
+RotaryLimitJoint.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ var dist = b.a - a.a;
+ var pdist = 0;
+ if(dist > this.max) {
+ pdist = this.max - dist;
+ } else if(dist < this.min) {
+ pdist = this.min - dist;
+ }
+
+ // calculate moment of inertia coefficient.
+ this.iSum = 1/(1/a.i + 1/b.i);
+
+ // calculate bias velocity
+ var maxBias = this.maxBias;
+ this.bias = clamp(-bias_coef(this.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+
+ // compute max impulse
+ this.jMax = this.maxForce * dt;
+
+ // If the bias is 0, the joint is not at a limit. Reset the impulse.
+ if(!this.bias) this.jAcc = 0;
+};
+
+RotaryLimitJoint.prototype.applyCachedImpulse = function(dt_coef)
+{
+ var a = this.a;
+ var b = this.b;
+
+ var j = this.jAcc*dt_coef;
+ a.w -= j*a.i_inv;
+ b.w += j*b.i_inv;
+};
+
+RotaryLimitJoint.prototype.applyImpulse = function()
+{
+ if(!this.bias) return; // early exit
+
+ var a = this.a;
+ var b = this.b;
+
+ // compute relative rotational velocity
+ var wr = b.w - a.w;
+
+ // compute normal impulse
+ var j = -(this.bias + wr)*this.iSum;
+ var jOld = this.jAcc;
+ if(this.bias < 0){
+ this.jAcc = clamp(jOld + j, 0, this.jMax);
+ } else {
+ this.jAcc = clamp(jOld + j, -this.jMax, 0);
+ }
+ j = this.jAcc - jOld;
+
+ // apply impulse
+ a.w -= j*a.i_inv;
+ b.w += j*b.i_inv;
+};
+
+RotaryLimitJoint.prototype.getImpulse = function()
+{
+ return Math.abs(joint.jAcc);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var RatchetJoint = cp.RatchetJoint = function(a, b, phase, ratchet)
+{
+ Constraint.call(this, a, b);
+
+ this.angle = 0;
+ this.phase = phase;
+ this.ratchet = ratchet;
+
+ // STATIC_BODY_CHECK
+ this.angle = (b ? b.a : 0) - (a ? a.a : 0);
+
+ this.iSum = this.bias = this.jAcc = this.jMax = 0;
+};
+
+RatchetJoint.prototype = Object.create(Constraint.prototype);
+
+RatchetJoint.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ var angle = this.angle;
+ var phase = this.phase;
+ var ratchet = this.ratchet;
+
+ var delta = b.a - a.a;
+ var diff = angle - delta;
+ var pdist = 0;
+
+ if(diff*ratchet > 0){
+ pdist = diff;
+ } else {
+ this.angle = Math.floor((delta - phase)/ratchet)*ratchet + phase;
+ }
+
+ // calculate moment of inertia coefficient.
+ this.iSum = 1/(a.i_inv + b.i_inv);
+
+ // calculate bias velocity
+ var maxBias = this.maxBias;
+ this.bias = clamp(-bias_coef(this.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+
+ // compute max impulse
+ this.jMax = this.maxForce * dt;
+
+ // If the bias is 0, the joint is not at a limit. Reset the impulse.
+ if(!this.bias) this.jAcc = 0;
+};
+
+RatchetJoint.prototype.applyCachedImpulse = function(dt_coef)
+{
+ var a = this.a;
+ var b = this.b;
+
+ var j = this.jAcc*dt_coef;
+ a.w -= j*a.i_inv;
+ b.w += j*b.i_inv;
+};
+
+RatchetJoint.prototype.applyImpulse = function()
+{
+ if(!this.bias) return; // early exit
+
+ var a = this.a;
+ var b = this.b;
+
+ // compute relative rotational velocity
+ var wr = b.w - a.w;
+ var ratchet = this.ratchet;
+
+ // compute normal impulse
+ var j = -(this.bias + wr)*this.iSum;
+ var jOld = this.jAcc;
+ this.jAcc = clamp((jOld + j)*ratchet, 0, this.jMax*Math.abs(ratchet))/ratchet;
+ j = this.jAcc - jOld;
+
+ // apply impulse
+ a.w -= j*a.i_inv;
+ b.w += j*b.i_inv;
+};
+
+RatchetJoint.prototype.getImpulse = function(joint)
+{
+ return Math.abs(joint.jAcc);
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var GearJoint = cp.GearJoint = function(a, b, phase, ratio)
+{
+ Constraint.call(this, a, b);
+
+ this.phase = phase;
+ this.ratio = ratio;
+ this.ratio_inv = 1/ratio;
+
+ this.jAcc = 0;
+
+ this.iSum = this.bias = this.jMax = 0;
+};
+
+GearJoint.prototype = Object.create(Constraint.prototype);
+
+GearJoint.prototype.preStep = function(dt)
+{
+ var a = this.a;
+ var b = this.b;
+
+ // calculate moment of inertia coefficient.
+ this.iSum = 1/(a.i_inv*this.ratio_inv + this.ratio*b.i_inv);
+
+ // calculate bias velocity
+ var maxBias = this.maxBias;
+ this.bias = clamp(-bias_coef(this.errorBias, dt)*(b.a*this.ratio - a.a - this.phase)/dt, -maxBias, maxBias);
+
+ // compute max impulse
+ this.jMax = this.maxForce * dt;
+};
+
+GearJoint.prototype.applyCachedImpulse = function(dt_coef)
+{
+ var a = this.a;
+ var b = this.b;
+
+ var j = this.jAcc*dt_coef;
+ a.w -= j*a.i_inv*this.ratio_inv;
+ b.w += j*b.i_inv;
+};
+
+GearJoint.prototype.applyImpulse = function()
+{
+ var a = this.a;
+ var b = this.b;
+
+ // compute relative rotational velocity
+ var wr = b.w*this.ratio - a.w;
+
+ // compute normal impulse
+ var j = (this.bias - wr)*this.iSum;
+ var jOld = this.jAcc;
+ this.jAcc = clamp(jOld + j, -this.jMax, this.jMax);
+ j = this.jAcc - jOld;
+
+ // apply impulse
+ a.w -= j*a.i_inv*this.ratio_inv;
+ b.w += j*b.i_inv;
+};
+
+GearJoint.prototype.getImpulse = function()
+{
+ return Math.abs(this.jAcc);
+};
+
+GearJoint.prototype.setRatio = function(value)
+{
+ this.ratio = value;
+ this.ratio_inv = 1/value;
+ this.activateBodies();
+};
+
+/* Copyright (c) 2007 Scott Lembcke
+ *
+ * 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.
+ */
+
+var SimpleMotor = cp.SimpleMotor = function(a, b, rate)
+{
+ Constraint.call(this, a, b);
+
+ this.rate = rate;
+
+ this.jAcc = 0;
+
+ this.iSum = this.jMax = 0;
+};
+
+SimpleMotor.prototype = Object.create(Constraint.prototype);
+
+SimpleMotor.prototype.preStep = function(dt)
+{
+ // calculate moment of inertia coefficient.
+ this.iSum = 1/(this.a.i_inv + this.b.i_inv);
+
+ // compute max impulse
+ this.jMax = this.maxForce * dt;
+};
+
+SimpleMotor.prototype.applyCachedImpulse = function(dt_coef)
+{
+ var a = this.a;
+ var b = this.b;
+
+ var j = this.jAcc*dt_coef;
+ a.w -= j*a.i_inv;
+ b.w += j*b.i_inv;
+};
+
+SimpleMotor.prototype.applyImpulse = function()
+{
+ var a = this.a;
+ var b = this.b;
+
+ // compute relative rotational velocity
+ var wr = b.w - a.w + this.rate;
+
+ // compute normal impulse
+ var j = -wr*this.iSum;
+ var jOld = this.jAcc;
+ this.jAcc = clamp(jOld + j, -this.jMax, this.jMax);
+ j = this.jAcc - jOld;
+
+ // apply impulse
+ a.w -= j*a.i_inv;
+ b.w += j*b.i_inv;
+};
+
+SimpleMotor.prototype.getImpulse = function()
+{
+ return Math.abs(this.jAcc);
+};
+
+})();
diff --git a/external/gaf/GAFBoot.js b/external/gaf/GAFBoot.js
new file mode 100644
index 0000000000..0baccc7ecd
--- /dev/null
+++ b/external/gaf/GAFBoot.js
@@ -0,0 +1,24 @@
+var gaf = gaf || {};
+gaf._tmp = gaf._tmp || {};
+gaf._initialized = false;
+
+gaf.CCGAFLoader = function()
+{
+ this.load = function(realUrl, url, item, cb)
+ {
+ if(!gaf._initialized)
+ {
+ gaf._setup();
+ }
+ var loader = new gaf.Loader();
+ loader.LoadFile(realUrl, function(data){cb(null, data)});
+ };
+};
+
+gaf._setup = function()
+{
+ gaf._setupShaders();
+ gaf._initialized = true;
+};
+
+cc.loader.register('.gaf', new gaf.CCGAFLoader());
diff --git a/external/gaf/GAFMacros.js b/external/gaf/GAFMacros.js
new file mode 100644
index 0000000000..ef34cc8f5d
--- /dev/null
+++ b/external/gaf/GAFMacros.js
@@ -0,0 +1,33 @@
+var gaf = gaf || {};
+
+gaf.COMPRESSION_NONE = 0x00474146;
+gaf.COMPRESSION_ZIP = 0x00474143;
+
+gaf.IDNONE = 0xffffffff;
+gaf.FIRST_FRAME_INDEX = 0;
+
+gaf.EFFECT_DROP_SHADOW = 0;
+gaf.EFFECT_BLUR = 1;
+gaf.EFFECT_GLOW = 2;
+gaf.EFFECT_COLOR_MATRIX = 6;
+
+gaf.ACTION_STOP = 0;
+gaf.ACTION_PLAY = 1;
+gaf.ACTION_GO_TO_AND_STOP = 2;
+gaf.ACTION_GO_TO_AND_PLAY = 3;
+gaf.ACTION_DISPATCH_EVENT = 4;
+
+gaf.PI_FRAME = 0;
+gaf.PI_EVENT_TYPE = 0;
+
+gaf.TYPE_TEXTURE = 0;
+gaf.TYPE_TEXT_FIELD = 1;
+gaf.TYPE_TIME_LINE = 2;
+
+gaf.UNIFORM_BLUR_TEXEL_OFFSET = "u_step";
+gaf.UNIFORM_GLOW_TEXEL_OFFSET = "u_step";
+gaf.UNIFORM_GLOW_COLOR = "u_glowColor";
+gaf.UNIFORM_ALPHA_TINT_MULT = "colorTransformMult";
+gaf.UNIFORM_ALPHA_TINT_OFFSET = "colorTransformOffsets";
+gaf.UNIFORM_ALPHA_COLOR_MATRIX_BODY = "colorMatrix";
+gaf.UNIFORM_ALPHA_COLOR_MATRIX_APPENDIX = "colorMatrix2";
diff --git a/external/gaf/Library/GAFAsset.js b/external/gaf/Library/GAFAsset.js
new file mode 100644
index 0000000000..23804e61ff
--- /dev/null
+++ b/external/gaf/Library/GAFAsset.js
@@ -0,0 +1,429 @@
+var gaf = gaf || {};
+
+gaf.Asset = cc.Class.extend
+({
+ _className: "GAFAsset",
+
+ // Private members
+ _header: null,
+ _timeLines: null,
+ _textFields: null,
+ _protos: null,
+ _objects: null,
+ _masks: null,
+
+ _rootTimeLine: null,
+ _textureLoadDelegate: null,
+ _sceneFps: 60,
+ _sceneWidth: 0,
+ _sceneHeight: 0,
+ _sceneColor: 0,
+ _gafData: null,
+ _desiredAtlasScale: 1,
+ _usedAtlasScale: 0,
+
+ _atlases: null,
+ _onLoadTasks: null,
+ _atlasScales: null,
+ _textureLoaded: false, // For async loading with cc.event manager
+ _atlasesToLoad: null, // Atlases that are not yet loaded
+ _gafName: null,
+
+ /**
+ * @method initWithGAFFile
+ * @param {String} filePath - path to .gaf file
+ * @param {String function(String)} textureLoadDelegate - is used to change atlas path, e.g. to load `atlas.tga` instead of `atlas.png`
+ * @return {bool}
+ */
+ initWithGAFFile: function (filePath, textureLoadDelegate) {
+ var self = this;
+ this._textureLoadDelegate = textureLoadDelegate;
+ this._gafName = filePath;
+ var gafData = cc.loader.getRes(filePath);
+ if(!gafData)
+ {
+ cc.loader.load(filePath, function(err, data){
+ if(!err)
+ {
+ self._init(data[0]);
+ }
+ });
+ }
+ else {
+ return this._init(gafData);
+ }
+ return false;
+ },
+
+ /**
+ * @method initWithGAFBundle
+ * @param {String} zipFilePath - path to the archive with .gaf and its textures
+ * @param {String} entryFile - name of the .gaf file in archive
+ * @param {function({path:String})} delegate - is used to change atlas path, e.g. to load `atlas.tga` instead of `atlas.png`
+ * @return {bool}
+ */
+ initWithGAFBundle: function (zipFilePath, entryFile, delegate)
+ {
+ cc.assert(false, "initWithGAFBundle is not yet implemented");
+ return false;
+ },
+
+ /**
+ * @method setRootTimelineWithName
+ * @param {String} name
+ */
+ setRootTimelineWithName: function (name)
+ {
+ for(var i = 0, end = this._timeLines.length; i < end; ++i)
+ {
+ var object = this._timeLines[i];
+ if (object && object.getLinkageName() === name)
+ {
+ this._setRootTimeline(object);
+ return;
+ }
+ }
+ },
+
+/* addEventListener: function(name, listener)
+ {},*/
+
+ isAssetVersionPlayable: function ()
+ {
+ return true;
+ },
+
+ /**
+ * Desired atlas scale.
+ * Default is 1.0f
+ * @returns {number}
+ */
+ desiredAtlasScale : function(){
+ return this._desiredAtlasScale;
+ },
+
+ /**
+ * Sets desired atlas scale. Will choose nearest atlas scale from available.
+ * Default is 1.0f
+ * @param scale
+ */
+ setDesiredAtlasScale : function(desiredAtlasScale){
+ this._desiredAtlasScale = desiredAtlasScale;
+ for(var currentScale in this._atlasScales)if(this._atlasScales.hasOwnProperty(currentScale))
+ {
+ if( (this._usedAtlasScale === 0) ||
+ (Math.abs(this._usedAtlasScale - desiredAtlasScale) > Math.abs(currentScale - desiredAtlasScale) ))
+ {
+ this._usedAtlasScale = currentScale;
+ }
+
+ }
+ },
+
+ /**
+ * @method createObject
+ * @return {gaf.Object}
+ */
+ createObject: function ()
+ {
+ return this._instantiateGaf(this._gafData);
+ },
+
+ /**
+ * @method createObjectAndRun
+ * @param {boolean} arg0 - run looped
+ * @return {gaf.Object}
+ */
+ createObjectAndRun: function (looped)
+ {
+ cc.assert(arguments.length === 1, "GAFAsset::createObjectAndRun should have one param");
+ var object = this._instantiateGaf(this._gafData);
+ object.setLooped(looped, true);
+ object.start();
+ return object;
+ },
+
+ /**
+ * @method setTextureLoadDelegate
+ * @param {function} delegate
+ */
+ setTextureLoadDelegate: function (delegate)
+ {
+ debugger;
+ },
+
+
+ /**
+ * @method getSceneFps
+ * @return {uint}
+ */
+ getSceneFps: function ()
+ {
+ return this._sceneFps;
+ },
+
+ /**
+ * @method getSceneWidth
+ * @return {uint}
+ */
+ getSceneWidth: function ()
+ {
+ debugger;
+ },
+
+ /**
+ * @method getSceneHeight
+ * @return {uint}
+ */
+ getSceneHeight: function ()
+ {
+ debugger;
+ },
+
+ /**
+ * @method getSceneColor
+ * @return {cc.color4b}
+ */
+ getSceneColor: function ()
+ {
+ debugger;
+ },
+
+ /**
+ * @method setSceneFps
+ * @param {uint} fps
+ */
+ setSceneFps: function (fps)
+ {
+ this._sceneFps = fps;
+ },
+
+ /**
+ * @method setSceneWidth
+ * @param {uint} width
+ */
+ setSceneWidth: function (width)
+ {
+ debugger;
+ },
+
+ /**
+ * @method setSceneHeight
+ * @param {uint} height
+ */
+ setSceneHeight: function (height)
+ {
+ debugger;
+ },
+
+ /**
+ * @method setSceneColor
+ * @param {color4b_object} arg0
+ */
+ setSceneColor: function (color4B)
+ {
+ debugger;
+ },
+
+ /**
+ * @method getHeader
+ * @return {GAFHeader}
+ */
+ getHeader: function ()
+ {
+ return this._header;
+ },
+
+ getGAFFileName: function()
+ {
+ return this._gafName;
+ },
+
+ // Private
+
+ ctor : function()
+ {
+ this._header = {};
+ this._timeLines = [];
+ this._textFields = [];
+ this._objects = [];
+ this._masks = [];
+ this._protos = [];
+ this._atlases = {};
+ this._onLoadTasks = [];
+ this._atlasScales = {};
+ this._atlasesToLoad = {};
+
+ if(arguments.length > 0)
+ this.initWithGAFFile.apply(this, arguments);
+ },
+
+ _getProtos: function()
+ {
+ return this._protos;
+ },
+
+ _setRootTimeline : function(timeLine)
+ {
+ this._rootTimeLine = timeLine;
+ this._header.pivot = timeLine.getPivot();
+ this._header.frameSize = timeLine.getRect();
+ },
+
+ _setHeader : function (gafHeader)
+ {
+ for(var prop in gafHeader)
+ {
+ if(gafHeader.hasOwnProperty(prop))
+ {
+ this._header[prop] = gafHeader[prop];
+ }
+ }
+ },
+
+ _getMajorVerison : function()
+ {
+ return this._header.versionMajor;
+ },
+
+ _init : function(gafData)
+ {
+ var self = this;
+ this._gafData = gafData;
+ this._setHeader(gafData.header);
+ this._timeLinesToLink = [];
+ if(this._getMajorVerison() < 4)
+ {
+ this._pushTimeLine(new gaf._TimeLineProto(this, this._header.framesCount, this._header.frameSize, this._header.pivot));
+ }
+ gaf._AssetPreload.Tags(this, gafData.tags, this._rootTimeLine);
+
+ //Link and create
+ this._objects.forEach(function(item)
+ {
+ switch(item.type)
+ {
+ case gaf.TYPE_TEXTURE:
+ // Create gaf sprite proto if it is not yet created
+ if(!self._protos[item.objectId])
+ {
+ self._protos[item.objectId] = new gaf._SpriteProto(self, self._atlasScales, item.elementAtlasIdRef);
+ }
+ break;
+ case gaf.TYPE_TIME_LINE:
+ // All time line protos are already created, just copy reference
+ self._protos[item.objectId] = self._timeLines[item.elementAtlasIdRef];
+ break;
+ case gaf.TYPE_TEXT_FIELD:
+ // All text field protos are already created, just copy reference
+ self._protos[item.objectId] = self._textFields[item.elementAtlasIdRef];
+ break;
+ default:
+ cc.log("Unknown object type: " + item.type);
+ break;
+ }
+ });
+ this._masks.forEach(function(item)
+ {
+ if(self._protos[item.objectId])
+ {
+ return; // this is continue
+ }
+ var proto = null;
+ switch(item.type)
+ {
+ case gaf.TYPE_TEXTURE:
+ // Create gaf sprite proto if it is not yet created
+ proto = new gaf._SpriteProto(self, self._atlasScales, item.elementAtlasIdRef);
+ break;
+ case gaf.TYPE_TIME_LINE:
+ // All time line protos are already created, just copy reference
+ proto = self._timeLines[item.elementAtlasIdRef];
+ break;
+ case gaf.TYPE_TEXT_FIELD:
+ // All text field protos are already created, just copy reference
+ proto = self._textFields[item.elementAtlasIdRef];
+ break;
+ }
+ self._protos[item.objectId] = new gaf._MaskProto(self, proto, item.elementAtlasIdRef);
+ });
+ this.setDesiredAtlasScale(this._desiredAtlasScale);
+
+ if(Object.keys(this._atlasesToLoad).length === 0)
+ {
+ this._textureLoaded = true;
+ this.dispatchEvent("load");
+ }
+ },
+
+ _pushTimeLine : function(timeLine)
+ {
+ this._timeLines[timeLine.getId()] = timeLine;
+
+ if(timeLine.getId() === 0)
+ {
+ this._setRootTimeline(timeLine);
+ }
+ },
+
+ _instantiateGaf : function()
+ {
+ var root = null;
+ root = this._rootTimeLine._gafConstruct();
+ return root;
+ },
+
+ _onAtlasLoaded : function(id, atlas)
+ {
+ this._atlases[id] = atlas;
+ delete this._atlasesToLoad[id];
+ if(Object.keys(this._atlasesToLoad).length === 0)
+ {
+ this._onLoadTasks.forEach(function(fn){fn()});
+ this._onLoadTasks.length = 0;
+ this._textureLoaded = true;
+ this.dispatchEvent("load");
+ }
+ },
+
+ isLoaded : function()
+ {
+ return this._textureLoaded;
+ },
+
+ _getSearchPaths: function(imageUrl)
+ {
+ var extendedPath = this.getGAFFileName().split('/');
+ extendedPath[extendedPath.length-1] = imageUrl;
+ var alternativeUrl = extendedPath.join('/');
+
+ return [imageUrl, alternativeUrl];
+ }
+});
+
+/**
+ * @method initWithGAFFile
+ * @param {String} gafFilePath - path to .gaf file
+ * @param {function({path:String})} delegate - is used to change atlas path, e.g. to load `atlas.tga` instead of `atlas.png`
+ * @return {gaf.Asset}
+ */
+gaf.Asset.create = function (gafFilePath, delegate)
+{
+ return new gaf.Asset(gafFilePath, delegate);
+};
+
+/**
+ * @method createWithBundle
+ * @param {String} zipFilePath - path to the archive with .gaf and its textures
+ * @param {String} entryFile - name of the .gaf file in archive
+ * @param {function({path:String})} delegate - is used to change atlas path, e.g. to load `atlas.tga` instead of `atlas.png`
+ * @return {gaf.Asset}
+ */
+gaf.Asset.createWithBundle = function (zipFilePath, entryFile, delegate)
+{
+ var asset = new gaf.Asset();
+ asset.initWithGAFBundle(zipFilePath, entryFile, delegate);
+ return asset;
+};
+
+cc.EventHelper.prototype.apply(gaf.Asset.prototype);
diff --git a/external/gaf/Library/GAFAssetPreload.js b/external/gaf/Library/GAFAssetPreload.js
new file mode 100644
index 0000000000..8514e09f2d
--- /dev/null
+++ b/external/gaf/Library/GAFAssetPreload.js
@@ -0,0 +1,270 @@
+
+gaf.CGAffineTransformCocosFormatFromFlashFormat = function(transform)
+{
+ var t = {};
+ t.a = transform.a;
+ t.b = -transform.b;
+ t.c = -transform.c;
+ t.d = transform.d;
+ t.tx = transform.tx;
+ t.ty = -transform.ty;
+ return t;
+};
+
+gaf._AssetPreload = function()
+{
+ this["0"] = this.End;
+ this["1"] = this.Atlases;
+ this["2"] = this.AnimationMasks;
+ this["3"] = this.AnimationObjects;
+ this["4"] = this.AnimationFrames;
+ this["5"] = this.NamedParts;
+ this["6"] = this.Sequences;
+ this["7"] = this.TextFields;
+ this["8"] = this.Atlases; // 2
+ this["9"] = this.Stage;
+ this["10"] = this.AnimationObjects; //2
+ this["11"] = this.AnimationMasks; // 2
+ this["12"] = this.AnimationFrames; // 2
+ this["13"] = this.TimeLine;
+};
+
+gaf._AssetPreload.prototype.End = function(asset, content, timeLine){
+ if(timeLine)
+ {
+ timeLine.getFps = function()
+ {
+ return asset.getSceneFps();
+ };
+ }
+};
+
+gaf._AssetPreload.prototype.Tag = function(asset, tag, timeLine)
+{
+ (this[tag.tagId]).call(this, asset, tag.content, timeLine);
+};
+
+gaf._AssetPreload.prototype.Tags = function(asset, tags, timeLine)
+{
+ var self = this;
+ tags.forEach(function(tag)
+ {
+ self.Tag(asset, tag, timeLine);
+ });
+};
+
+gaf._AssetPreload.prototype.AtlasCreateFrames = function(elements, asset, spriteFrames)
+{
+ elements.forEach(function (item) {
+ var texture = asset._atlases[item.atlasId];
+ var rect = cc.rect(item.origin.x, item.origin.y, item.size.x, item.size.y);
+ var frame = new cc.SpriteFrame(texture, rect);
+ frame._gafAnchor =
+ {
+ x: (0 - (0 - (item.pivot.x / item.size.x))),
+ y: (0 + (1 - (item.pivot.y / item.size.y)))
+ };
+ spriteFrames[item.elementAtlasId] = frame;
+ // 9 grid
+ });
+};
+
+
+
+gaf._AssetPreload.prototype.Atlases = function(asset, content, timeLine)
+{
+ var spriteFrames = asset._atlasScales[content.scale] = asset._atlasScales[content.scale] || [];
+ var csf = cc.Director._getInstance().getContentScaleFactor();
+
+ content.atlases.forEach(function(item)
+ {
+ var atlasId = item.id;
+ var finalizeLoading = function()
+ {
+ gaf._AssetPreload.AtlasCreateFrames(content.elements, asset, spriteFrames);
+ };
+
+ var atlasPath = "";
+ item.sources.forEach(function(atlasSource)
+ {
+ if(atlasSource.csf === csf)
+ {
+ atlasPath = atlasSource.source;
+ }
+ });
+ cc.assert(atlasPath, "GAF Error. Texture for current CSF not found. Reconvert animation with correct parameters.");
+
+ if(asset._textureLoadDelegate)
+ {
+ atlasPath = asset._textureLoadDelegate(atlasPath);
+ }
+
+ var loaded = false;
+ var paths = asset._getSearchPaths(atlasPath);
+ for(var i = 0, len = paths.length; i < len; ++i){
+ var path = paths[i];
+ var atlas = cc.textureCache.getTextureForKey(path);
+ if(atlas && atlas.isLoaded())
+ {
+ atlas.handleLoadedTexture(true);
+ loaded = true;
+ asset._atlases[atlasId] = atlas;
+ finalizeLoading();
+ break;
+ }
+ }
+ // Need to load atlases async
+ if(!loaded)
+ {
+ var success = function (atlas) {
+ atlas.handleLoadedTexture(true);
+ asset._onAtlasLoaded(atlasId, atlas);
+ };
+
+ var fail = function () {
+ cc.log("GAF Error. Couldn't find `" + atlasPath + "` required by `" + asset.getGAFFileName() + "`");
+ };
+
+ if(!asset._atlasesToLoad.hasOwnProperty(atlasId))
+ {
+ gaf._AtlasLoader.loadArray(paths, success, fail);
+ asset._atlasesToLoad[atlasId] = {};
+ }
+ asset._onLoadTasks.push(finalizeLoading);
+ }
+ });
+};
+
+gaf._AssetPreload.prototype.AnimationObjects = function(asset, content, timeLine)
+{
+ content.forEach(function(item)
+ {
+ item.type = (item.type === undefined) ? gaf.TYPE_TEXTURE : item.type;
+ timeLine._objects.push(item.objectId);
+ asset._objects[item.objectId] = item;
+ });
+};
+
+gaf._AssetPreload.prototype.convertTint = function(mat, alpha)
+{
+ if(!mat)
+ return null;
+ return {
+ mult:
+ {
+ r: mat.redMultiplier * 255,
+ g: mat.greenMultiplier * 255,
+ b: mat.blueMultiplier * 255,
+ a: alpha * 255
+ },
+ offset:
+ {
+ r: mat.redOffset * 255,
+ g: mat.greenOffset * 255,
+ b: mat.blueOffset * 255,
+ a: mat.alphaOffset * 255
+ }
+ };
+};
+
+gaf._AssetPreload.prototype.convertState = function(state)
+{
+ return {
+ hasColorTransform: state.hasColorTransform,
+ hasMask: state.hasMask,
+ hasEffect: state.hasEffect,
+ objectIdRef: state.objectIdRef,
+ depth: state.depth,
+ alpha: state.alpha * 255,
+ matrix: gaf.CGAffineTransformCocosFormatFromFlashFormat(state.matrix),
+ colorTransform: this.convertTint(state.colorTransform, state.alpha),
+ effect: state.effect,
+ maskObjectIdRef: state.maskObjectIdRef
+ };
+};
+
+gaf._AssetPreload.prototype.AnimationFrames = function(asset, content, timeLine)
+{
+ var self = this;
+ cc.assert(timeLine, "Error. Time Line should not be null.");
+ var statesForId = {};
+ var frames = [];
+ var lastFrame = {};
+ for(var i = 0, len = content.length; i < len; ++i)
+ {
+ var frame = content[i];
+ if(frame.state)
+ {
+ frame.state.forEach(function (state)
+ {
+ if (state.alpha !== 0)
+ {
+ statesForId[state.objectIdRef] = self.convertState(state);
+ }
+ else
+ {
+ statesForId[state.objectIdRef] = null;
+ }
+ });
+ }
+ var stateArray = [];
+ for(var obj in statesForId){ if(statesForId.hasOwnProperty(obj) && statesForId[obj])
+ {
+ stateArray.push(statesForId[obj]);
+ }}
+ lastFrame = frame;
+ frames[frame.frame - 1] = {states: stateArray, actions: frame.actions || null};
+ }
+ timeLine.getFrames = function(){return frames};
+};
+
+gaf._AssetPreload.prototype.NamedParts = function(asset, content, timeLine)
+{
+ var parts = {};
+ content.forEach(function(item)
+ {
+ parts[item.name] = item.objectId;
+ });
+ timeLine.getNamedParts = function(){return parts};
+};
+
+gaf._AssetPreload.prototype.Sequences = function(asset, content, timeLine)
+{
+ var sequences = {};
+ content.forEach(function(item){
+ sequences[item.id] = {start: item.start - 1, end: item.end};
+ });
+ timeLine.getSequences = function(){return sequences};
+};
+
+gaf._AssetPreload.prototype.TextFields = function(asset, content, timeLine)
+{
+ debugger;
+};
+
+gaf._AssetPreload.prototype.Stage = function(asset, content, timeLine)
+{
+ asset._sceneFps = content.fps;
+ asset._sceneColor = content.color;
+ asset._sceneWidth = content.width;
+ asset._sceneHeight = content.height;
+};
+
+gaf._AssetPreload.prototype.AnimationMasks = function(asset, content, timeLine)
+{
+ content.forEach(function(item)
+ {
+ item.type = (item.type === undefined) ? gaf.TYPE_TEXTURE : item.type;
+ timeLine._objects.push(item.objectId);
+ asset._masks[item.objectId] = item;
+ });
+};
+
+gaf._AssetPreload.prototype.TimeLine = function(asset, content, timeLine)
+{
+ var result = new gaf._TimeLineProto(asset, content.animationFrameCount, content.boundingBox, content.pivotPoint, content.id, content.linkageName);
+ asset._pushTimeLine(result);
+ this.Tags(asset, content.tags, result);
+};
+
+gaf._AssetPreload = new gaf._AssetPreload();
diff --git a/external/gaf/Library/GAFAtlasLoader.js b/external/gaf/Library/GAFAtlasLoader.js
new file mode 100644
index 0000000000..152bba0788
--- /dev/null
+++ b/external/gaf/Library/GAFAtlasLoader.js
@@ -0,0 +1,50 @@
+/**
+ * Created by admiral on 19.02.2015.
+ */
+
+gaf._AtlasLoader = {};
+gaf._AtlasLoader.execute = function(condition, success, fail)
+{
+ condition() ? success() : fail();
+};
+
+gaf._AtlasLoader.checkAtlas = function(atlas) // curried function
+{
+ return function(){return atlas && typeof atlas !== "string" && atlas.isLoaded()};
+};
+
+gaf._AtlasLoader.load = function(path, success, fail)
+{
+ cc.textureCache.addImage(path, function(atlas){
+ gaf._AtlasLoader.execute(
+ gaf._AtlasLoader.checkAtlas(atlas),
+ function(){success(atlas)},
+ fail
+ );
+ });
+};
+
+gaf._AtlasLoader.loadFront = function(arr, success, fail)
+{
+ // Call recursively this function for each element starting from the first
+ // stops on first success, or fails after last element
+ return function()
+ {
+ if (arr.length > 0){
+ gaf._AtlasLoader.load(
+ arr[0],
+ success,
+ gaf._AtlasLoader.loadFront(
+ arr.slice(1),
+ success,
+ fail
+ ));}
+ else
+ fail();
+ }
+};
+
+gaf._AtlasLoader.loadArray = function(array, success, fail)
+{
+ gaf._AtlasLoader.loadFront(array, success, fail)();
+};
diff --git a/external/gaf/Library/GAFDataReader.js b/external/gaf/Library/GAFDataReader.js
new file mode 100644
index 0000000000..3affbe1335
--- /dev/null
+++ b/external/gaf/Library/GAFDataReader.js
@@ -0,0 +1,229 @@
+gaf.DataReader = function(data) {
+ this.dataRaw = data;
+ this.buf = new DataView(data);
+ this.offset = [0];
+};
+
+gaf.DataReader.prototype.constructor = gaf.DataReader;
+
+gaf.DataReader.prototype.newOffset = function(size){
+ this.offset[this.offset.length - 1] += size;
+ if(this.getOffset() > this.maxOffset()){
+ throw new Error("GAF format error");
+ }
+ return this.offset[this.offset.length - 1] - size;
+};
+
+gaf.DataReader.prototype.maxOffset = function(){
+ if(this.offset.length == 1){
+ return this.buf.byteLength;
+ }
+ else{
+ return this.offset[this.offset.length - 2];
+ }
+};
+
+gaf.DataReader.prototype.getOffset = function(size){
+ return this.offset[this.offset.length - 1];
+};
+
+gaf.DataReader.prototype.Ubyte = function() {
+ return this.buf.getUint8(this.newOffset(1));
+};
+
+gaf.DataReader.prototype.Boolean = function() {
+ var result = this.buf.getUint8(this.newOffset(1));
+ if(result > 1){
+ throw new Error("GAF format error");
+ }
+ return result;
+};
+
+gaf.DataReader.prototype.Uint = function() {
+ return this.buf.getUint32(this.newOffset(4), true);
+};
+
+gaf.DataReader.prototype.Int = function() {
+ return this.buf.getInt32(this.newOffset(4), true);
+};
+
+gaf.DataReader.prototype.color = function() {
+ return {
+ b: this.Ubyte(),
+ g: this.Ubyte(),
+ r: this.Ubyte(),
+ a: this.Ubyte()
+ };
+};
+
+gaf.DataReader.prototype.Ushort = function() {
+ return this.buf.getUint16(this.newOffset(2), true);
+};
+
+gaf.DataReader.prototype.Float = function() {
+ return this.buf.getFloat32(this.newOffset(4), true);
+};
+
+gaf.DataReader.prototype.String = function() {
+ var strLen = this.Ushort();
+ var from = this.newOffset(strLen);
+ var to = this.getOffset();
+
+ try
+ {
+ var str = this.dataRaw.slice(from, to);
+ }
+ catch(e)
+ {
+ // Internet Explorer 10 T.T
+ if(e.message == "Object doesn't support property or method 'slice'")
+ {
+ str = [];
+ for(var i = from; i < to; ++i)
+ str.push(this.buf.getUint8(i));
+ }
+ else
+ {
+ throw(e);
+ }
+ }
+ return decodeURIComponent(escape(String.fromCharCode.apply(null, new Uint8Array(str))));
+
+};
+
+gaf.DataReader.prototype.startNestedBuffer = function(length) {
+ this.offset.push(this.offset[this.offset.length-1]);
+ this.offset[this.offset.length-2] += length;
+};
+
+gaf.DataReader.prototype.endNestedBuffer = function() {
+ if (this.offset.length == 1) throw new Error('No nested buffer available');
+ this.offset.pop();
+};
+
+gaf.DataReader.prototype.Point = function(){
+ return {
+ x: this.Float(),
+ y: this.Float()
+ };
+};
+
+gaf.DataReader.prototype.Rect = function(){
+ return {
+ x: this.Float(),
+ y: this.Float(),
+ width: this.Float(),
+ height: this.Float()
+ };
+};
+
+gaf.DataReader.prototype.Matrix = function(){
+ return {
+ a: this.Float(),
+ b: this.Float(),
+ c: this.Float(),
+ d: this.Float(),
+ tx: this.Float(),
+ ty: this.Float()
+ };
+};
+
+gaf.DataReader.prototype.seek = function(pos){
+ this.offset[this.offset.length-1] = pos;
+};
+
+gaf.DataReader.prototype.tell = function(){
+ return this.offset[this.offset.length-1];
+};
+
+/* Creates a fields parsing function
+* @ returns a function that will read from DataReader `field` of type `type`
+* @`key` - key for read data to be stored
+* @`data` - data to store. Can be DataReader function name or a function that will return a value
+* Note. Parameters pair `key` and `data` can be repeated any number of times*/
+
+gaf.DataReader.prototype.fields = function(){
+ var self = this;
+ var arguments_ = arguments;
+ return function(){
+ arguments.callee.result = {};
+ var i = 0;
+ if(arguments_.length % 2){
+ throw new Error('Number of arguments is not even');
+ }
+ while(i < arguments_.length){
+ var field = arguments_[i++];
+ var func = arguments_[i++];
+ if(typeof func === 'function'){
+ arguments.callee.result[field] = func();
+ }
+ else if (func in self && typeof self[func] === 'function'){
+ arguments.callee.result[field] = self[func].call(self);
+ }
+ else{
+ throw new Error('Object DataReader has no function `' + func + '`');
+ }
+ }
+ return arguments.callee.result;
+ }
+};
+
+/*
+* Creates a parsing function
+* @ returns function that will execute expression if caller's `result` field has `key` equal to `value` parameter
+* @ `key` - key in caller's `result` element
+* @ `value` - expected value of the `key` or a comparator function
+* @ `func` - function to execute if condition is true
+* */
+
+gaf.DataReader.prototype.condition = function(key, value, func){
+ var arguments_ = arguments;
+ return function() {
+ if(arguments_.length != 3){
+ throw new Error('Condition function');
+ }
+ var parent = arguments.callee.caller;
+ if(!('result' in parent)){
+ throw new Error('Condition function caller has no key `result`');
+ }
+ var container = parent.result;
+ var field = arguments_[0];
+ var value = arguments_[1];
+ var exec = arguments_[2];
+
+ var evaluate = null;
+ if(typeof value === 'function'){
+ evaluate = function(){return value(container[field]);};
+ }
+ else{
+ evaluate = function(){return value == container[field];};
+ }
+ if(evaluate()){
+ return exec();
+ }
+ else{
+ return null;
+ }
+ }
+};
+
+/*
+* Creates an array parsing function
+* @ returns function that will execute `func` number of times read from DataReader
+* @ `type` - type of count number
+* @ `func` - function to be executed
+* */
+
+gaf.DataReader.prototype.array = function(){
+ var self = this;
+ var arguments_ = arguments;
+ return function() {
+ arguments.callee.result = [];
+ var length = self[arguments_[0]].call(self);
+ for (var i = 0; i < length; ++i) {
+ var r = arguments_[1].call();
+ arguments.callee.result.push(r);
+ }
+ return arguments.callee.result;
+ }
+};
diff --git a/external/gaf/Library/GAFLoader.js b/external/gaf/Library/GAFLoader.js
new file mode 100644
index 0000000000..3e40c33947
--- /dev/null
+++ b/external/gaf/Library/GAFLoader.js
@@ -0,0 +1,75 @@
+var gaf = gaf || {};
+
+//@Private class
+gaf.Loader = function(){
+
+ var readHeaderBegin = function(stream, header){
+ header.compression = stream.Uint();
+ header.versionMajor = stream.Ubyte();
+ header.versionMinor = stream.Ubyte();
+ header.fileLength = stream.Uint();
+ };
+
+ var readHeaderEndV3 = function(stream, header) {
+ header.framesCount = stream.Ushort();
+ header.frameSize = stream.Rect();
+ header.pivot = stream.Point();
+ };
+
+ var readHeaderEndV4 = function(stream, header){
+ var scaleCount = stream.Uint();
+ header.scaleValues = [];
+ for(var i = 0; i < scaleCount; ++i){
+ header.scaleValues.push(stream.Float());
+ }
+ var csfCount = stream.Uint();
+ header.csfValues = [];
+ for(var i = 0; i < csfCount; ++i){
+ header.csfValues.push(stream.Float());
+ }
+ };
+
+ this.LoadFile = function(filePath, onLoaded){
+ var oReq = new XMLHttpRequest();
+ oReq.open("GET", filePath, true);
+ var self = this;
+ oReq.responseType = "arraybuffer";
+ oReq.onload = function(oEvent) {
+ var gaf_data = new gaf.DataReader(oReq.response);
+ var gafFile = self.LoadStream(gaf_data);
+ if(onLoaded)
+ onLoaded(gafFile);
+ };
+ oReq.send();
+ };
+
+ this.LoadStream = function(stream){
+ var header = {};
+ readHeaderBegin(stream, header);
+ if(header.compression == gaf.COMPRESSION_NONE) { // GAF
+ }
+ else if(header.compression == gaf.COMPRESSION_ZIP){ // GAC
+ var compressed = stream.dataRaw.slice(stream.tell());
+
+ var inflate = new window.Zlib.Inflate(new Uint8Array(compressed));
+ var decompressed = inflate.decompress();
+ stream = new gaf.DataReader(decompressed.buffer);
+ }
+ else{
+ throw new Error("GAF syntax error.");
+ }
+
+ if(header.versionMajor < 4){
+ readHeaderEndV3(stream, header);
+ }
+ else{
+ readHeaderEndV4(stream, header);
+ }
+
+ var tags = gaf.ReadTags(stream);
+ return {
+ header: header,
+ tags: tags
+ };
+ };
+};
diff --git a/external/gaf/Library/GAFMask.js b/external/gaf/Library/GAFMask.js
new file mode 100644
index 0000000000..34ca20681c
--- /dev/null
+++ b/external/gaf/Library/GAFMask.js
@@ -0,0 +1,36 @@
+
+gaf.Mask = gaf.Object.extend
+({
+ _className: "GAFMask",
+ _clippingNode: null,
+
+ ctor : function(gafSpriteProto)
+ {
+ this._super();
+ cc.assert(gafSpriteProto, "Error! Missing mandatory parameter.");
+ this._gafproto = gafSpriteProto;
+ },
+
+ _init : function()
+ {
+ var maskNodeProto = this._gafproto.getMaskNodeProto();
+ cc.assert(maskNodeProto, "Error. Mask node for id ref " + this._gafproto.getIdRef() + " not found.");
+ this._maskNode = maskNodeProto._gafConstruct();
+ this._clippingNode = cc.ClippingNode.create(this._maskNode);
+ this._clippingNode.setAlphaThreshold(0.5);
+ this.addChild(this._clippingNode);
+ },
+
+ setExternalTransform : function(affineTransform)
+ {
+ if(!cc.affineTransformEqualToTransform(this._maskNode._additionalTransform, affineTransform))
+ {
+ this._maskNode.setAdditionalTransform(affineTransform);
+ }
+ },
+
+ _getNode : function()
+ {
+ return this._clippingNode;
+ }
+});
\ No newline at end of file
diff --git a/external/gaf/Library/GAFMaskProto.js b/external/gaf/Library/GAFMaskProto.js
new file mode 100644
index 0000000000..6074fd1279
--- /dev/null
+++ b/external/gaf/Library/GAFMaskProto.js
@@ -0,0 +1,16 @@
+
+gaf._MaskProto = function(asset, mask, idRef)
+{
+ this.getIdRef = function(){return idRef};
+ this.getMaskNodeProto = function() {return mask};
+
+ /*
+ * Will construct GAFMask
+ */
+ this._gafConstruct = function()
+ {
+ var ret = new gaf.Mask(this);
+ ret._init();
+ return ret;
+ };
+};
diff --git a/external/gaf/Library/GAFObject.js b/external/gaf/Library/GAFObject.js
new file mode 100644
index 0000000000..7d5375abe5
--- /dev/null
+++ b/external/gaf/Library/GAFObject.js
@@ -0,0 +1,426 @@
+var gaf = gaf || {};
+
+gaf._stateHasCtx = function(state)
+{
+ // Check for tint color offset
+ if( state.hasColorTransform &&
+ (state.colorTransform.offset.r > 0 ||
+ state.colorTransform.offset.g > 0 ||
+ state.colorTransform.offset.b > 0 ||
+ state.colorTransform.offset.a > 0)
+ )
+ {
+ return true;
+ }
+
+ // Check for color transform filter
+ if(state.hasEffect)
+ {
+ for(var i = 0, total = state.effect.length; i < total; ++i)
+ {
+ if(state.effect[i].type === gaf.EFFECT_COLOR_MATRIX)
+ return true;
+ }
+ }
+ return false;
+};
+
+gaf.Object = cc.Node.extend
+({
+ _asset : null,
+ _className : "GAFObject",
+ _id : gaf.IDNONE,
+ _gafproto : null,
+ _parentTimeLine : null,
+ _lastVisibleInFrame : 0,
+ _filterStack : null,
+ _cascadeColorMult : null,
+ _cascadeColorOffset : null,
+ _needsCtx : false,
+ _usedAtlasScale: 1,
+
+ // Public methods
+ ctor: function(scale)
+ {
+ if(arguments.length == 1)
+ {
+ this._usedAtlasScale = scale;
+ }
+ this._super();
+ this._cascadeColorMult = cc.color(255, 255, 255, 255);
+ this._cascadeColorOffset = cc.color(0, 0, 0, 0);
+ this._filterStack = [];
+ },
+
+ /**
+ * @method setAnimationStartedNextLoopDelegate
+ * @param {function(Object)} delegate
+ */
+ setAnimationStartedNextLoopDelegate : function (delegate) {},
+
+ /**
+ * @method setAnimationFinishedPlayDelegate
+ * @param {function(Object)} delegate
+ */
+ setAnimationFinishedPlayDelegate : function (delegate) {},
+
+ /**
+ * @method setLooped
+ * @param {bool} looped
+ */
+ setLooped : function (looped) {},
+
+ /**
+ * @method getBoundingBoxForCurrentFrame
+ * @return {cc.Rect}
+ */
+ getBoundingBoxForCurrentFrame : function () {return null;},
+
+ /**
+ * @method setFps
+ * @param {uint} fps
+ */
+ setFps : function (fps) {},
+
+ /**
+ * @method getObjectByName
+ * @param {String} name - name of the object to find
+ * @return {gaf.Object}
+ */
+ getObjectByName : function (name) {return null;},
+
+ /**
+ * @method clearSequence
+ */
+ clearSequence : function () {},
+
+ /**
+ * @method getIsAnimationRunning
+ * @return {bool}
+ */
+ getIsAnimationRunning : function () {return false;},
+
+ /**
+ * @method getSequences
+ * @return [string] - list of sequences if has any
+ */
+ getSequences : function(){return [];},
+
+
+ /**
+ * @method gotoAndStop
+ * @param {uint|String} value - label ot frame number
+ * @return {bool}
+ */
+ gotoAndStop : function (value) {},
+
+ /**
+ * @method getStartFrame
+ * @param {String} frameLabel
+ * @return {uint}
+ */
+ getStartFrame : function (frameLabel) {return gaf.IDNONE;},
+
+ /**
+ * @method setFramePlayedDelegate
+ * @param {function(Object, frame)} delegate
+ */
+ setFramePlayedDelegate : function (delegate) {},
+
+ /**
+ * @method getCurrentFrameIndex
+ * @return {uint}
+ */
+ getCurrentFrameIndex : function () {
+ return gaf.IDNONE;
+ },
+
+ /**
+ * @method getTotalFrameCount
+ * @return {uint}
+ */
+ getTotalFrameCount : function () {return 0;},
+
+ /**
+ * @method start
+ */
+ start : function () {},
+
+ /**
+ * @method stop
+ */
+ stop : function () {},
+
+ /**
+ * @method isVisibleInCurrentFrame
+ * @return {bool}
+ */
+ isVisibleInCurrentFrame : function ()
+ {
+ /*if (this._parentTimeLine &&
+ ((this._parentTimeLine.getCurrentFrameIndex() + 1) != this._lastVisibleInFrame))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }*/
+ return !(this._parentTimeLine && ((this._parentTimeLine.getCurrentFrameIndex() + 1) != this._lastVisibleInFrame));
+ },
+
+ /**
+ * @method isDone
+ * @return {bool}
+ */
+ isDone : function () {return true;},
+
+ /**
+ * @method playSequence
+ * @param {String} name - name of the sequence to play
+ * @param {bool} looped - play looped
+ * @param {bool} resume - whether to resume animation if stopped. True by default
+ * @return {bool}
+ */
+ playSequence : function (name, looped, resume) {return false;},
+
+ /**
+ * @method isReversed
+ * @return {bool}
+ */
+ isReversed : function () {return false;},
+
+ /**
+ * @method setSequenceDelegate
+ * @param {function(Object, sequenceName)} delegate
+ */
+ setSequenceDelegate : function (delegate) {},
+
+ /**
+ * @method setFrame
+ * @param {uint} index
+ * @return {bool}
+ */
+ setFrame : function (index) {return false;},
+
+ /**
+ * @method setControlDelegate
+ * @param {function} func
+ */
+ setControlDelegate : function (func) {},
+
+ /**
+ * @method getEndFrame
+ * @param {String} frameLabel
+ * @return {uint}
+ */
+ getEndFrame : function (frameLabel) {return gaf.IDNONE;},
+
+ /**
+ * @method pauseAnimation
+ */
+ pauseAnimation : function () {},
+
+ /**
+ * @method gotoAndPlay
+ * @param {uint|String} value - label ot frame number
+ * @return {bool}
+ */
+ gotoAndPlay : function (value) {},
+
+ /**
+ * @method isLooped
+ * @return {bool}
+ */
+ isLooped : function () {return false;},
+
+ /**
+ * @method resumeAnimation
+ */
+ resumeAnimation : function () {},
+
+ /**
+ * @method setReversed
+ * @param {bool} reversed
+ */
+ setReversed : function (reversed) {},
+
+ /**
+ * @method hasSequences
+ * @return {bool}
+ */
+ hasSequences : function () {return false;},
+
+ /**
+ * @method getFps
+ * @return {uint}
+ */
+ getFps : function () {return 60;},
+
+ /**
+ * @method setLocator
+ * @param {bool} locator
+ * Locator object will not draw itself, but its children will be drawn
+ */
+ setLocator : function (locator){},
+
+ setExternalTransform : function(affineTransform)
+ {
+ if(!cc.affineTransformEqualToTransform(this._additionalTransform, affineTransform))
+ {
+ this.setAdditionalTransform(affineTransform);
+ }
+ },
+
+ getExternalTransform : function()
+ {
+ return this._additionalTransform;
+ },
+
+ setAnimationRunning: function () {},
+
+ ////////////////
+ // Private
+ ////////////////
+ _enableTick: function(val){},
+
+ _resetState : function()
+ {},
+
+ _updateVisibility : function(state, parent)
+ {
+ var alphaOffset = state.hasColorTransform ? state.colorTransform.offset.a : 0;
+ this.setOpacity(state.alpha + alphaOffset);
+ //return this.isVisible();
+ },
+
+ // @Override
+ isVisible : function()
+ {
+ return this.getOpacity() > 0;
+ },
+
+ // @Override
+ visit: function(parentCmd)
+ {
+ if(this.isVisibleInCurrentFrame())
+ {
+ this._super(parentCmd);
+ }
+ },
+
+ _getFilters : function(){return null},
+
+ _processAnimation : function(){},
+
+
+ _applyState : function(state, parent)
+ {
+ this._applyStateSuper(state, parent);
+ },
+
+ _applyStateSuper : function(state, parent)
+ {
+ this._needsCtx = parent._needsCtx;
+ this._filterStack.length = 0; // clear
+ this._parentTimeLine = parent; // only gaf time line can call applyState. Assign it as parent
+ if(this._usedAtlasScale != 1)
+ {
+ var newMat = cc.clone(state.matrix);
+ newMat.tx *= this._usedAtlasScale;
+ newMat.ty *= this._usedAtlasScale;
+ this.setExternalTransform(newMat); // apply transformations of the state
+ }
+ else
+ {
+ this.setExternalTransform(state.matrix); // apply transformations of the state
+ }
+ // Cascade filters
+ // TODO: apply more than one filter
+ if (state.hasEffect) {
+ this._filterStack = this._filterStack.concat(state.effect);
+ this._needsCtx = true;
+ }
+ if (parent._filterStack && parent._filterStack.length > 0) {
+ this._filterStack = this._filterStack.concat(parent._filterStack);
+ }
+
+ if(this._filterStack.length > 0 && this._filterStack[0].type === gaf.EFFECT_COLOR_MATRIX)
+ {
+ this._needsCtx = true;
+ }
+
+ // Cascade color transformations
+
+ // If state has a tint, then we should process it
+ if (state.hasColorTransform)
+ {
+ this._cascadeColorMult.r = state.colorTransform.mult.r * parent._cascadeColorMult.r / 255;
+ this._cascadeColorMult.g = state.colorTransform.mult.g * parent._cascadeColorMult.g / 255;
+ this._cascadeColorMult.b = state.colorTransform.mult.b * parent._cascadeColorMult.b / 255;
+ this._cascadeColorMult.a = state.colorTransform.mult.a * parent._cascadeColorMult.a / 255;
+
+ this._cascadeColorOffset.r = state.colorTransform.offset.r + parent._cascadeColorOffset.r;
+ this._cascadeColorOffset.g = state.colorTransform.offset.g + parent._cascadeColorOffset.g;
+ this._cascadeColorOffset.b = state.colorTransform.offset.b + parent._cascadeColorOffset.b;
+ this._cascadeColorOffset.a = state.colorTransform.offset.a + parent._cascadeColorOffset.a;
+ }
+ else
+ {
+ this._cascadeColorMult.r = parent._cascadeColorMult.r;
+ this._cascadeColorMult.g = parent._cascadeColorMult.g;
+ this._cascadeColorMult.b = parent._cascadeColorMult.b;
+ this._cascadeColorMult.a = state.alpha * (parent._cascadeColorMult.a / 255);
+
+ this._cascadeColorOffset.r = parent._cascadeColorOffset.r;
+ this._cascadeColorOffset.g = parent._cascadeColorOffset.g;
+ this._cascadeColorOffset.b = parent._cascadeColorOffset.b;
+ this._cascadeColorOffset.a = parent._cascadeColorOffset.a;
+ }
+
+ if (this._cascadeColorOffset.r > 0 ||
+ this._cascadeColorOffset.g > 0 ||
+ this._cascadeColorOffset.b > 0 ||
+ this._cascadeColorOffset.a > 0)
+ {
+ this._needsCtx = true;
+ }
+ },
+
+ _initRendererCmd: function()
+ {
+ this._renderCmd = cc.renderer.getRenderCmd(this);
+ this._renderCmd._visit = this._renderCmd.visit;
+ var self = this;
+ this._renderCmd.visit = function(parentCmd) {
+ if(self.isVisibleInCurrentFrame()){
+ this._visit(parentCmd);
+ }
+ }
+ },
+
+ _getNode : function()
+ {
+ return this;
+ },
+
+ setAnchorPoint : function(point, y)
+ {
+ if (y === undefined)
+ {
+ this._super(point.x, point.y - 1);
+ }
+ else
+ {
+ this._super(point, y - 1);
+ }
+ }
+
+});
+
+gaf.Object._createNullObject = function()
+{
+ var ret = new gaf.Object();
+ ret.isVisible = function(){return true};
+ return ret;
+};
diff --git a/external/gaf/Library/GAFShaderManager.js b/external/gaf/Library/GAFShaderManager.js
new file mode 100644
index 0000000000..49b7ffba0f
--- /dev/null
+++ b/external/gaf/Library/GAFShaderManager.js
@@ -0,0 +1,63 @@
+
+gaf._glShaderInit = function() {
+ gaf._Uniforms = {
+ ColorTransformMult: -1,
+ ColorTransformOffset: -1,
+ ColorMatrixBody: -1,
+ ColorMatrixAppendix: -1,
+ BlurTexelOffset: -1,
+ GlowTexelOffset: -1,
+ GlowColor: -1
+ };
+
+ gaf._shaderCreate = function (fs, vs) {
+ var program = new cc.GLProgram();
+ var result = program.initWithVertexShaderByteArray(vs, fs);
+ cc.assert(result, "Shader init error");
+ program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
+ program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
+ program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
+ result = program.link();
+ cc.assert(result, "Shader linking error");
+ program.updateUniforms();
+ return program;
+ };
+
+ gaf._shaderCreateAlpha = function () {
+ var program = gaf._shaderCreate(gaf.SHADER_COLOR_MATRIX_FRAG, cc.SHADER_POSITION_TEXTURE_COLOR_VERT);
+ gaf._Uniforms.ColorTransformMult = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_TINT_MULT);
+ gaf._Uniforms.ColorTransformOffset = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_TINT_OFFSET);
+ gaf._Uniforms.ColorMatrixBody = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_COLOR_MATRIX_BODY);
+ gaf._Uniforms.ColorMatrixAppendix = program.getUniformLocationForName(gaf.UNIFORM_ALPHA_COLOR_MATRIX_APPENDIX);
+ return program;
+ };
+
+ gaf._shaderCreateBlur = function () {
+ var program = gaf._shaderCreate(gaf.SHADER_GAUSSIAN_BLUR_FRAG, cc.SHADER_POSITION_TEXTURE_COLOR_VERT);
+ gaf._Uniforms.BlurTexelOffset = program._glContext.getUniformLocation(program._programObj, gaf.UNIFORM_BLUR_TEXEL_OFFSET);
+
+ return program;
+ };
+
+ gaf._shaderCreateGlow = function () {
+ var program = gaf._shaderCreate(gaf.SHADER_GLOW_FRAG, cc.SHADER_POSITION_TEXTURE_COLOR_VERT);
+ gaf._Uniforms.GlowTexelOffset = program._glContext.getUniformLocation(program._programObj, gaf.UNIFORM_GLOW_TEXEL_OFFSET);
+ gaf._Uniforms.GlowColor = program._glContext.getUniformLocation(program._programObj, gaf.UNIFORM_GLOW_COLOR);
+ return program;
+ };
+
+ gaf._Shaders = {
+ Alpha: gaf._shaderCreateAlpha(),
+ Blur: gaf._shaderCreateBlur(),
+ Glow: gaf._shaderCreateGlow()
+ };
+};
+
+gaf._setupShaders = function() {
+ if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
+ gaf._glShaderInit();
+ }
+ else {
+ delete gaf._glShaderInit;
+ }
+};
diff --git a/external/gaf/Library/GAFShaders.js b/external/gaf/Library/GAFShaders.js
new file mode 100644
index 0000000000..7d91537285
--- /dev/null
+++ b/external/gaf/Library/GAFShaders.js
@@ -0,0 +1,58 @@
+gaf.SHADER_GAUSSIAN_BLUR_FRAG =
+ "varying mediump vec2 v_texCoord;\n"
+ + "uniform mediump vec2 u_step;\n"
+ + "void main()\n"
+ + "{ \n"
+ + " mediump vec4 sum = vec4(0.0); \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 4.0) * 0.05; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 3.0) * 0.09; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 2.0) * 0.12; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 1.0) * 0.15; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 0.0) * 0.18; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 1.0) * 0.15; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 2.0) * 0.12; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 3.0) * 0.09; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 4.0) * 0.05; \n"
+ + " gl_FragColor = sum; \n"
+ + "} \n";
+
+gaf.SHADER_GLOW_FRAG =
+ "varying mediump vec2 v_texCoord;\n"
+ + "uniform mediump vec2 u_step;\n"
+ + "uniform mediump vec4 u_glowColor;\n"
+ + "void main()\n"
+ + "{ \n"
+ + " mediump vec4 sum = vec4(0.0); \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 4.0) * 0.05; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 3.0) * 0.09; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 2.0) * 0.12; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord - u_step * 1.0) * 0.15; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 0.0) * 0.18; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 1.0) * 0.15; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 2.0) * 0.12; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 3.0) * 0.09; \n"
+ + " sum += texture2D(CC_Texture0, v_texCoord + u_step * 4.0) * 0.05; \n"
+ + " gl_FragColor = sum * u_glowColor; \n"
+ + "} \n";
+
+gaf.SHADER_COLOR_MATRIX_FRAG =
+ "varying mediump vec2 v_texCoord;\n"
+ + "varying mediump vec4 v_fragmentColor;\n"
+ + "uniform mediump vec4 colorTransformMult;\n"
+ + "uniform mediump vec4 colorTransformOffsets;\n"
+ + "uniform mediump mat4 colorMatrix;\n"
+ + "uniform mediump vec4 colorMatrix2;\n"
+ + "void main()\n"
+ + "{ \n"
+ + " vec4 texColor = texture2D(CC_Texture0, v_texCoord); \n"
+ + " const float kMinimalAlphaAllowed = 1.0e-8; \n"
+ + " if (texColor.a > kMinimalAlphaAllowed) \n"
+ + " { \n"
+ + " texColor = vec4(texColor.rgb / texColor.a, texColor.a); \n"
+ + " vec4 ctxColor = texColor * colorTransformMult + colorTransformOffsets; \n"
+ + " vec4 adjustColor = colorMatrix * ctxColor + colorMatrix2; \n"
+ + " adjustColor *= v_fragmentColor; \n"
+ + " texColor = vec4(adjustColor.rgb * adjustColor.a, adjustColor.a); \n"
+ + " } \n"
+ + " gl_FragColor = texColor; \n"
+ + "}\n";
diff --git a/external/gaf/Library/GAFSprite.js b/external/gaf/Library/GAFSprite.js
new file mode 100644
index 0000000000..2387bf92df
--- /dev/null
+++ b/external/gaf/Library/GAFSprite.js
@@ -0,0 +1,100 @@
+
+gaf.Sprite = gaf.Object.extend
+({
+ _className: "GAFSprite",
+
+ _hasCtx: false,
+ _hasFilter: false,
+
+ ctor : function(gafSpriteProto, usedScale)
+ {
+ this._super(usedScale);
+ cc.assert(gafSpriteProto, "Error! Missing mandatory parameter.");
+ this._gafproto = gafSpriteProto;
+ },
+
+ // Private
+
+ _init : function()
+ {
+ var frame = this._gafproto.getFrame();
+ cc.assert(frame instanceof cc.SpriteFrame, "Error. Wrong object type.");
+
+ // Create sprite with custom render command from frame
+ this._sprite = new cc.Sprite();
+ this._sprite._renderCmd = this._gafCreateRenderCmd(this._sprite);
+ this._sprite.initWithSpriteFrame(frame);
+
+ this._sprite.setAnchorPoint(this._gafproto.getAnchor());
+ this.addChild(this._sprite);
+ //this._sprite.setCascadeColorEnabled(true);
+ //this._sprite.setCascadeOpacityEnabled(true);
+ this._sprite.setOpacityModifyRGB(true);
+
+ if(cc._renderType === cc.game.RENDER_TYPE_WEBGL)
+ this._sprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
+ },
+
+ _applyState : function(state, parent)
+ {
+ this._applyStateSuper(state, parent);
+ if(this._needsCtx)
+ {
+ // Enable ctx state if wasn't enabled
+ if(!this._hasCtx)
+ {
+ this._enableCtx();
+ this._hasCtx = true;
+ }
+ // Set ctx shader
+ this._applyCtxState(state);
+ }
+ else
+ {
+ // Disable ctx state if was enabled
+ if(this._hasCtx)
+ {
+ this._disableCtx();
+ this._hasCtx = false;
+ }
+ // Apply color
+ if(!cc.colorEqual(this._sprite._realColor, this._cascadeColorMult))
+ {
+ this._sprite.setColor(this._cascadeColorMult);
+ }
+ // Apply opacity
+ if(this._sprite.getOpacity() != this._cascadeColorMult.a)
+ {
+ this._sprite.setOpacity(this._cascadeColorMult.a);
+ }
+
+ }
+ },
+
+ _enableCtx: function()
+ {
+ this._sprite._renderCmd._enableCtx();
+ },
+
+ _disableCtx: function()
+ {
+ this._sprite._renderCmd._disableCtx();
+ },
+
+ _applyCtxState: function(state){
+ this._sprite._renderCmd._applyCtxState(this);
+ },
+
+ getBoundingBoxForCurrentFrame: function ()
+ {
+ var result = this._sprite.getBoundingBox();
+ return cc._rectApplyAffineTransformIn(result, this.getNodeToParentTransform());
+ },
+
+ _gafCreateRenderCmd: function(item){
+ if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
+ return new gaf.Sprite.CanvasRenderCmd(item);
+ else
+ return new gaf.Sprite.WebGLRenderCmd(item);
+ }
+});
diff --git a/external/gaf/Library/GAFSpriteCanvasRenderCmd.js b/external/gaf/Library/GAFSpriteCanvasRenderCmd.js
new file mode 100644
index 0000000000..bb807cc220
--- /dev/null
+++ b/external/gaf/Library/GAFSpriteCanvasRenderCmd.js
@@ -0,0 +1,233 @@
+
+(function() {
+ gaf.Sprite.CanvasRenderCmd = function (renderable) {
+ cc.Sprite.CanvasRenderCmd.call(this, renderable);
+ this._hasTintMult = false;
+ this._hasTintOffset = false;
+ this._hasCtx = false;
+ this._tintMult = cc.color(255,255,255,255);
+ this._tintOffset = cc.color(0,0,0,0);
+ this._textureDirty = false;
+ };
+ var proto = gaf.Sprite.CanvasRenderCmd.prototype = Object.create(cc.Sprite.CanvasRenderCmd.prototype);
+ proto.constructor = gaf.Sprite.CanvasRenderCmd;
+
+ proto._disableCtx = function(){
+ this._hasTintOffset = false;
+ this._hasCtx = false;
+ this._textureDirty = true;
+ this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ this._tintMult = cc.color(255,255,255,255);
+ this._tintOffset = cc.color(0,0,0,0);
+ };
+
+ proto._enableCtx = function(){
+
+ };
+
+ proto._applyCtxState = function(gafObject){
+
+ var tintMult = gafObject._cascadeColorMult;
+ var tintOffset = gafObject._cascadeColorOffset;
+ var opacity = tintMult.a;
+
+ // Apply opacity
+ if(this._node.getOpacity() != opacity)
+ {
+ this._node.setOpacity(opacity);
+ }
+
+ // Check Tint multiplicator
+ var multDirty = !cc.colorEqual(this._tintMult, tintMult);
+ if(multDirty)
+ {
+ this._node.setColor(tintMult);
+ this._tintMult = tintMult;
+ this._hasTintMult =
+ (tintMult.r !== 255 ||
+ tintMult.g !== 255 ||
+ tintMult.b !== 255 );
+ }
+
+ // Check Tint offset
+ var offfsetDirty =
+ (this._tintOffset.r != tintOffset.r) ||
+ (this._tintOffset.g != tintOffset.g) ||
+ (this._tintOffset.b != tintOffset.b) ||
+ (this._tintOffset.a != tintOffset.a);
+
+ if(offfsetDirty)
+ {
+ this._tintOffset = tintOffset;
+ this._hasTintOffset =
+ (tintOffset.r !== 0 ||
+ tintOffset.g !== 0 ||
+ tintOffset.b !== 0 ||
+ tintOffset.a !== 0 );
+ }
+
+ // Update dirty flag
+ this._textureDirty = multDirty || offfsetDirty;
+ if(this._textureDirty)
+ {
+ this.setDirtyFlag(cc.Node._dirtyFlags.colorDirty);
+ }
+
+
+ this._hasCtx = gafObject._filterStack.length > 0 && gafObject._filterStack[0].type === gaf.EFFECT_COLOR_MATRIX;
+
+ };
+
+ proto.rendering = function(ctx, scaleX, scaleY)
+ {
+ var node = this._node;
+ var locTextureCoord = this._textureCoord,
+ alpha = (this._displayedOpacity / 255);
+
+ if ((node._texture && ((locTextureCoord.width === 0 || locTextureCoord.height === 0) //set texture but the texture isn't loaded.
+ || !node._texture._textureLoaded)) || alpha === 0)
+ return;
+
+ var wrapper = ctx || cc._renderContext,
+ context = wrapper.getContext();
+ var locX = node._offsetPosition.x,
+ locHeight = node._rect.height,
+ locWidth = node._rect.width,
+ locY = -node._offsetPosition.y - locHeight,
+ image;
+
+ wrapper.setTransform(this._worldTransform, scaleX, scaleY);
+ wrapper.setCompositeOperation(this._blendFuncStr);
+ wrapper.setGlobalAlpha(alpha);
+
+ if(node._flippedX || node._flippedY)
+ wrapper.save();
+ if (node._flippedX) {
+ locX = -locX - locWidth;
+ context.scale(-1, 1);
+ }
+ if (node._flippedY) {
+ locY = node._offsetPosition.y;
+ context.scale(1, -1);
+ }
+
+ image = node._texture._htmlElementObj;
+
+ if (this._colorized) {
+ context.drawImage(image,
+ 0, 0, locTextureCoord.width,locTextureCoord.height,
+ locX * scaleX,locY * scaleY, locWidth * scaleX, locHeight * scaleY);
+ } else {
+ context.drawImage(image,
+ locTextureCoord.renderX, locTextureCoord.renderY, locTextureCoord.width, locTextureCoord.height,
+ locX * scaleX, locY * scaleY, locWidth * scaleX, locHeight * scaleY);
+ }
+
+ if(node._flippedX || node._flippedY)
+ wrapper.restore();
+ cc.g_NumberOfDraws++;
+ };
+
+ if(cc.sys._supportCanvasNewBlendModes){
+ proto._updateColor = function () {
+ var displayedColor = this._displayedColor, node = this._node;
+ this._hasTintMult |= (displayedColor.r !== 255 || displayedColor.g !== 255 || displayedColor.b !== 255);
+
+ // If no color changes
+ if(this._textureDirty)
+ {
+ this._textureDirty = false;
+ if (this._colorized) {
+ this._colorized = false;
+ node.texture = this._originalTexture;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ var locElement, locTexture = node._texture, locRect = this._textureCoord;
+ if(this._hasTintMult)
+ {
+ if (locTexture && locRect.validRect && this._originalTexture) {
+ locElement = locTexture.getHtmlElementObj();
+ if (!locElement)
+ return;
+
+ this._colorized = true;
+ if (this._hasTintOffset || this._hasCtx) displayedColor = this._tintMult;
+
+ locElement = cc.Sprite.CanvasRenderCmd._generateTintImageWithMultiply(this._originalTexture._htmlElementObj, displayedColor, locRect);
+ locTexture = new cc.Texture2D();
+ locTexture.initWithElement(locElement);
+ locTexture.handleLoadedTexture();
+ node.texture = locTexture;
+ }
+ }
+
+ locTexture = node._texture;
+ if(this._hasTintOffset)
+ {
+ var cacheTextureForColor = cc.textureCache.getTextureColors(this._originalTexture.getHtmlElementObj());
+ if (locTexture && locRect.validRect && this._originalTexture) {
+ locElement = locTexture.getHtmlElementObj();
+ if (!locElement)
+ return;
+ if(this._colorized)
+ var texRect = cc.rect(0,0,locRect.width, locRect.height);
+ else
+ texRect = locRect;
+ locElement = this._gafGenerateTintImage(node.texture._htmlElementObj, texRect, cacheTextureForColor, this._tintOffset, locRect);
+ locTexture = new cc.Texture2D();
+ locTexture.initWithElement(locElement);
+ locTexture.handleLoadedTexture();
+ node.texture = locTexture;
+ this._colorized = true;
+ }
+ }
+
+
+ };
+
+ proto._gafGenerateTintImage = function(texture, texRect, tintedImgCache, color, rect, renderCanvas){
+ if (!rect)
+ rect = cc.rect(0, 0, texture.width, texture.height);
+
+ // Create a new buffer if required
+ var w = Math.min(rect.width, tintedImgCache[0].width);
+ var h = Math.min(rect.height, tintedImgCache[0].height);
+ var buff = renderCanvas, ctx;
+ if (!buff) {
+ buff = document.createElement("canvas");
+ buff.width = w;
+ buff.height = h;
+ ctx = buff.getContext("2d");
+ } else {
+ ctx = buff.getContext("2d");
+ ctx.clearRect(0, 0, w, h);
+ }
+ ctx.save();
+
+ // draw a channel with alpha of the original image
+ ctx.globalCompositeOperation = 'source-over';
+ //ctx.globalAlpha = 1;
+ ctx.drawImage(tintedImgCache[2], rect.x, rect.y, w, h, 0, 0, w, h);
+
+ // draw a rect of specified color
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.fillStyle = 'rgba(' + Math.round(color.r) + ',' + Math.round(color.g) + ',' + Math.round(color.b) + ',1)';
+ ctx.fillRect(0, 0, w, h);
+
+ // add the desired image to the drawn
+ ctx.globalCompositeOperation = 'lighter';
+ ctx.drawImage(texture, texRect.x, texRect.y, w, h, 0, 0, w, h);
+
+
+ ctx.restore();
+ return buff;
+
+ };
+ }
+
+})();
diff --git a/external/gaf/Library/GAFSpriteProto.js b/external/gaf/Library/GAFSpriteProto.js
new file mode 100644
index 0000000000..6e33fa7d5f
--- /dev/null
+++ b/external/gaf/Library/GAFSpriteProto.js
@@ -0,0 +1,36 @@
+
+gaf._SpriteProto = function(asset, atlasFrames, elementAtlasIdRef)
+{
+ //this._anchor = atlasFrame._gafAnchor;
+ //delete atlasFrame._gafAnchor;
+
+ this.getFrames = function(){return atlasFrames};
+ this.getIdRef = function(){return elementAtlasIdRef};
+ //this.getAnchor = function() {return this._anchor};
+ this.getAsset = function() {return asset};
+
+ /*
+ * Will construct GAFSprite
+ */
+ this._gafConstruct = function()
+ {
+ var usedScale = this.getAsset()._usedAtlasScale;
+ var ret = new gaf.Sprite(this, usedScale);
+ ret._init();
+ return ret;
+ };
+};
+
+gaf._SpriteProto.prototype.getFrame = function()
+{
+ var usedScale = this.getAsset()._usedAtlasScale;
+ cc.assert(usedScale, "Error. Atlas scale zero.");
+ var frames = this.getFrames()[usedScale];
+ cc.assert(frames, "Error. No frames found for used scale `"+usedScale+"`");
+ return frames[this.getIdRef()];
+};
+
+gaf._SpriteProto.prototype.getAnchor = function()
+{
+ return this.getFrame()._gafAnchor;
+};
diff --git a/external/gaf/Library/GAFSpriteWebGLRenderCmd.js b/external/gaf/Library/GAFSpriteWebGLRenderCmd.js
new file mode 100644
index 0000000000..eabe25b0c9
--- /dev/null
+++ b/external/gaf/Library/GAFSpriteWebGLRenderCmd.js
@@ -0,0 +1,132 @@
+
+(function(){
+ gaf.Sprite.WebGLRenderCmd = function (renderable) {
+ cc.Sprite.WebGLRenderCmd.call(this, renderable);
+ this._defualtShader = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
+ this._customShader = gaf._Shaders.Alpha;
+
+ //this._shaderProgram = this._defualtShader;
+
+ this._tintMult = null;
+ this._tintOffset = null;
+ this._ctxMatrixBody = null;
+ this._ctxMatrixAppendix = null;
+ };
+
+ var proto = gaf.Sprite.WebGLRenderCmd.prototype = Object.create(cc.Sprite.WebGLRenderCmd.prototype);
+ proto.constructor = gaf.Sprite.WebGLRenderCmd;
+
+ proto._identityVec = [1.0, 1.0, 1.0, 1.0];
+ proto._zeroVec = [0.0, 0.0, 0.0, 0.0];
+ proto._identityMat = [
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ ];
+
+ proto._disableCtx = function(){
+ this.setShaderProgram(this._defualtShader);
+ };
+
+ proto._enableCtx = function(){
+ this.setShaderProgram(this._customShader);
+ };
+
+ proto._applyCtxState = function(gafObject){
+ var tintMult = gafObject._cascadeColorMult;
+ this._tintMult = [
+ tintMult.r / 255,
+ tintMult.g / 255,
+ tintMult.b / 255,
+ tintMult.a / 255
+ ];
+
+ var tintOffset = gafObject._cascadeColorOffset;
+ this._tintOffset = [
+ tintOffset.r / 255,
+ tintOffset.g / 255,
+ tintOffset.b / 255,
+ tintOffset.a / 255
+ ];
+
+ var filterStack = gafObject._filterStack;
+ if(filterStack && filterStack.length > 0 && filterStack[0].type === gaf.EFFECT_COLOR_MATRIX)
+ {
+ var m = filterStack[0].colorMatrix;
+ this._ctxMatrixBody = [
+ m.rr, m.rg, m.rb, m.ra,
+ m.gr, m.gg, m.gb, m.ga,
+ m.br, m.bg, m.bb, m.ba,
+ m.ar, m.ag, m.ab, m.aa
+ ];
+ this._ctxMatrixAppendix = [
+ m.r / 255,
+ m.g / 255,
+ m.b / 255,
+ m.a / 255
+ ];
+ }
+ else
+ {
+ this._ctxMatrixBody = null;
+ this._ctxMatrixAppendix = null;
+ }
+ };
+
+ proto._setUniforms = function()
+ {
+ if(this._shaderProgram === this._customShader)
+ {
+ this._shaderProgram.use();
+ {
+ this._shaderProgram.setUniformLocationWith4fv(
+ gaf._Uniforms.ColorTransformMult,
+ this._tintMult,
+ 1
+ );
+ this._shaderProgram.setUniformLocationWith4fv(
+ gaf._Uniforms.ColorTransformOffset,
+ this._tintOffset,
+ 1
+ );
+ }
+
+ if(this._ctxMatrixBody && this._ctxMatrixAppendix)
+ {
+ this._shaderProgram.setUniformLocationWithMatrix4fv(
+ gaf._Uniforms.ColorMatrixBody,
+ this._ctxMatrixBody,
+ 1
+ );
+ this._shaderProgram.setUniformLocationWith4fv(
+ gaf._Uniforms.ColorMatrixAppendix,
+ this._ctxMatrixAppendix,
+ 1
+ );
+ }
+ else
+ {
+ this._shaderProgram.setUniformLocationWithMatrix4fv(
+ gaf._Uniforms.ColorMatrixBody,
+ this._identityMat,
+ 1
+ );
+ this._shaderProgram.setUniformLocationWith4fv(
+ gaf._Uniforms.ColorMatrixAppendix,
+ this._zeroVec,
+ 1
+ );
+ }
+ }
+ };
+
+ proto.rendering = function(ctx)
+ {
+ this._setUniforms();
+
+ // Super call
+ cc.Sprite.WebGLRenderCmd.prototype.rendering.call(this, ctx);
+ };
+
+})();
diff --git a/external/gaf/Library/GAFTags.js b/external/gaf/Library/GAFTags.js
new file mode 100644
index 0000000000..09f8186538
--- /dev/null
+++ b/external/gaf/Library/GAFTags.js
@@ -0,0 +1,378 @@
+
+gaf.ReadSingleTag = function(stream){
+ var tagId = stream.Ushort();
+ var tag = gaf.Tags[tagId];
+ var result = {};
+ if(typeof tag === "undefined"){
+ console.log("GAF. Non implemented tag detected.");
+ gaf.Tags.Default.parse(stream, tagId);
+ }
+ else{
+ //console.log("tag " + tag.tagName);
+ result = tag.parse(stream, tagId);
+ }
+ return result;
+};
+
+gaf.ReadTags = function(stream){
+ var tags = [];
+ try {
+ do {
+ var tag = gaf.ReadSingleTag(stream);
+ tags.push(tag);
+ } while (tag.tagId != 0);
+ }
+ catch (e){
+ if (e instanceof Error && e.message == "GAF format error"){
+ console.log("GAF format error:\n" + e.stack);
+ // Tag will be closed and parser will continue from where it should.
+ }
+ else{
+ console.log(e.stack);
+ throw e;
+ }
+ }
+ return tags;
+};
+
+
+gaf.Tag = function(){
+ this.Default = Object.create(gaf.Tag.base);
+ this["0"] = Object.create(gaf.Tag.End);
+ this["1"] = Object.create(gaf.Tag.DefineAtlas);
+ this["2"] = Object.create(gaf.Tag.DefineAnimationMasks);
+ this["3"] = Object.create(gaf.Tag.DefineAnimationObjects);
+ this["4"] = Object.create(gaf.Tag.DefineAnimationFrames);
+ this["5"] = Object.create(gaf.Tag.DefineNamedParts);
+ this["6"] = Object.create(gaf.Tag.DefineSequences);
+ this["7"] = Object.create(gaf.Tag.DefineTextFields);
+ this["8"] = Object.create(gaf.Tag.DefineAtlas2);
+ this["9"] = Object.create(gaf.Tag.DefineStage);
+ this["10"] = Object.create(gaf.Tag.DefineAnimationObjects2);
+ this["11"] = Object.create(gaf.Tag.DefineAnimationMasks2);
+ this["12"] = Object.create(gaf.Tag.DefineAnimationFrames2);
+ this["13"] = Object.create(gaf.Tag.DefineTimeline);
+};
+
+gaf.Tag.base = function() {};
+gaf.Tag.base.parse = function(stream, tagId){
+ var size = stream.Uint();
+
+ stream.startNestedBuffer(size);
+ var result = this.doParse(stream);
+ stream.endNestedBuffer();
+
+ result.tagName = this.tagName;
+ result.tagId = tagId;
+ return result;
+};
+gaf.Tag.base.doParse = function(stream){
+ return {};
+ };
+
+gaf.Tag.End = Object.create(gaf.Tag.base);
+gaf.Tag.End.tagName = "TagEnd";
+
+gaf.Tag.DefineAtlas = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAtlas.tagName = "TagDefineAtlas";
+gaf.Tag.DefineAtlas.doParse = function (s) {
+ var exec = s.fields(
+ 'scale', 'Float',
+ 'atlases', s.array('Ubyte', s.fields(
+ 'id', 'Uint',
+ 'sources', s.array('Ubyte', s.fields(
+ 'source', 'String',
+ 'csf', 'Float'
+ ))
+ )),
+ 'elements', s.array('Uint', s.fields(
+ 'pivot', 'Point',
+ 'origin', 'Point',
+ 'scale', 'Float',
+ 'size', 'Point',
+ 'atlasId', 'Uint',
+ 'elementAtlasId', 'Uint'
+ ))
+ );
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineAnimationMasks = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAnimationMasks.tagName = "TagDefineAnimationMasks";
+gaf.Tag.DefineAnimationMasks.doParse = function (s) {
+ var exec = s.array('Uint', s.fields(
+ 'objectId', 'Uint',
+ 'elementAtlasIdRef', 'Uint'
+ ));
+ var result = {'content': exec()};
+ debugger;
+ return result;
+};
+
+gaf.Tag.DefineAnimationObjects = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAnimationObjects.tagName = "TagDefineAnimationObjects";
+gaf.Tag.DefineAnimationObjects.doParse = function (s) {
+ var exec = s.array('Uint', s.fields(
+ 'objectId', 'Uint',
+ 'elementAtlasIdRef', 'Uint'
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineAnimationFrames = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAnimationFrames.tagName = "TagDefineAnimationFrames";
+gaf.Tag.DefineAnimationFrames.doParse = function(s){
+ var exec = s.array('Uint', s.fields(
+ 'frame', 'Uint',
+ 'state', s.array('Uint', s.fields(
+ 'hasColorTransform', 'Ubyte',
+ 'hasMask', 'Ubyte',
+ 'hasEffect', 'Ubyte',
+ 'objectIdRef', 'Uint',
+ 'depth', 'Int',
+ 'alpha', 'Float',
+ 'matrix', 'Matrix',
+ 'colorTransform', s.condition('hasColorTransform', 1, s.fields(
+ 'alphaOffset', 'Float',
+ 'redMultiplier', 'Float',
+ 'redOffset', 'Float',
+ 'greenMultiplier', 'Float',
+ 'greenOffset', 'Float',
+ 'blueMultiplier', 'Float',
+ 'blueOffset', 'Float'
+ )),
+ 'effect', s.condition('hasEffect', 1, s.array('Ubyte', gaf.Tag._readFilter(s))),
+ 'maskObjectIdRef', s.condition('hasMask', 1, s.fields(
+ 'maskObjectIdRef', 'Uint'
+ ))
+ ))
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineNamedParts = Object.create(gaf.Tag.base);
+gaf.Tag.DefineNamedParts.tagName = "TagDefineNamedParts";
+gaf.Tag.DefineNamedParts.doParse = function(s) {
+ var exec = s.array('Uint', s.fields(
+ 'objectId', 'Uint',
+ 'name', 'String'
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineSequences = Object.create(gaf.Tag.base);
+gaf.Tag.DefineSequences.tagName = "TagDefineSequences";
+gaf.Tag.DefineSequences.doParse = function(s) {
+ var exec = s.array('Uint', s.fields(
+ 'id', 'String',
+ 'start', 'Ushort',
+ 'end', 'Ushort'
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineTextFields = Object.create(gaf.Tag.base);
+gaf.Tag.DefineTextFields.tagName = "TagDefineTextFields";
+gaf.Tag.DefineTextFields.doParse = function(s) {
+ var exec = s.array('Uint', s.fields(
+ 'id', 'Uint',
+ 'pivot', 'Point',
+ 'end', 'Ushort',
+ 'width', 'Float',
+ 'height', 'Float',
+ 'text', 'String',
+ 'embedFonts', 'Boolean',
+ 'multiline', 'Boolean',
+ 'wordWrap', 'Boolean',
+ 'hasRestrict', 'Boolean',
+ 'restrict', s.condition('hasRestrict', 1, function (){return s['String'];}),
+ 'editable', 'Boolean',
+ 'selectable', 'Boolean',
+ 'displayAsPassword', 'Boolean',
+ 'maxChars', 'Uint',
+ 'align', 'Uint',
+ 'blockIndent', 'Uint',
+ 'bold', 'Boolean',
+ 'bullet', 'Boolean',
+ 'color', 'color',
+ 'font', 'String',
+ 'indent', 'Uint',
+ 'italic', 'Boolean',
+ 'kerning', 'Boolean',
+ 'leading', 'Uint',
+ 'leftMargin', 'Uint',
+ 'letterSpacing', 'Float',
+ 'rightMargin', 'Uint',
+ 'size', 'Uint',
+ 'tabStops', s.array('Uint', s.fields(
+ 'value', 'Uint'
+ )),
+ 'target', 'string',
+ 'underline', 'Boolean',
+ 'url', 'String'
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineAtlas2 = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAtlas2.tagName = "TagDefineAtlas2";
+gaf.Tag.DefineAtlas2.doParse = function(s) {
+ var exec = s.fields(
+ 'scale', 'Float',
+ 'atlases', s.array('Ubyte', s.fields(
+ 'id', 'Uint',
+ 'sources', s.array('Ubyte', s.fields(
+ 'source', 'String',
+ 'csf', 'Float'
+ ))
+ )),
+ 'elements', s.array('Uint', s.fields(
+ 'pivot', 'Point',
+ 'origin', 'Point',
+ 'scale', 'Float',
+ 'size', 'Point',
+ 'atlasId', 'Uint',
+ 'elementAtlasId', 'Uint',
+ 'hasScale9Grid', 'Boolean',
+ 'scale9GridRect', s.condition('hasScale9Grid', 1, function(){return s.Rect();})
+ ))
+ );
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineStage = Object.create(gaf.Tag.base);
+gaf.Tag.DefineStage.tagName = "TagDefineStage";
+gaf.Tag.DefineStage.doParse = function(s) {
+ var exec = s.fields(
+ 'fps', 'Ubyte',
+ 'color', 'color',
+ 'width', 'Ushort',
+ 'height', 'Ushort'
+ );
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineAnimationObjects2 = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAnimationObjects2.tagName = "TagDefineAnimationObjects2";
+gaf.Tag.DefineAnimationObjects2.doParse = function(s) {
+ var exec = s.array('Uint', s.fields(
+ 'objectId', 'Uint',
+ 'elementAtlasIdRef', 'Uint',
+ 'type', 'Ushort'
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineAnimationMasks2 = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAnimationMasks2.tagName = "TagDefineAnimationMasks2";
+gaf.Tag.DefineAnimationMasks2.doParse = function(s) {
+ var exec = s.array('Uint', s.fields(
+ 'objectId', 'Uint',
+ 'elementAtlasIdRef', 'Uint',
+ 'type', 'Ushort'
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineAnimationFrames2 = Object.create(gaf.Tag.base);
+gaf.Tag.DefineAnimationFrames2.tagName = "TagDefineAnimationFrames2";
+gaf.Tag.DefineAnimationFrames2.doParse = function(s) {
+ var exec = s.array('Uint', s.fields(
+ 'frame', 'Uint',
+ 'hasChangesInDisplayList', 'Boolean',
+ 'hasActions', 'Boolean',
+ 'state', s.condition('hasChangesInDisplayList', 1, s.array('Uint', s.fields(
+ 'hasColorTransform', 'Boolean',
+ 'hasMask', 'Boolean',
+ 'hasEffect', 'Boolean',
+ 'objectIdRef', 'Uint',
+ 'depth', 'Int',
+ 'alpha', 'Float',
+ 'matrix', 'Matrix',
+ 'colorTransform', s.condition('hasColorTransform', 1, s.fields(
+ 'alphaOffset', 'Float',
+ 'redMultiplier', 'Float',
+ 'redOffset', 'Float',
+ 'greenMultiplier', 'Float',
+ 'greenOffset', 'Float',
+ 'blueMultiplier', 'Float',
+ 'blueOffset', 'Float'
+ )),
+ 'effect', s.condition('hasEffect', 1, s.array('Ubyte', gaf.Tag._readFilter(s))),
+ 'maskObjectIdRef', s.condition('hasMask', 1, function(){return s.Uint()})
+ ))),
+ 'actions', s.condition('hasActions', 1, s.array('Uint', s.fields(
+ 'type', 'Uint',
+ 'scope', 'String',
+ 'params', gaf.Tag._readActionArguments(s)
+ )))
+ ));
+ return {'content': exec()};
+};
+
+gaf.Tag.DefineTimeline = Object.create(gaf.Tag.base);
+gaf.Tag.DefineTimeline.tagName = "TagDefineTimeline";
+gaf.Tag.DefineTimeline.doParse = function(s) {
+ var exec = s.fields(
+ 'id', 'Uint',
+ 'animationFrameCount', 'Uint',
+ 'boundingBox', 'Rect',
+ 'pivotPoint', 'Point',
+ 'hasLinkage', 'Boolean',
+ 'linkageName', s.condition('hasLinkage', 1, function () {
+ return s.String();
+ })
+ );
+ var result = {'content': exec()};
+ result.content.tags = gaf.ReadTags(s);
+ return result;
+};
+
+gaf.Tag._readActionArguments = function(s){
+ return function(){
+ var size = s.Uint();
+ var ret = [];
+ s.startNestedBuffer(size);
+ while(s.maxOffset() < s.tell()){
+ ret.push(s.String());
+ }
+ s.endNestedBuffer();
+ return ret;
+ };
+};
+
+gaf.Tag._readFilter = function(s){
+ return s.fields(
+ 'type', 'Uint',
+ 'dropShadow', s.condition('type', gaf.EFFECT_DROP_SHADOW, s.fields( // DropShadow
+ 'color', 'color',
+ 'blurX', 'Float',
+ 'blurY', 'Float',
+ 'angle', 'Float',
+ 'distance', 'Float',
+ 'strength', 'Float',
+ 'inner', 'Boolean',
+ 'knockout', 'Boolean'
+ )),
+ 'blur', s.condition('type', gaf.EFFECT_BLUR, s.fields( // Blur
+ 'blurX', 'Float',
+ 'blurY', 'Float'
+ )),
+ 'glow', s.condition('type', gaf.EFFECT_GLOW, s.fields( // Glow
+ 'color', 'color',
+ 'blurX', 'Float',
+ 'blurY', 'Float',
+ 'strength', 'Float',
+ 'inner', 'Boolean',
+ 'knockout', 'Boolean'
+ )),
+ 'colorMatrix', s.condition('type', gaf.EFFECT_COLOR_MATRIX, s.fields( // ColorMatrix
+ 'rr', 'Float', 'gr', 'Float', 'br', 'Float', 'ar', 'Float', 'r', 'Float',
+ 'rg', 'Float', 'gg', 'Float', 'bg', 'Float', 'ag', 'Float', 'g', 'Float',
+ 'rb', 'Float', 'gb', 'Float', 'bb', 'Float', 'ab', 'Float', 'b', 'Float',
+ 'ra', 'Float', 'ga', 'Float', 'ba', 'Float', 'aa', 'Float', 'a', 'Float'
+ ))
+ )
+};
+
+gaf.Tags = new gaf.Tag();
diff --git a/external/gaf/Library/GAFTextField.js b/external/gaf/Library/GAFTextField.js
new file mode 100644
index 0000000000..04f9744920
--- /dev/null
+++ b/external/gaf/Library/GAFTextField.js
@@ -0,0 +1,6 @@
+
+gaf.TextField = gaf.Object.extend
+({
+ _className: "GAFTextField"
+
+});
\ No newline at end of file
diff --git a/external/gaf/Library/GAFTimeLine.js b/external/gaf/Library/GAFTimeLine.js
new file mode 100644
index 0000000000..ef9387aa46
--- /dev/null
+++ b/external/gaf/Library/GAFTimeLine.js
@@ -0,0 +1,547 @@
+
+gaf.TimeLine = gaf.Object.extend
+({
+ _className: "GAFTimeLine",
+ _objects: null,
+ _container: null,
+ _animationStartedNextLoopDelegate: null,
+ _animationFinishedPlayDelegate: null,
+ _framePlayedDelegate: null,
+ _sequenceDelegate: null,
+ _fps: 60,
+ _frameTime: 1/60,
+ _currentSequenceStart: gaf.FIRST_FRAME_INDEX,
+ _currentSequenceEnd: gaf.FIRST_FRAME_INDEX,
+ _totalFrameCount: 0,
+ _isRunning: false,
+ _isLooped: false,
+ _isReversed: false,
+ _timeDelta: 0,
+ _animationsSelectorScheduled: false,
+ _currentFrame: gaf.FIRST_FRAME_INDEX,
+
+
+ setAnimationStartedNextLoopDelegate: function (delegate)
+ {
+ this._animationStartedNextLoopDelegate = delegate;
+ },
+ setAnimationFinishedPlayDelegate: function (delegate)
+ {
+ this._animationFinishedPlayDelegate = delegate;
+ },
+ setLooped: function (looped, recursively)
+ {
+ this._isLooped = looped;
+ if (recursively)
+ {
+ this._objects.forEach(function (item)
+ {
+ item.setLooped(looped, recursively);
+ });
+ }
+ },
+ getBoundingBoxForCurrentFrame: function ()
+ {
+ var result = null;//cc.rect();
+ var isFirstObj = true;
+ this._objects.forEach(function (item) {
+ if(item.isVisibleInCurrentFrame() && item.isVisible())
+ {
+ var bb = item.getBoundingBoxForCurrentFrame();
+ if(!bb)
+ {
+ bb = item.getBoundingBox();
+ }
+ if (isFirstObj)
+ {
+ isFirstObj = false;
+ result = bb;
+ }
+ else
+ {
+ result = cc.rectUnion(result, bb);
+ }
+ }
+ });
+ return cc._rectApplyAffineTransformIn(result, this._container.getNodeToParentTransform());
+ },
+ setFps: function (fps)
+ {
+ cc.assert(fps !== 0, 'Error! Fps is set to zero.');
+ this._fps = fps;
+ this._frameTime = 1/fps;
+ },
+ getObjectByName: function (name)
+ {
+ var elements = name.split('.');
+ var result = null;
+ var retId = -1;
+ var timeLine = this;
+ var BreakException = {};
+ try
+ {
+ elements.forEach(function(element)
+ {
+ var parts = timeLine._gafproto.getNamedParts();
+ if(parts.hasOwnProperty(element))
+ {
+ retId = parts[element];
+ }
+ else
+ {
+ // Sequence is incorrect
+ BreakException.lastElement = element;
+ throw BreakException;
+ }
+ result = timeLine._objects[retId];
+ timeLine = result;
+ });
+ }
+ catch (e)
+ {
+ if (e!==BreakException)
+ {
+ throw e;
+ }
+ cc.log("Sequence incorrect: `" + name + "` At: `" + BreakException.lastElement + "`");
+ return null;
+ }
+ return result;
+ },
+ clearSequence: function ()
+ {
+ this._currentSequenceStart = gaf.FIRST_FRAME_INDEX;
+ this._currentSequenceEnd = this._gafproto.getTotalFrames();
+ },
+ getIsAnimationRunning: function ()
+ {
+ return this._isRunning;
+ },
+ gotoAndStop: function (value)
+ {
+ var frame = 0;
+ if (typeof value === 'string')
+ {
+ frame = this.getStartFrame(value);
+ }
+ else
+ {
+ frame = value;
+ }
+ if (this.setFrame(frame))
+ {
+ this.setAnimationRunning(false, false);
+ return true;
+ }
+ return false;
+ },
+ gotoAndPlay: function (value)
+ {
+ var frame = 0;
+ if (typeof value === 'string')
+ {
+ frame = this.getStartFrame(value);
+ }
+ else
+ {
+ frame = value;
+ }
+ if (this.setFrame(frame))
+ {
+ this.setAnimationRunning(true, false);
+ return true;
+ }
+ return false;
+ },
+ getStartFrame: function (frameLabel)
+ {
+ var seq = this._gafproto.getSequences()[frameLabel];
+ if (seq)
+ {
+ return seq.start;
+ }
+ return gaf.IDNONE;
+ },
+ getEndFrame: function (frameLabel)
+ {
+ var seq = this._gafproto.getSequences()[frameLabel];
+ if (seq)
+ {
+ return seq.end;
+ }
+ return gaf.IDNONE;
+ },
+ setFramePlayedDelegate: function (delegate)
+ {
+ this._framePlayedDelegate = delegate;
+ },
+ getCurrentFrameIndex: function ()
+ {
+ return this._showingFrame;
+ },
+ getTotalFrameCount: function ()
+ {
+ return this._gafproto.getTotalFrames();
+ },
+ start: function ()
+ {
+ this._enableTick(true);
+ if (!this._isRunning)
+ {
+ this._currentFrame = gaf.FIRST_FRAME_INDEX;
+ this.setAnimationRunning(true, true);
+ }
+ },
+ stop: function ()
+ {
+ this._enableTick(false);
+ if (this._isRunning)
+ {
+ this._currentFrame = gaf.FIRST_FRAME_INDEX;
+ this.setAnimationRunning(false, true);
+ }
+ },
+ isDone: function ()
+ {
+ if (this._isLooped)
+ {
+ return false;
+ }
+ else
+ {
+ if (!this._isReversed)
+ {
+ return this._currentFrame > this._totalFrameCount;
+ }
+ else
+ {
+ return this._currentFrame < gaf.FIRST_FRAME_INDEX - 1;
+ }
+ }
+ },
+ getSequences: function()
+ {
+ return this._gafproto.getSequences();
+ },
+ playSequence: function (name, looped)
+ {
+ var s = this.getStartFrame(name);
+ var e = this.getEndFrame(name);
+ if (gaf.IDNONE === s || gaf.IDNONE === e)
+ {
+ return false;
+ }
+ this._currentSequenceStart = s;
+ this._currentSequenceEnd = e;
+ if (this._currentFrame < this._currentSequenceStart || this._currentFrame > this._currentSequenceEnd)
+ {
+ this._currentFrame = this._currentSequenceStart;
+ }
+ else
+ {
+ this._currentFrame = this._currentSequenceStart;
+ }
+ this.setLooped(looped, false);
+ this.resumeAnimation();
+ return true;
+ },
+ isReversed: function ()
+ {
+ return this._isReversed;
+ },
+ setSequenceDelegate: function (delegate)
+ {
+ this._sequenceDelegate = delegate;
+ },
+ setFrame: function (index)
+ {
+ if (index >= gaf.FIRST_FRAME_INDEX && index < this._totalFrameCount)
+ {
+ this._showingFrame = index;
+ this._currentFrame = index;
+ this._processAnimation();
+ return true;
+ }
+ return false;
+ },
+
+ pauseAnimation: function ()
+ {
+ if (this._isRunning)
+ {
+ this.setAnimationRunning(false, false);
+ }
+ },
+ isLooped: function ()
+ {
+ return this._isLooped;
+ },
+ resumeAnimation: function ()
+ {
+ if (!this._isRunning)
+ {
+ this.setAnimationRunning(true, false);
+ }
+ },
+ setReversed: function (reversed)
+ {
+ this._isReversed = reversed;
+ },
+ hasSequences: function ()
+ {
+ return this._gafproto.getSequences().length > 0;
+ },
+ getFps: function ()
+ {
+ return this._fps;
+ },
+
+
+ // Private
+
+ ctor: function(gafTimeLineProto, scale)
+ {
+ this._super(scale);
+ this._objects = [];
+ cc.assert(gafTimeLineProto, "Error! Missing mandatory parameter.");
+ this._gafproto = gafTimeLineProto;
+ },
+
+ setExternalTransform: function(affineTransform)
+ {
+ if(!cc.affineTransformEqualToTransform(this._container._additionalTransform, affineTransform))
+ {
+ this._container.setAdditionalTransform(affineTransform);
+ }
+ },
+
+ _init: function()
+ {
+ this.setContentSize(this._gafproto.getBoundingBox());
+ this._currentSequenceEnd = this._gafproto.getTotalFrames();
+ this._totalFrameCount = this._currentSequenceEnd;
+ this.setFps(this._gafproto.getFps());
+ this._container = new cc.Node();
+ this.addChild(this._container);
+
+ var self = this;
+ var asset = this._gafproto.getAsset();
+
+ // Construct objects for current time line
+ this._gafproto.getObjects().forEach(function(object)
+ {
+ var objectProto = asset._getProtos()[object];
+ cc.assert(objectProto, "Error. GAF proto for type: " + object.type + " and reference id: " + object + " not found.");
+ self._objects[object] = objectProto._gafConstruct();
+ });
+ },
+
+ _enableTick: function(val)
+ {
+ if (!this._animationsSelectorScheduled && val)
+ {
+ this.schedule(this._processAnimations);
+ this._animationsSelectorScheduled = true;
+ }
+ else if (this._animationsSelectorScheduled && !val)
+ {
+ this.unschedule(this._processAnimations);
+ this._animationsSelectorScheduled = false;
+ }
+ },
+
+ _processAnimations: function (dt)
+ {
+ this._timeDelta += dt;
+ while (this._timeDelta >= this._frameTime)
+ {
+ this._timeDelta -= this._frameTime;
+ this._step();
+ }
+ },
+
+ _step: function ()
+ {
+ this._showingFrame = this._currentFrame;
+
+ if(!this.getIsAnimationRunning())
+ {
+ this._processAnimation();
+ return;
+ }
+
+ if(this._sequenceDelegate)
+ {
+ var seq;
+ if(!this._isReversed)
+ {
+ seq = this._getSequenceByLastFrame(this._currentFrame);
+ }
+ else
+ {
+ seq = this._getSequenceByFirstFrame(this._currentFrame + 1);
+ }
+
+ if (seq)
+ {
+ this._sequenceDelegate(this, seq);
+ }
+ }
+ if (this._isCurrentFrameLastInSequence())
+ {
+ if(this._isLooped)
+ {
+ if(this._animationStartedNextLoopDelegate)
+ this._animationStartedNextLoopDelegate(this);
+ }
+ else
+ {
+ this.setAnimationRunning(false, false);
+ if(this._animationFinishedPlayDelegate)
+ this._animationFinishedPlayDelegate(this);
+ }
+ }
+ this._processAnimation();
+ this._currentFrame = this._nextFrame();
+ },
+
+ _isCurrentFrameLastInSequence: function()
+ {
+ if (this._isReversed)
+ return this._currentFrame == this._currentSequenceStart;
+ return this._currentFrame == this._currentSequenceEnd - 1;
+ },
+
+ _nextFrame: function()
+ {
+ if (this._isCurrentFrameLastInSequence())
+ {
+ if (!this._isLooped)
+ return this._currentFrame;
+
+ if (this._isReversed)
+ return this._currentSequenceEnd - 1;
+ else
+ return this._currentSequenceStart;
+ }
+
+ return this._currentFrame + (this._isReversed ? -1 : 1);
+ },
+
+ _processAnimation: function ()
+ {
+ //var id = this._gafproto.getId();
+ this._realizeFrame(this._container, this._currentFrame);
+ if (this._framePlayedDelegate)
+ {
+ this._framePlayedDelegate(this, this._currentFrame);
+ }
+ },
+ _realizeFrame: function(out, frameIndex)
+ {
+ var self = this;
+ var objects = self._objects;
+ var frames = self._gafproto.getFrames();
+ if(frameIndex > frames.length)
+ {
+ return;
+ }
+ var currentFrame = frames[frameIndex];
+ if(!currentFrame)
+ {
+ return;
+ }
+ var states = currentFrame.states;
+ for(var stateIdx = 0, total = states.length; stateIdx < total; ++stateIdx)
+ {
+ var state = states[stateIdx];
+ var object = objects[state.objectIdRef];
+ if(!object)
+ {
+ return;
+ }
+ if(state.alpha < 0)
+ {
+ object._resetState();
+ }
+ object._updateVisibility(state, self);
+ if(!object.isVisible())
+ {
+ continue;
+ }
+ object._applyState(state, self);
+ var parent = out;
+ if(state.hasMask)
+ {
+ parent = objects[state.maskObjectIdRef]._getNode();
+ cc.assert(parent, "Error! Mask not found.");
+ }
+ object._lastVisibleInFrame = 1 + frameIndex;
+ gaf.TimeLine.rearrangeSubobject(parent, object, state.depth);
+ if(object._step)
+ {
+ object._step();
+ }
+ }
+ },
+ setAnimationRunning: function (value, recursively)
+ {
+ this._isRunning = value;
+ if(recursively)
+ {
+ this._objects.forEach(function (obj)
+ {
+ if (obj && obj.setAnimationRunning)
+ {
+ obj.setAnimationRunning(value, recursively);
+ }
+ });
+ }
+ },
+
+ _getSequenceByLastFrame: function(){
+ var sequences = this._gafproto.getSequences();
+ for(var item in sequences){
+ if(sequences.hasOwnProperty(item)){
+ if(sequences[item].end === frame + 1)
+ {
+ return item;
+ }
+ }
+ }
+ return "";
+ },
+
+ _resetState : function()
+ {
+ this._super();
+ this._currentFrame = this._currentSequenceStart;
+ },
+
+ _getSequenceByFirstFrame: function(){
+ var sequences = this._gafproto.getSequences();
+ for(var item in sequences){
+ if(sequences.hasOwnProperty(item)){
+ if(sequences[item].start === frame)
+ {
+ return item;
+ }
+ }
+ }
+ return "";
+ }
+});
+
+gaf.TimeLine.rearrangeSubobject = function(out, object, depth)
+{
+ var parent = object.getParent();
+ if (parent !== out)
+ {
+ object.removeFromParent(false);
+ out.addChild(object, depth);
+ }
+ else
+ {
+ object.setLocalZOrder(depth);
+ }
+};
diff --git a/external/gaf/Library/GAFTimeLineProto.js b/external/gaf/Library/GAFTimeLineProto.js
new file mode 100644
index 0000000000..9d78b219d9
--- /dev/null
+++ b/external/gaf/Library/GAFTimeLineProto.js
@@ -0,0 +1,32 @@
+
+gaf._TimeLineProto = function(asset, animationFrameCount, boundingBox, pivotPoint, id, linkageName)
+{
+ id = typeof id != 'undefined' ? id : 0;
+ linkageName = linkageName || "";
+
+ this._objects = [];
+
+ this.getTotalFrames = function(){return animationFrameCount};
+ this.getBoundingBox = function() {return boundingBox};
+ this.getId = function() {return id};
+ this.getLinkageName = function() {return linkageName};
+ this.getPivot = function(){return pivotPoint};
+ this.getRect = function(){return boundingBox};
+ this.getNamedParts = function() {return {}}; // Map name -> id
+ this.getSequences = function() {return {}}; // Map name -> {start, end}
+ this.getFrames = function(){return []}; // Array {states, actions}
+ this.getFps = function(){return 60};
+ this.getObjects = function(){return this._objects};
+ this.getAsset = function(){return asset};
+
+ /*
+ * Will construct GAFTimeLine
+ */
+ this._gafConstruct = function()
+ {
+ var usedScale = this.getAsset()._usedAtlasScale;
+ var ret = new gaf.TimeLine(this, usedScale);
+ ret._init();
+ return ret;
+ };
+};
diff --git a/external/gaf/gaf_viewer.css b/external/gaf/gaf_viewer.css
new file mode 100644
index 0000000000..60933161d2
--- /dev/null
+++ b/external/gaf/gaf_viewer.css
@@ -0,0 +1,42 @@
+#drop_zone {
+ border: 2px dashed #bbb;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ padding: 25px;
+ text-align: center;
+ font: 20pt bold 'Vollkorn';
+ color: #bbb;
+
+}
+.renderjson a {
+ text-decoration: none;
+}
+.renderjson .disclosure {
+ color: crimson;
+ font-size: 150%;
+}
+.renderjson .syntax {
+ color: grey;
+}
+.renderjson .string {
+ color: darkred;
+}
+.renderjson .number {
+ color: darkcyan;
+}
+.renderjson .boolean {
+ color: blueviolet;
+}
+.renderjson .key {
+ color: darkblue;
+}
+.renderjson .keyword {
+ color: blue;
+}
+.renderjson .object.syntax {
+ color: lightseagreen;
+}
+.renderjson .array.syntax {
+ color: orange;
+}
diff --git a/external/gaf/gaf_viewer.html b/external/gaf/gaf_viewer.html
new file mode 100644
index 0000000000..2c66aeb05f
--- /dev/null
+++ b/external/gaf/gaf_viewer.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Drop GAF here
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/gaf/gaf_viewer.js b/external/gaf/gaf_viewer.js
new file mode 100644
index 0000000000..98d247cd60
--- /dev/null
+++ b/external/gaf/gaf_viewer.js
@@ -0,0 +1,219 @@
+ /*
+ * Created by Teivaz on 29.11.2014.
+ * Thanks to David Caldwell for `renderjson`
+ */
+function handleFileSelect(evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+
+ var files = evt.dataTransfer.files;
+
+ var output = [];
+ for (var i = 0, f; f = files[i]; i++) {
+ var name = escape(f.name);
+ var ext = name.split('.').pop();
+ if (ext == 'gaf') {
+ var reader = new FileReader();
+ reader.onload = (function(theFile) {
+ return function(req) {
+ var arrayBuffer = new gaf.DataReader(req.target.result);
+ var loader = new gaf.Loader();
+ var data = loader.LoadStream(arrayBuffer);
+ document.getElementById('list').appendChild(renderjson(data));
+ };
+ })(f);
+ reader.readAsArrayBuffer(f);
+ }
+ }
+}
+
+function handleDragOver(evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+ evt.dataTransfer.dropEffect = 'copy';
+}
+
+var dropZone = document.getElementById('drop_zone');
+dropZone.addEventListener('dragover', handleDragOver, false);
+dropZone.addEventListener('drop', handleFileSelect, false);
+
+var module;
+(module || {}).exports = renderjson = (function() {
+ var themetext = function( /* [class, text]+ */ ) {
+ var spans = [];
+ while (arguments.length)
+ spans.push(append(span(Array.prototype.shift.call(arguments)),
+ text(Array.prototype.shift.call(arguments))));
+ return spans;
+ };
+ var append = function( /* el, ... */ ) {
+ var el = Array.prototype.shift.call(arguments);
+ for (var a = 0; a < arguments.length; a++)
+ if (arguments[a].constructor == Array)
+ append.apply(this, [el].concat(arguments[a]));
+ else
+ el.appendChild(arguments[a]);
+ return el;
+ };
+ var prepend = function(el, child) {
+ el.insertBefore(child, el.firstChild);
+ return el;
+ };
+ var isempty = function(obj) {
+ for (var k in obj)
+ if (obj.hasOwnProperty(k)) return false;
+ return true;
+ };
+ var text = function(txt) {
+ return document.createTextNode(txt)
+ };
+ var div = function() {
+ return document.createElement("div")
+ };
+ var span = function(classname) {
+ var s = document.createElement("span");
+ if (classname) s.className = classname;
+ return s;
+ };
+ var A = function A(txt, classname, callback) {
+ var a = document.createElement("a");
+ if (classname) a.className = classname;
+ a.appendChild(text(txt));
+ a.href = '#';
+ a.onclick = function() {
+ callback();
+ return false;
+ };
+ return a;
+ };
+
+ function _renderjson(json, indent, dont_indent, show_level, sort_objects) {
+ var my_indent = dont_indent ? "" : indent;
+
+ if (json === null) return themetext(null, my_indent, "keyword", "null");
+ if (json === void 0) return themetext(null, my_indent, "keyword", "undefined");
+ if (typeof(json) != "object") // Strings, numbers and bools
+ return themetext(null, my_indent, typeof(json), JSON.stringify(json));
+
+ var disclosure = function(open, close, type, builder) {
+ var content;
+ var empty = span(type);
+ var show = function() {
+ if (!content) append(empty.parentNode,
+ content = prepend(builder(),
+ A(renderjson.hide, "disclosure",
+ function() {
+ content.style.display = "none";
+ empty.style.display = "inline";
+ })));
+ content.style.display = "inline";
+ empty.style.display = "none";
+ };
+
+ function isColor(a){
+ return a.hasOwnProperty('a') && a.hasOwnProperty('r') && a.hasOwnProperty('g') && a.hasOwnProperty('b');
+ }
+
+ var color_rect = span();
+ if (json.hasOwnProperty("tagName"))
+ var placeholder = json.tagName;
+ else if (json.hasOwnProperty("header"))
+ placeholder = " GAF v" + json.header.versionMajor + "." + json.header.versionMinor + " ";
+ else if (json.constructor == Array)
+ placeholder = " " + json.length + " ";
+ else if (json.hasOwnProperty("id"))
+ placeholder = " id:" + json.id + " ... ";
+ else if (json.hasOwnProperty("objectId"))
+ placeholder = " id:" + json.objectId + " ... ";
+ else if (json.hasOwnProperty("frame"))
+ placeholder = " frame:" + json.frame + " ... ";
+ else if(isColor(json)){
+ color_rect.style.backgroundColor = "rgba("+json.r+","+json.g+","+json.b+","+json.a / 255.0+")";// parseInt(json.r).toString(16) + parseInt(json.g).toString(16) + parseInt(json.b).toString(16);
+ color_rect.style.height = '10px';
+ color_rect.style.width = '10px';
+ color_rect.style.display = 'inline-block';
+ color_rect.style.margin = '0 4px';
+ color_rect.style.border = '1px solid #7f7f7f';
+ }
+
+ placeholder = placeholder || ' ... ';
+ append(empty,
+ A(renderjson.show, "disclosure", show),
+ color_rect,
+ themetext(type + " syntax", open),
+ A(placeholder, null, show),
+ themetext(type + " syntax", close));
+
+ var el = append(span(), text(my_indent.slice(0, -1)), empty);
+ if (show_level > 0)
+ show();
+ return el;
+ };
+
+ if (json.constructor == Array) {
+ if (json.length == 0) return themetext(null, my_indent, "array syntax", "[]");
+
+ return disclosure("[", "]", "array", function() {
+ var as = append(span("array"), themetext("array syntax", "[", null, "\n"));
+ for (var i = 0; i < json.length; i++)
+ append(as,
+ _renderjson(json[i], indent + " ", false, show_level - 1, sort_objects),
+ i != json.length - 1 ? themetext("syntax", ",") : [],
+ text("\n"));
+ append(as, themetext(null, indent, "array syntax", "]"));
+ return as;
+ });
+ }
+
+ // object
+ if (isempty(json))
+ return themetext(null, my_indent, "object syntax", "{}");
+
+
+ return disclosure("{", "}", "object", function() {
+ var os = append(span("object"), themetext("object syntax", "{", null, "\n"));
+ for (var k in json) var last = k;
+ var keys = Object.keys(json);
+ if (sort_objects)
+ keys = keys.sort();
+ for (var i in keys) {
+ var k = keys[i];
+ append(os, themetext(null, indent + " ", "key", '"' + k + '"', "object syntax", ': '),
+ _renderjson(json[k], indent + " ", true, show_level - 1, sort_objects),
+ k != last ? themetext("syntax", ",") : [],
+ text("\n"));
+ }
+ append(os, themetext(null, indent, "object syntax", "}"));
+ return os;
+ });
+ }
+
+ var renderjson = function renderjson(json) {
+ var pre = append(document.createElement("pre"), _renderjson(json, "", false, renderjson.show_to_level, renderjson.sort_objects));
+ pre.className = "renderjson";
+ return pre;
+ };
+ renderjson.set_icons = function(show, hide) {
+ renderjson.show = show;
+ renderjson.hide = hide;
+ return renderjson;
+ };
+ renderjson.set_show_to_level = function(level) {
+ renderjson.show_to_level = typeof level == "string" &&
+ level.toLowerCase() === "all" ? Number.MAX_VALUE : level;
+ return renderjson;
+ };
+ renderjson.set_sort_objects = function(sort_bool) {
+ renderjson.sort_objects = sort_bool;
+ return renderjson;
+ };
+ // Backwards compatibility. Use set_show_to_level() for new code.
+ renderjson.set_show_by_default = function(show) {
+ renderjson.show_to_level = show ? Number.MAX_VALUE : 0;
+ return renderjson;
+ };
+ renderjson.set_icons('⊕', '⊖');
+ renderjson.set_show_by_default(false);
+ renderjson.set_sort_objects(false);
+ return renderjson;
+})();
\ No newline at end of file
diff --git a/external/pluginx/Plugin.js b/external/pluginx/Plugin.js
new file mode 100644
index 0000000000..e2bc1450c7
--- /dev/null
+++ b/external/pluginx/Plugin.js
@@ -0,0 +1,253 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * plugin manager
+ * @class
+ *
+ */
+(function(){
+
+ if(cc === undefined){
+ return;
+ }
+
+ //Native plugin usage
+ var PluginManager = function(){};
+
+ PluginManager.prototype = {
+ constructor: PluginManager,
+
+ /**
+ * @returns {PluginManager}
+ * @expose
+ */
+ getInstance: function(){
+ return this;
+ },
+
+ /**
+ * @param {String} pluginName
+ * @expose
+ */
+ loadPlugin: function(pluginName){
+
+ },
+
+ /**
+ *
+ * @param pluginName
+ * @expose
+ */
+ unloadPlugin: function(pluginName){
+
+ }
+ };
+
+ var PluginAssembly = function(){};
+
+ PluginAssembly.prototype = {
+ constructor: PluginAssembly,
+
+ /**
+ * @param {Boolean} debug
+ * @expose
+ */
+ setDebugMode: function(debug){},
+
+ /**
+ * @param {String} appKey
+ * @expose
+ */
+ startSession: function(appKey){},
+
+ /**
+ * @param {Boolean} Capture
+ * @expose
+ */
+ setCaptureUncaughtException: function(Capture){},
+
+ /**
+ * @param {String} funName
+ * @param {All} Params
+ * @expose
+ */
+ callFuncWithParam: function(funName){
+ if(typeof this[funName] === 'function'){
+ return this[funName].apply(this, Array.prototype.splice.call(arguments, 1));
+ }else{
+ cc.log("function is not define");
+ }
+ },
+
+ /**
+ * @param {String} funName
+ * @param {All} Params
+ * @expose
+ */
+ callStringFuncWithParam: function(funName){
+ this.callFuncWithParam.apply(arguments);
+ },
+
+ /**
+ * @returns {String}
+ * @expose
+ */
+ getPluginName: function(){
+ return this._name;
+ },
+
+ /**
+ * @returns {String}
+ * @expose
+ */
+ getPluginVersion: function(){
+ return this._version;
+ }
+ };
+
+ /** @expose */
+ PluginAssembly.extend = function(name, porp){
+ var p, prototype = {};
+ for(p in PluginAssembly.prototype){
+ prototype[p] = PluginAssembly.prototype[p];
+ }
+ for(p in porp){
+ prototype[p] = porp[p];
+ }
+ var tmp = eval("(function " + name + "Plugin(){})");
+ prototype.constructor = tmp;
+ tmp.prototype = prototype;
+ return tmp;
+ };
+
+ //Param
+ var Param = function(type, value){
+ var paramType = plugin.PluginParam.ParamType,tmpValue;
+ switch(type){
+ case paramType.TypeInt:
+ tmpValue = parseInt(value);
+ break;
+ case paramType.TypeFloat:
+ tmpValue = parseFloat(value);
+ break;
+ case paramType.TypeBool:
+ tmpValue = Boolean(value);
+ break;
+ case paramType.TypeString:
+ tmpValue = String(value);
+ break;
+ case paramType.TypeStringMap:
+ tmpValue = value//JSON.stringify(value);
+ break;
+ default:
+ tmpValue = value;
+ }
+ return tmpValue
+ };
+
+ /** @expose */
+ Param.ParamType = {
+ /** @expose */
+ TypeInt:1,
+ /** @expose */
+ TypeFloat:2,
+ /** @expose */
+ TypeBool:3,
+ /** @expose */
+ TypeString:4,
+ /** @expose */
+ TypeStringMap:5
+ };
+
+ /** @expose */
+ Param.AdsResultCode = {
+ /** @expose */
+ AdsReceived:0,
+ /** @expose */
+ FullScreenViewShown:1,
+ /** @expose */
+ FullScreenViewDismissed:2,
+ /** @expose */
+ PointsSpendSucceed:3,
+ /** @expose */
+ PointsSpendFailed:4,
+ /** @expose */
+ NetworkError:5,
+ /** @expose */
+ UnknownError:6
+ };
+
+ /** @expose */
+ Param.PayResultCode = {
+ /** @expose */
+ PaySuccess:0,
+ /** @expose */
+ PayFail:1,
+ /** @expose */
+ PayCancel:2,
+ /** @expose */
+ PayTimeOut:3
+ };
+
+ /** @expose */
+ Param.ShareResultCode = {
+ /** @expose */
+ ShareSuccess:0,
+ /** @expose */
+ ShareFail:1,
+ /** @expose */
+ ShareCancel:2,
+ /** @expose */
+ ShareTimeOut:3
+ };
+
+ /** @expose */
+ var PluginList = {};
+
+ /** @expose */
+ var Plugin = {
+
+ /** @expose */
+ extend: function(name, extend){
+ var config = (cc.game.config && cc.game.config.plugin) || {};
+ PluginList[name] = new (PluginAssembly.extend(name, extend));
+ typeof PluginList[name].ctor === "function" && PluginList[name].ctor(config[name]);
+ },
+
+ /** @expose */
+ PluginList: PluginList,
+
+ /** @expose */
+ PluginParam: Param,
+
+ /** @expose */
+ PluginManager: new PluginManager()
+
+ };
+
+ /** @expose */
+ window.plugin = Plugin;
+
+})();
\ No newline at end of file
diff --git a/external/pluginx/platform/facebook.js b/external/pluginx/platform/facebook.js
new file mode 100644
index 0000000000..190115951a
--- /dev/null
+++ b/external/pluginx/platform/facebook.js
@@ -0,0 +1,557 @@
+/****************************************************************************
+ Copyright (c) 2013-2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * Facebook SDK for Web Platform
+ * FacebookAgent...
+ *
+ * @property {String} name - plugin name
+ * @property {String} version - API version
+ */
+plugin.extend('facebook', {
+ name: "",
+ version: "",
+ _userInfo: null,
+ _isLoggedIn: false,
+
+ /**
+ * HTTP methods constants
+ * @constant
+ * @type {Object}
+ */
+ HttpMethod: {
+ 'GET': 'get',
+ 'POST': 'post',
+ 'DELETE': 'delete'
+ },
+
+ /**
+ * Succeed code returned in callbacks
+ * @constant
+ * @type {Number}
+ */
+ CODE_SUCCEED: 0,
+
+ /**
+ * App event names constants
+ * @constant
+ * @type {Object}
+ */
+ AppEvent: {
+ 'ACTIVATED_APP': FB.AppEvents.EventNames.ACTIVATED_APP,
+ 'COMPLETED_REGISTRATION': FB.AppEvents.EventNames.COMPLETED_REGISTRATION,
+ 'VIEWED_CONTENT': FB.AppEvents.EventNames.VIEWED_CONTENT,
+ 'SEARCHED': FB.AppEvents.EventNames.SEARCHED,
+ 'RATED': FB.AppEvents.EventNames.RATED,
+ 'COMPLETED_TUTORIAL': FB.AppEvents.EventNames.COMPLETED_TUTORIAL,
+ 'ADDED_TO_CART': FB.AppEvents.EventNames.ADDED_TO_CART,
+ 'ADDED_TO_WISHLIST': FB.AppEvents.EventNames.ADDED_TO_WISHLIST,
+ 'INITIATED_CHECKOUT': FB.AppEvents.EventNames.INITIATED_CHECKOUT,
+ 'ADDED_PAYMENT_INFO': FB.AppEvents.EventNames.ADDED_PAYMENT_INFO,
+ 'PURCHASED': FB.AppEvents.EventNames.PURCHASED,
+ 'ACHIEVED_LEVEL': FB.AppEvents.EventNames.ACHIEVED_LEVEL,
+ 'UNLOCKED_ACHIEVEMENT': FB.AppEvents.EventNames.UNLOCKED_ACHIEVEMENT,
+ 'SPENT_CREDITS': FB.AppEvents.EventNames.SPENT_CREDITS
+ },
+
+ /**
+ * App event parameter names constants
+ * @constant
+ * @type {Object}
+ */
+ AppEventParam: {
+ 'CURRENCY': FB.AppEvents.ParameterNames.CURRENCY,
+ 'REGISTRATION_METHOD': FB.AppEvents.ParameterNames.REGISTRATION_METHOD,
+ 'CONTENT_TYPE': FB.AppEvents.ParameterNames.CONTENT_TYPE,
+ 'CONTENT_ID': FB.AppEvents.ParameterNames.CONTENT_ID,
+ 'SEARCH_STRING': FB.AppEvents.ParameterNames.SEARCH_STRING,
+ 'SUCCESS': FB.AppEvents.ParameterNames.SUCCESS,
+ 'MAX_RATING_VALUE': FB.AppEvents.ParameterNames.MAX_RATING_VALUE,
+ 'PAYMENT_INFO_AVAILABLE': FB.AppEvents.ParameterNames.PAYMENT_INFO_AVAILABLE,
+ 'NUM_ITEMS': FB.AppEvents.ParameterNames.NUM_ITEMS,
+ 'LEVEL': FB.AppEvents.ParameterNames.LEVEL,
+ 'DESCRIPTION': FB.AppEvents.ParameterNames.DESCRIPTION
+ },
+
+ /**
+ * App event parameter values constants
+ * @constant
+ * @type {Object}
+ */
+ AppEventParamValue: {
+ 'VALUE_YES': "1",
+ 'VALUE_NO': "0"
+ },
+
+ _checkLoginStatus: function() {
+ var self = this;
+ FB.getLoginStatus(function (response) {
+ if (response && response.status === 'connected') {
+ //login
+ self._isLoggedIn = true;
+ //save user info
+ self._userInfo = response['authResponse'];
+ } else {
+ // Reset cached status
+ self._isLoggedIn = false;
+ self._userInfo = {};
+ }
+ });
+ },
+
+ ctor: function (config) {
+ this.name = "facebook";
+ this.version = "1.0";
+ this._userInfo = {};
+ this._isLoggedIn = false;
+
+ if (!FB) {
+ return;
+ }
+
+ //This configuration will be read from the project.json.
+ FB.init(config);
+ this._checkLoginStatus();
+
+ plugin.FacebookAgent = this;
+ },
+ /**
+ * Gets the current object
+ * @returns {FacebookAgent}
+ */
+ getInstance: function () {
+ return this;
+ },
+ /**
+ * Login to facebook
+ * @param {Function} callback
+ * @param {Array} permissions
+ * @example
+ * //example
+ * plugin.FacebookAgent.login();
+ */
+ login: function (permissions, callback) {
+ var self = this;
+ if (typeof permissions == 'function') {
+ callback = permissions;
+ permissions = [];
+ }
+ if (permissions.every(function (item) {
+ if (item != 'public_profile')
+ return true;
+ })) {
+ permissions.push("public_profile");
+ }
+ var permissionsStr = permissions.join(',');
+ FB.login(function (response) {
+ if (response['authResponse']) {
+ //save user info
+ self._isLoggedIn = true;
+ self._userInfo = response['authResponse'];
+ var permissList = response['authResponse']['grantedScopes'].split(",");
+ typeof callback === 'function' && callback(0, {
+ accessToken: response['authResponse']['accessToken'],
+ permissions: permissList
+ });
+ } else {
+ self._isLoggedIn = false;
+ self._userInfo = {};
+ typeof callback === 'function' && callback(response['error_code'] || 1, {
+ error_message: response['error_message'] || "Unknown error"
+ });
+ }
+ }, {
+ scope: permissionsStr,
+ return_scopes: true
+ });
+ },
+ /**
+ * Checking login status
+ * @return {Bool} Whether user is logged in
+ * @example
+ * //example
+ * plugin.FacebookAgent.isLoggedIn(type, msg);
+ */
+ isLoggedIn: function () {
+ //this._checkLoginStatus();
+ return this._isLoggedIn;
+ },
+
+ /**
+ * Logout of facebook
+ * @param {Function} callback
+ * @example
+ * //example
+ * plugin.FacebookAgent.logout(callback);
+ */
+ logout: function (callback) {
+ var self = this;
+ FB.logout(function (response) {
+ if (response['authResponse']) {
+ // user is now logged out
+ self._isLoggedIn = false;
+ self._userInfo = {};
+ typeof callback === 'function' && callback(0, {"isLoggedIn": false});
+ } else {
+ typeof callback === 'function' && callback(response['error_code'] || 1, {
+ error_message: response['error_message'] || "Unknown error"
+ });
+ }
+ });
+ },
+
+ /**
+ * Acquiring new permissions
+ * @deprecated since v3.0
+ * @param permissions
+ * @param callback
+ * @example
+ * //example
+ * plugin.FacebookAgent.requestPermissions(["manage_pages"], callback);
+ */
+ _requestPermissions: function (permissions, callback) {
+ var permissionsStr = permissions.join(',');
+ var self = this;
+ FB.login(function (response) {
+ if (response['authResponse']) {
+ var permissList = response['authResponse']['grantedScopes'].split(",");
+ //save user info
+ self._isLoggedIn = true;
+ self._userInfo = response['authResponse'];
+ typeof callback === 'function' && callback(0, {
+ permissions: permissList
+ });
+ } else {
+ self._isLoggedIn = false;
+ self._userInfo = {};
+ typeof callback === 'function' && callback(response['error_code'] || 1, {
+ error_message: response['error_message'] || "Unknown error"
+ });
+ }
+ }, {
+ scope: permissionsStr,
+ return_scopes: true
+ });
+ },
+
+ /**
+ * Acquiring AccessToken
+ * @return {String}
+ * @example
+ * //example
+ * var accessToken = plugin.FacebookAgent.getAccessToken();
+ */
+ getAccessToken: function () {
+ return this._userInfo ? this._userInfo['accessToken'] : null;
+ },
+
+ /**
+ * Acquiring User ID
+ * @return {String}
+ * @example
+ * //example
+ * var userID = plugin.FacebookAgent.getUserID();
+ */
+ getUserID: function () {
+ return this._userInfo ? this._userInfo['userID'] : null;
+ },
+
+ _share: function (info, callback) {
+ FB.ui({
+ method: 'share',
+ name: info['title'],
+ caption: info['caption'],
+ description: info['text'],
+ href: info['link'],
+ picture: info['imageUrl']
+ },
+ function (response) {
+ if (response) {
+ if (response['post_id'])
+ typeof callback === 'function' && callback(0, {
+ didComplete: true,
+ post_id: response['post_id']
+ });
+ else
+ typeof callback === 'function' && callback(response['error_code'] || 1, {
+ error_message: response['error_message'] || "Unknown error"
+ });
+ } else {
+ typeof callback === 'function' && callback(1, {
+ error_message: "Unknown error"
+ });
+ }
+ });
+ },
+
+ /**
+ * Request a web dialog for Facebook sharing
+ * @param info
+ * @param callback
+ */
+ dialog: function (info, callback) {
+ if (!info) {
+ typeof callback === 'function' && callback(1, {
+ error_message: "No info parameter provided"
+ });
+ return;
+ }
+ if (!this.canPresentDialog(info)) {
+ typeof callback === 'function' && callback(1, {
+ error_message: "The requested dialog: " + info['dialog'] + " can not be presented on Web"
+ });
+ return;
+ }
+
+ // Preprocess properties
+ info['name'] = info['name'] || info['site'];
+ delete info['site'];
+
+ info['href'] = info['href'] || info['link'] || info['siteUrl'];
+ delete info['siteUrl'];
+ delete info['link'];
+
+ info['picture'] = info['picture'] || info['image'] || info['photo'] || info['imageUrl'] || info['imagePath'];
+ delete info['imageUrl'];
+ delete info['imagePath'];
+ delete info['photo'];
+ delete info['image'];
+
+ info['caption'] = info['title'] || info['caption'];
+ delete info['title'];
+
+ info['description'] = info['text'] || info['description'];
+ delete info['text'];
+
+ var method = info['dialog'];
+ delete info['dialog'];
+
+ if (method === 'shareLink' || method == 'feedDialog') {
+ info['method'] = 'share';
+ } else if (method == 'messageLink') {
+ info['method'] = 'send';
+ info['link'] = info['href'];
+ } else if (method == 'shareOpenGraph') {
+ info['method'] = 'share_open_graph';
+
+ if (info['url']) {
+ var obj = {};
+ if (info["preview_property_name"])
+ obj[info["preview_property_name"]] = info["url"];
+ else
+ obj["object"] = info["url"];
+
+ for (var p in info) {
+ if (p != "method" && p != "action_type" && p != "action_properties") {
+ info[p] && (obj[p] = info[p]);
+ delete info[p];
+ }
+ }
+
+ info['action_properties'] = JSON.stringify(obj);
+ }
+ }
+
+ FB.ui(info,
+ function (response) {
+ if (response && typeof callback === 'function') {
+ if (response['post_id'] || response['success']) {
+ callback(0, {
+ didComplete: true,
+ post_id: response['post_id'] || ""
+ });
+ }
+ else {
+ if (response['error_code']) {
+ callback(response['error_code'], {
+ error_message : response['error_message'] || 'Unknown error'
+ });
+ }
+ else callback(0, response);
+ }
+ } else if (response == undefined && typeof callback === 'function') {
+ callback(1, {
+ error_message: "Unknown error"
+ });
+ }
+ });
+ },
+
+ /**
+ * Check whether the share request can be achieved
+ * @param info
+ */
+ canPresentDialog: function (info) {
+ if (info && info['dialog'] && (
+ info['dialog'] === 'shareLink' ||
+ info['dialog'] === 'feedDialog' ||
+ info['dialog'] === 'shareOpenGraph' ||
+ info['dialog'] === 'messageLink'))
+ return true;
+ else
+ return false;
+ },
+ /**
+ * FB.api
+ * @param {String} path
+ * @param {Number} httpmethod
+ * @param {Object} params
+ * @param {Function} callback
+ */
+ api: function (path, httpmethod, params, callback) {
+ if (typeof params === 'function') {
+ callback = params;
+ params = {};
+ }
+ FB.api(path, httpmethod, params, function (response) {
+ if (response.error) {
+ typeof callback === 'function' && callback(response['error']['code'], {
+ error_message: response['error']['message'] || 'Unknown error'
+ })
+ } else {
+ typeof callback === 'function' && callback(0, response);
+ }
+ });
+ },
+
+ _getPermissionList: function (callback) {
+ FB.api("/me/permissions", function (response) {
+ if (response['data']) {
+ var permissionList = [];
+ for (var i = 0; i < response['data'].length; i++) {
+ if (response['data'][i]["status"] == "granted") {
+ permissionList.push(response['data'][i]['permission']);
+ }
+ }
+ typeof callback == 'function' && callback(0, {
+ permissions: permissionList
+ });
+ } else {
+ if (!response['error'])
+ response['error'] = {};
+ typeof callback == 'function' && callback(response['error']['code'] || 1, {
+ error_message: response['error']['message'] || 'Unknown error'
+ });
+ }
+ })
+ },
+
+ destroyInstance: function () {
+ },
+ canvas:{
+ /**
+ * Payment request
+ * @param {Object} info
+ * @param {Function} callback
+ */
+ pay: function (info, callback) {
+ /*
+ * Reference document
+ * https://developers.facebook.com/docs/payments/reference/paydialog
+ */
+ info['method'] = 'pay';
+ info['action'] = 'purchaseitem';
+
+ FB.ui(info, function (response) {
+ if (response['error_code']) {
+ callback(response['error_code'] || 1, {
+ error_message: response['error_message'] || response['error_msg'] || 'Unknown error'
+ });
+ } else {
+ callback(0, response);
+ }
+ })
+ }
+ },
+
+ /**
+ * Send an app requests to friends
+ * @param {Object} info
+ * @param {Function} callback
+ */
+ appRequest: function (info, callback) {
+ if (!info) {
+ typeof callback === 'function' && callback(1, {
+ error_message: "No info parameter provided"
+ });
+ return;
+ }
+
+ info['method'] = "apprequests";
+
+ FB.ui(info,
+ function (response) {
+ if (response) {
+ if (response['error_code']) {
+ typeof callback === 'function' && callback(response['error_code'], {
+ error_message : response['error_message'] || 'Unknown error'
+ });
+ }
+ else {
+ typeof callback === 'function' && callback(0, response);
+ }
+ } else {
+ typeof callback === 'function' && callback(1, {
+ error_message: "Unknown error"
+ });
+ }
+ });
+ },
+
+ /**
+ * Log an event
+ * @param {String} eventName
+ * @param {Number} valueToSum
+ * @param {Object} parameters
+ */
+ logEvent: function (eventName, valueToSum, parameters) {
+ if (eventName == undefined) return;
+ if (valueToSum === undefined && parameters === undefined) {
+ FB.AppEvents.logEvent(eventName, null, null);
+ } else if (typeof valueToSum === "number" && parameters === undefined) {
+ FB.AppEvents.logEvent(eventName, valueToSum);
+ } else if (typeof valueToSum === "object" && parameters === undefined) {
+ FB.AppEvents.logEvent(eventName, null, valueToSum);
+ } else {
+ FB.AppEvents.logEvent(eventName, valueToSum, parameters);
+ }
+ },
+
+ /**
+ * Activate App
+ */
+ activateApp: function () {
+ FB.AppEvents.activateApp();
+ },
+
+ /**
+ * Log a purchase
+ * @param {Number} amount Amount of the purchase
+ * @param {String} currency The currency
+ * @param {Object} param Supplemental parameters
+ */
+ logPurchase:function(amount, currency, param){
+ FB.AppEvents.logPurchase(amount, currency, param);
+ }
+});
diff --git a/external/pluginx/platform/facebook_sdk.js b/external/pluginx/platform/facebook_sdk.js
new file mode 100644
index 0000000000..bc05068323
--- /dev/null
+++ b/external/pluginx/platform/facebook_sdk.js
@@ -0,0 +1,151 @@
+
+/*1411456395,,JIT Construction: v1425205,zh_CN*/
+
+/**
+ * Copyright Facebook Inc.
+ *
+ * Licensed under the Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+try {window.FB || (function(window) {
+ var self = window, document = window.document;
+ var setTimeout = window.setTimeout, setInterval = window.setInterval,clearTimeout = window.clearTimeout,clearInterval = window.clearInterval;var __DEV__ = 0;
+ function emptyFunction() {};
+ var __w, __t;
+ __t=function(a){return a[0];};__w=function(a){return a;};
+ var require,__d;(function(a){var b={},c={},d=['global','require','requireDynamic','requireLazy','module','exports'];require=function(e,f){if(c.hasOwnProperty(e))return c[e];if(!b.hasOwnProperty(e)){if(f)return null;throw new Error('Module '+e+' has not been defined');}var g=b[e],h=g.deps,i=g.factory.length,j,k=[];for(var l=0;l1?Number(arguments[1]):0;if(isNaN(j))j=0;var k=Math.min(Math.max(j,0),i.length);return i.indexOf(String(h),j)==k;};g.endsWith=function(h){var i=String(this);if(this==null)throw new TypeError('String.prototype.endsWith called on null or undefined');var j=i.length,k=String(h),l=arguments.length>1?Number(arguments[1]):j;if(isNaN(l))l=0;var m=Math.min(Math.max(l,0),j),n=m-k.length;if(n<0)return false;return i.lastIndexOf(k,n)==n;};g.contains=function(h){if(this==null)throw new TypeError('String.prototype.contains called on null or undefined');var i=String(this),j=arguments.length>1?Number(arguments[1]):0;if(isNaN(j))j=0;return i.indexOf(String(h),j)!=-1;};g.repeat=function(h){if(this==null)throw new TypeError('String.prototype.repeat called on null or undefined');var i=String(this),j=h?Number(h):0;if(isNaN(j))j=0;if(j<0||j===Infinity)throw RangeError();if(j===1)return i;if(j===0)return '';var k='';while(j){if(j&1)k+=i;if((j>>=1))i+=i;}return k;};e.exports=g;},null);
+ __d("ES5Array",[],function(a,b,c,d,e,f){var g={};g.isArray=function(h){return Object.prototype.toString.call(h)=='[object Array]';};e.exports=g;},null);
+ __d("ie8DontEnum",[],function(a,b,c,d,e,f){var g=['toString','toLocaleString','valueOf','hasOwnProperty','isPrototypeOf','prototypeIsEnumerable','constructor'],h=({}).hasOwnProperty,i=function(){};if(({toString:true}).propertyIsEnumerable('toString'))i=function(j,k){for(var l=0;l1)))/4)-ca((ga-1901+ha)/100)+ca((ga-1601+ha)/400);};}if(typeof JSON=="object"&&JSON){k.stringify=JSON.stringify;k.parse=JSON.parse;}if((m=typeof k.stringify=="function"&&!ea)){(ba=function(){return 1;}).toJSON=ba;try{m=k.stringify(0)==="0"&&k.stringify(new Number())==="0"&&k.stringify(new String())=='""'&&k.stringify(g)===j&&k.stringify(j)===j&&k.stringify()===j&&k.stringify(ba)==="1"&&k.stringify([ba])=="[1]"&&k.stringify([j])=="[null]"&&k.stringify(null)=="null"&&k.stringify([j,g,null])=="[null,null,null]"&&k.stringify({result:[ba,true,false,null,"\0\b\n\f\r\t"]})==l&&k.stringify(null,ba)==="1"&&k.stringify([1,2],null,1)=="[\n 1,\n 2\n]"&&k.stringify(new Date(-8.64e+15))=='"-271821-04-20T00:00:00.000Z"'&&k.stringify(new Date(8.64e+15))=='"+275760-09-13T00:00:00.000Z"'&&k.stringify(new Date(-62198755200000))=='"-000001-01-01T00:00:00.000Z"'&&k.stringify(new Date(-1))=='"1969-12-31T23:59:59.999Z"';}catch(fa){m=false;}}if(typeof k.parse=="function")try{if(k.parse("0")===0&&!k.parse(false)){ba=k.parse(l);if((r=ba.A.length==5&&ba.A[0]==1)){try{r=!k.parse('"\t"');}catch(fa){}if(r)try{r=k.parse("01")!=1;}catch(fa){}}}}catch(fa){r=false;}ba=l=null;if(!m||!r){if(!(h={}.hasOwnProperty))h=function(ga){var ha={},ia;if((ha.__proto__=null,ha.__proto__={toString:1},ha).toString!=g){h=function(ja){var ka=this.__proto__,la=ja in (this.__proto__=null,this);this.__proto__=ka;return la;};}else{ia=ha.constructor;h=function(ja){var ka=(this.constructor||ia).prototype;return ja in this&&!(ja in ka&&this[ja]===ka[ja]);};}ha=null;return h.call(this,ga);};i=function(ga,ha){var ia=0,ja,ka,la,ma;(ja=function(){this.valueOf=0;}).prototype.valueOf=0;ka=new ja();for(la in ka)if(h.call(ka,la))ia++;ja=ka=null;if(!ia){ka=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"];ma=function(na,oa){var pa=g.call(na)=="[object Function]",qa,ra;for(qa in na)if(!(pa&&qa=="prototype")&&h.call(na,qa))oa(qa);for(ra=ka.length;qa=ka[--ra];h.call(na,qa)&&oa(qa));};}else if(ia==2){ma=function(na,oa){var pa={},qa=g.call(na)=="[object Function]",ra;for(ra in na)if(!(qa&&ra=="prototype")&&!h.call(pa,ra)&&(pa[ra]=1)&&h.call(na,ra))oa(ra);};}else ma=function(na,oa){var pa=g.call(na)=="[object Function]",qa,ra;for(qa in na)if(!(pa&&qa=="prototype")&&h.call(na,qa)&&!(ra=qa==="constructor"))oa(qa);if(ra||h.call(na,(qa="constructor")))oa(qa);};return ma(ga,ha);};if(!m){n={"\\":"\\\\",'"':'\\"',"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t"};o=function(ga,ha){return ("000000"+(ha||0)).slice(-ga);};p=function(ga){var ha='"',ia=0,ja;for(;ja=ga.charAt(ia);ia++)ha+='\\"\b\f\n\r\t'.indexOf(ja)>-1?n[ja]:ja<" "?"\\u00"+o(2,ja.charCodeAt(0).toString(16)):ja;return ha+'"';};q=function(ga,ha,ia,ja,ka,la,ma){var na=ha[ga],oa,pa,qa,ra,sa,ta,ua,va,wa,xa,ya,za,ab,bb,cb;if(typeof na=="object"&&na){oa=g.call(na);if(oa=="[object Date]"&&!h.call(na,"toJSON")){if(na>-1/0&&na<1/0){if(ea){ra=ca(na/86400000);for(pa=ca(ra/365.2425)+1970-1;ea(pa+1,0)<=ra;pa++);for(qa=ca((ra-ea(pa,0))/30.42);ea(pa,qa+1)<=ra;qa++);ra=1+ra-ea(pa,qa);sa=(na%86400000+86400000)%86400000;ta=ca(sa/3600000)%24;ua=ca(sa/60000)%60;va=ca(sa/1000)%60;wa=sa%1000;}else{pa=na.getUTCFullYear();qa=na.getUTCMonth();ra=na.getUTCDate();ta=na.getUTCHours();ua=na.getUTCMinutes();va=na.getUTCSeconds();wa=na.getUTCMilliseconds();}na=(pa<=0||pa>=10000?(pa<0?"-":"+")+o(6,pa<0?-pa:pa):o(4,pa))+"-"+o(2,qa+1)+"-"+o(2,ra)+"T"+o(2,ta)+":"+o(2,ua)+":"+o(2,va)+"."+o(3,wa)+"Z";}else na=null;}else if(typeof na.toJSON=="function"&&((oa!="[object Number]"&&oa!="[object String]"&&oa!="[object Array]")||h.call(na,"toJSON")))na=na.toJSON(ga);}if(ia)na=ia.call(ha,ga,na);if(na===null)return "null";oa=g.call(na);if(oa=="[object Boolean]"){return ""+na;}else if(oa=="[object Number]"){return na>-1/0&&na<1/0?""+na:"null";}else if(oa=="[object String]")return p(na);if(typeof na=="object"){for(ab=ma.length;ab--;)if(ma[ab]===na)throw TypeError();ma.push(na);xa=[];bb=la;la+=ka;if(oa=="[object Array]"){for(za=0,ab=na.length;za0)for(ja="",ia>10&&(ia=10);ja.length-1){z++;}else if("{}[]:,".indexOf(ia)>-1){z++;return ia;}else if(ia=='"'){for(ja="@",z++;z-1){ja+=t[ia];z++;}else if(ia=="u"){ka=++z;for(la=z+4;z="0"&&ia<="9"||ia>="a"&&ia<="f"||ia>="A"&&ia<="F"))u();}ja+=s("0x"+ga.slice(ka,z));}else u();}else{if(ia=='"')break;ja+=ia;z++;}}if(ga.charAt(z)=='"'){z++;return ja;}u();}else{ka=z;if(ia=="-"){ma=true;ia=ga.charAt(++z);}if(ia>="0"&&ia<="9"){if(ia=="0"&&(ia=ga.charAt(z+1),ia>="0"&&ia<="9"))u();ma=false;for(;z="0"&&ia<="9");z++);if(ga.charAt(z)=="."){la=++z;for(;la="0"&&ia<="9");la++);if(la==z)u();z=la;}ia=ga.charAt(z);if(ia=="e"||ia=="E"){ia=ga.charAt(++z);if(ia=="+"||ia=="-")z++;for(la=z;la="0"&&ia<="9");la++);if(la==z)u();z=la;}return +ga.slice(ka,z);}if(ma)u();if(ga.slice(z,z+4)=="true"){z+=4;return true;}else if(ga.slice(z,z+5)=="false"){z+=5;return false;}else if(ga.slice(z,z+4)=="null"){z+=4;return null;}u();}}return "$";};w=function(ga){var ha,ia,ja;if(ga=="$")u();if(typeof ga=="string"){if(ga.charAt(0)=="@")return ga.slice(1);if(ga=="["){ha=[];for(;;ia||(ia=true)){ga=v();if(ga=="]")break;if(ia)if(ga==","){ga=v();if(ga=="]")u();}else u();if(ga==",")u();ha.push(w(ga));}return ha;}else if(ga=="{"){ha={};for(;;ia||(ia=true)){ga=v();if(ga=="}")break;if(ia)if(ga==","){ga=v();if(ga=="}")u();}else u();if(ga==","||typeof ga!="string"||ga.charAt(0)!="@"||v()!=":")u();ha[ga.slice(1)]=w(v());}return ha;}u();}return ga;};y=function(ga,ha,ia){var ja=x(ga,ha,ia);if(ja===j){delete ga[ha];}else ga[ha]=ja;};x=function(ga,ha,ia){var ja=ga[ha],ka;if(typeof ja=="object"&&ja)if(g.call(ja)=="[object Array]"){for(ka=ja.length;ka--;)y(ja,ka,ia);}else i(ja,function(la){y(ja,la,ia);});return ia.call(ga,ha,ja);};k.parse=function(ga,ha){z=0;aa=ga;var ia=w(v());if(v()!="$")u();z=aa=null;return ha&&g.call(ha)=="[object Function]"?x((ba={},ba[""]=ia,ba),"",ha):ia;};}}}).call(this);},null);
+ __d("ES6Object",["ie8DontEnum"],function(a,b,c,d,e,f,g){var h=({}).hasOwnProperty,i={assign:function(j){var k=Array.prototype.slice.call(arguments,1);if(j==null)throw new TypeError('Object.assign target cannot be null or undefined');j=Object(j);for(var l=0;l>>0;for(var l=0;l9999?'+':''))+('00000'+Math.abs(i)).slice(0<=i&&i<=9999?-4:-6);return i+'-'+g(this.getUTCMonth()+1)+'-'+g(this.getUTCDate())+'T'+g(this.getUTCHours())+':'+g(this.getUTCMinutes())+':'+g(this.getUTCSeconds())+'.'+(this.getUTCMilliseconds()/1000).toFixed(3).slice(2,5)+'Z';}};e.exports=h;},null);
+ __d("ES6Number",[],function(a,b,c,d,e,f){var g={isFinite:function(h){return (typeof h=='number')&&isFinite(h);},isNaN:function(h){return (typeof h=='number')&&isNaN(h);}};e.exports=g;},null);
+ __d("ES",["ES5ArrayPrototype","ES5FunctionPrototype","ES5StringPrototype","ES5Array","ES5Object","ES5Date","JSON3","ES6Object","ES6ArrayPrototype","ES6DatePrototype","ES6Number"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q){var r=({}).toString,s={'JSON.stringify':m.stringify,'JSON.parse':m.parse},t={'Array.prototype':g,'Function.prototype':h,'String.prototype':i,Object:k,Array:j,Date:l},u={Object:n,'Array.prototype':o,'Date.prototype':p,Number:q};function v(x){for(var y in x){if(!x.hasOwnProperty(y))continue;var z=x[y],aa=y.split('.'),ba=aa.length==2?window[aa[0]][aa[1]]:window[y];for(var ca in z){if(!z.hasOwnProperty(ca))continue;var da=ba[ca];s[y+'.'+ca]=da&&/\{\s+\[native code\]\s\}/.test(da)?da:z[ca];}}}v(t);v(u);function w(x,y,z){var aa=Array.prototype.slice.call(arguments,3),ba=z?r.call(x).slice(8,-1)+'.prototype':x,ca=s[ba+'.'+y]||x[y];if(typeof ca==='function')return ca.apply(x,aa);}e.exports=w;},null);
+ var ES = require('ES');
+ __d("JSSDKRuntimeConfig",[],{"locale":"zh_CN","rtl":false,"revision":"1425205"});__d("JSSDKConfig",[],{"bustCache":true,"tagCountLogRate":0.01,"errorHandling":{"rate":4},"usePluginPipe":true,"features":{"allow_non_canvas_app_events":false,"event_subscriptions_log":{"rate":0.01,"value":10000},"kill_fragment":true,"xfbml_profile_pic_server":true,"error_handling":{"rate":4},"e2e_ping_tracking":{"rate":1.0e-6},"xd_timeout":{"rate":4,"value":30000},"use_bundle":true,"launch_payment_dialog_via_pac":{"rate":100}},"api":{"mode":"warn","whitelist":["Canvas","Canvas.Prefetcher","Canvas.Prefetcher.addStaticResource","Canvas.Prefetcher.setCollectionMode","Canvas.getPageInfo","Canvas.hideFlashElement","Canvas.scrollTo","Canvas.setAutoGrow","Canvas.setDoneLoading","Canvas.setSize","Canvas.setUrlHandler","Canvas.showFlashElement","Canvas.startTimer","Canvas.stopTimer","Data","Data.process","Data.query","Data.query:wait","Data.waitOn","Data.waitOn:wait","Event","Event.subscribe","Event.unsubscribe","Music.flashCallback","Music.init","Music.send","Payment","Payment.cancelFlow","Payment.continueFlow","Payment.init","Payment.lockForProcessing","Payment.unlockForProcessing","Payment.parse","Payment.setSize","ThirdPartyProvider","ThirdPartyProvider.init","ThirdPartyProvider.sendData","UA","UA.nativeApp","XFBML","XFBML.RecommendationsBar","XFBML.RecommendationsBar.markRead","XFBML.parse","addFriend","api","getAccessToken","getAuthResponse","getLoginStatus","getUserID","init","login","logout","publish","share","ui","ui:subscribe","AppEvents","AppEvents.activateApp","AppEvents.logEvent","AppEvents.logPurchase","AppEvents.EventNames","AppEvents.ParameterNames"]},"initSitevars":{"enableMobileComments":1,"iframePermissions":{"read_stream":false,"manage_mailbox":false,"manage_friendlists":false,"read_mailbox":false,"publish_checkins":true,"status_update":true,"photo_upload":true,"video_upload":true,"sms":false,"create_event":true,"rsvp_event":true,"offline_access":true,"email":true,"xmpp_login":false,"create_note":true,"share_item":true,"export_stream":false,"publish_stream":true,"publish_likes":true,"ads_management":false,"contact_email":true,"access_private_data":false,"read_insights":false,"read_requests":false,"read_friendlists":true,"manage_pages":false,"physical_login":false,"manage_groups":false,"read_deals":false}}});__d("UrlMapConfig",[],{"www":"www.facebook.com","m":"m.facebook.com","connect":"connect.facebook.net","business":"business.facebook.com","api_https":"api.facebook.com","api_read_https":"api-read.facebook.com","graph_https":"graph.facebook.com","fbcdn_http":"static.ak.fbcdn.net","fbcdn_https":"fbstatic-a.akamaihd.net","cdn_http":"static.ak.facebook.com","cdn_https":"s-static.ak.facebook.com"});__d("JSSDKXDConfig",[],{"XdUrl":"\/connect\/xd_arbiter.php?version=41","XdBundleUrl":"\/connect\/xd_arbiter\/ZEbdHPQfV3x.js?version=41","Flash":{"path":"https:\/\/connect.facebook.net\/rsrc.php\/v1\/yR\/r\/ks_9ZXiQ0GL.swf"},"useCdn":true});__d("JSSDKCssConfig",[],{"rules":".fb_hidden{position:absolute;top:-10000px;z-index:10001}.fb_invisible{display:none}.fb_reset{background:none;border:0;border-spacing:0;color:#000;cursor:auto;direction:ltr;font-family:\"lucida grande\", tahoma, verdana, arial, sans-serif;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:1;margin:0;overflow:visible;padding:0;text-align:left;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;visibility:visible;white-space:normal;word-spacing:normal}.fb_reset>div{overflow:hidden}.fb_link img{border:none}\n.fb_dialog{background:rgba(82, 82, 82, .7);position:absolute;top:-10000px;z-index:10001}.fb_reset .fb_dialog_legacy{overflow:visible}.fb_dialog_advanced{padding:10px;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.fb_dialog_content{background:#fff;color:#333}.fb_dialog_close_icon{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yq\/r\/IE9JII6Z1Ys.png) no-repeat scroll 0 0 transparent;_background-image:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yL\/r\/s816eWC-2sl.gif);cursor:pointer;display:block;height:15px;position:absolute;right:18px;top:17px;width:15px}.fb_dialog_mobile .fb_dialog_close_icon{top:5px;left:5px;right:auto}.fb_dialog_padding{background-color:transparent;position:absolute;width:1px;z-index:-1}.fb_dialog_close_icon:hover{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yq\/r\/IE9JII6Z1Ys.png) no-repeat scroll 0 -15px transparent;_background-image:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yL\/r\/s816eWC-2sl.gif)}.fb_dialog_close_icon:active{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yq\/r\/IE9JII6Z1Ys.png) no-repeat scroll 0 -30px transparent;_background-image:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yL\/r\/s816eWC-2sl.gif)}.fb_dialog_loader{background-color:#f2f2f2;border:1px solid #606060;font-size:25px;padding:20px}.fb_dialog_top_left,.fb_dialog_top_right,.fb_dialog_bottom_left,.fb_dialog_bottom_right{height:10px;width:10px;overflow:hidden;position:absolute}.fb_dialog_top_left{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 0;left:-10px;top:-10px}.fb_dialog_top_right{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 -10px;right:-10px;top:-10px}.fb_dialog_bottom_left{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 -20px;bottom:-10px;left:-10px}.fb_dialog_bottom_right{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 -30px;right:-10px;bottom:-10px}.fb_dialog_vert_left,.fb_dialog_vert_right,.fb_dialog_horiz_top,.fb_dialog_horiz_bottom{position:absolute;background:#525252;filter:alpha(opacity=70);opacity:.7}.fb_dialog_vert_left,.fb_dialog_vert_right{width:10px;height:100\u0025}.fb_dialog_vert_left{margin-left:-10px}.fb_dialog_vert_right{right:0;margin-right:-10px}.fb_dialog_horiz_top,.fb_dialog_horiz_bottom{width:100\u0025;height:10px}.fb_dialog_horiz_top{margin-top:-10px}.fb_dialog_horiz_bottom{bottom:0;margin-bottom:-10px}.fb_dialog_iframe{line-height:0}.fb_dialog_content .dialog_title{background:#6d84b4;border:1px solid #3b5998;color:#fff;font-size:15px;font-weight:bold;margin:0}.fb_dialog_content .dialog_title>span{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/yd\/r\/Cou7n-nqK52.gif) no-repeat 5px 50\u0025;float:left;padding:5px 0 7px 26px}body.fb_hidden{-webkit-transform:none;height:100\u0025;margin:0;overflow:visible;position:absolute;top:-10000px;left:0;width:100\u0025}.fb_dialog.fb_dialog_mobile.loading{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/ya\/r\/3rhSv5V8j3o.gif) white no-repeat 50\u0025 50\u0025;min-height:100\u0025;min-width:100\u0025;overflow:hidden;position:absolute;top:0;z-index:10001}.fb_dialog.fb_dialog_mobile.loading.centered{max-height:590px;min-height:590px;max-width:500px;min-width:500px}#fb-root #fb_dialog_ipad_overlay{background:rgba(0, 0, 0, .45);position:absolute;left:0;top:0;width:100\u0025;min-height:100\u0025;z-index:10000}#fb-root #fb_dialog_ipad_overlay.hidden{display:none}.fb_dialog.fb_dialog_mobile.loading iframe{visibility:hidden}.fb_dialog_content .dialog_header{-webkit-box-shadow:white 0 1px 1px -1px inset;background:-webkit-gradient(linear, 0\u0025 0\u0025, 0\u0025 100\u0025, from(#738ABA), to(#2C4987));border-bottom:1px solid;border-color:#1d4088;color:#fff;font:14px Helvetica, sans-serif;font-weight:bold;text-overflow:ellipsis;text-shadow:rgba(0, 30, 84, .296875) 0 -1px 0;vertical-align:middle;white-space:nowrap}.fb_dialog_content .dialog_header table{-webkit-font-smoothing:subpixel-antialiased;height:43px;width:100\u0025}.fb_dialog_content .dialog_header td.header_left{font-size:13px;padding-left:5px;vertical-align:middle;width:60px}.fb_dialog_content .dialog_header td.header_right{font-size:13px;padding-right:5px;vertical-align:middle;width:60px}.fb_dialog_content .touchable_button{background:-webkit-gradient(linear, 0\u0025 0\u0025, 0\u0025 100\u0025, from(#4966A6), color-stop(.5, #355492), to(#2A4887));border:1px solid #29447e;-webkit-background-clip:padding-box;-webkit-border-radius:3px;-webkit-box-shadow:rgba(0, 0, 0, .117188) 0 1px 1px inset, rgba(255, 255, 255, .167969) 0 1px 0;display:inline-block;margin-top:3px;max-width:85px;line-height:18px;padding:4px 12px;position:relative}.fb_dialog_content .dialog_header .touchable_button input{border:none;background:none;color:#fff;font:12px Helvetica, sans-serif;font-weight:bold;margin:2px -12px;padding:2px 6px 3px 6px;text-shadow:rgba(0, 30, 84, .296875) 0 -1px 0}.fb_dialog_content .dialog_header .header_center{color:#fff;font-size:17px;font-weight:bold;line-height:18px;text-align:center;vertical-align:middle}.fb_dialog_content .dialog_content{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/y9\/r\/jKEcVPZFk-2.gif) no-repeat 50\u0025 50\u0025;border:1px solid #555;border-bottom:0;border-top:0;height:150px}.fb_dialog_content .dialog_footer{background:#f2f2f2;border:1px solid #555;border-top-color:#ccc;height:40px}#fb_dialog_loader_close{float:left}.fb_dialog.fb_dialog_mobile .fb_dialog_close_button{text-shadow:rgba(0, 30, 84, .296875) 0 -1px 0}.fb_dialog.fb_dialog_mobile .fb_dialog_close_icon{visibility:hidden}\n.fb_iframe_widget{display:inline-block;position:relative}.fb_iframe_widget span{display:inline-block;position:relative;text-align:justify}.fb_iframe_widget iframe{position:absolute}.fb_iframe_widget_lift{z-index:1}.fb_hide_iframes iframe{position:relative;left:-10000px}.fb_iframe_widget_loader{position:relative;display:inline-block}.fb_iframe_widget_fluid{display:inline}.fb_iframe_widget_fluid span{width:100\u0025}.fb_iframe_widget_loader iframe{min-height:32px;z-index:2;zoom:1}.fb_iframe_widget_loader .FB_Loader{background:url(http:\/\/static.ak.fbcdn.net\/rsrc.php\/v2\/y9\/r\/jKEcVPZFk-2.gif) no-repeat;height:32px;width:32px;margin-left:-16px;position:absolute;left:50\u0025;z-index:4}\n.fbpluginrecommendationsbarleft,.fbpluginrecommendationsbarright{position:fixed !important;bottom:0;z-index:999}.fbpluginrecommendationsbarleft{left:10px}.fbpluginrecommendationsbarright{right:10px}","components":["css:fb.css.base","css:fb.css.dialog","css:fb.css.iframewidget","css:fb.css.plugin.recommendationsbar"]});__d("ApiClientConfig",[],{"FlashRequest":{"swfUrl":"https:\/\/connect.facebook.net\/rsrc.php\/v1\/yW\/r\/PvklbuW2Ycn.swf"}});__d("JSSDKCanvasPrefetcherConfig",[],{"blacklist":[144959615576466],"sampleRate":500});__d("JSSDKPluginPipeConfig",[],{"threshold":0,"enabledApps":{"209753825810663":1,"187288694643718":1}});
+ __d("QueryString",[],function(a,b,c,d,e,f){function g(k){var l=[];ES(ES('Object','keys',false,k).sort(),'forEach',true,function(m){var n=k[m];if(typeof n==='undefined')return;if(n===null){l.push(m);return;}l.push(encodeURIComponent(m)+'='+encodeURIComponent(n));});return l.join('&');}function h(k,l){var m={};if(k==='')return m;var n=k.split('&');for(var o=0;oh);},ie64:function(){return x.ie()&&r;},firefox:function(){return w()||i;},opera:function(){return w()||j;},webkit:function(){return w()||k;},safari:function(){return x.webkit();},chrome:function(){return w()||l;},windows:function(){return w()||o;},osx:function(){return w()||n;},linux:function(){return w()||p;},iphone:function(){return w()||s;},mobile:function(){return w()||(s||t||q||v);},nativeApp:function(){return w()||u;},android:function(){return w()||q;},ipad:function(){return w()||t;}};e.exports=x;},null);
+ __d("hasNamePropertyBug",["guid","UserAgent_DEPRECATED"],function(a,b,c,d,e,f,g,h){var i=h.ie()?undefined:false;function j(){var l=document.createElement("form"),m=l.appendChild(document.createElement("input"));m.name=g();i=m!==l.elements[m.name];l=m=null;return i;}function k(){return typeof i==='undefined'?j():i;}e.exports=k;},null);
+ __d("wrapFunction",[],function(a,b,c,d,e,f){var g={};function h(i,j,k){j=j||'default';return function(){var l=j in g?g[j](i,k):i;return l.apply(this,arguments);};}h.setWrapper=function(i,j){j=j||'default';g[j]=i;};e.exports=h;},null);
+ __d("DOMEventListener",["wrapFunction"],function(a,b,c,d,e,f,g){var h,i;if(window.addEventListener){h=function(k,l,m){m.wrapper=g(m,'entry','DOMEventListener.add '+l);k.addEventListener(l,m.wrapper,false);};i=function(k,l,m){k.removeEventListener(l,m.wrapper,false);};}else if(window.attachEvent){h=function(k,l,m){m.wrapper=g(m,'entry','DOMEventListener.add '+l);k.attachEvent('on'+l,m.wrapper);};i=function(k,l,m){k.detachEvent('on'+l,m.wrapper);};}else i=h=function(){};var j={add:function(k,l,m){h(k,l,m);return {remove:function(){i(k,l,m);k=null;}};},remove:i};e.exports=j;},null);
+ __d("sdk.createIframe",["guid","hasNamePropertyBug","DOMEventListener"],function(a,b,c,d,e,f,g,h,i){function j(k){k=ES('Object','assign',false,{},k);var l,m=k.name||g(),n=k.root,o=k.style||{border:'none'},p=k.url,q=k.onload,r=k.onerror;if(h()){l=document.createElement('');}else{l=document.createElement("iframe");l.name=m;}delete k.style;delete k.name;delete k.url;delete k.root;delete k.onload;delete k.onerror;var s=ES('Object','assign',false,{frameBorder:0,allowTransparency:true,scrolling:'no'},k);if(s.width)l.width=s.width+'px';if(s.height)l.height=s.height+'px';delete s.height;delete s.width;for(var t in s)if(s.hasOwnProperty(t))l.setAttribute(t,s[t]);ES('Object','assign',false,l.style,o);l.src="javascript:false";n.appendChild(l);if(q)var u=i.add(l,'load',function(){u.remove();q();});if(r)var v=i.add(l,'error',function(){v.remove();r();});l.src=p;return l;}e.exports=j;},null);
+ __d("DOMWrapper",[],function(a,b,c,d,e,f){var g,h,i={setRoot:function(j){g=j;},getRoot:function(){return g||document.body;},setWindow:function(j){h=j;},getWindow:function(){return h||self;}};e.exports=i;},null);
+ __d("sdk.feature",["JSSDKConfig"],function(a,b,c,d,e,f,g){function h(i,j){if(g.features&&i in g.features){var k=g.features[i];if(typeof k==='object'&&typeof k.rate==='number'){if(k.rate&&Math.random()*100<=k.rate){return k.value||true;}else return k.value?null:false;}else return k;}return typeof j!=='undefined'?j:null;}e.exports=h;},null);
+ __d("sdk.getContextType",["UserAgent_DEPRECATED","sdk.Runtime"],function(a,b,c,d,e,f,g,h){function i(){if(g.nativeApp())return 3;if(g.mobile())return 2;if(h.isEnvironment(h.ENVIRONMENTS.CANVAS))return 5;return 1;}e.exports=i;},null);
+ __d("sdk.domReady",[],function(a,b,c,d,e,f){var g,h="readyState" in document?/loaded|complete/.test(document.readyState):!!document.body;function i(){if(!g)return;var l;while(l=g.shift())l();g=null;}function j(l){if(g){g.push(l);return;}else l();}if(!h){g=[];if(document.addEventListener){document.addEventListener('DOMContentLoaded',i,false);window.addEventListener('load',i,false);}else if(document.attachEvent){document.attachEvent('onreadystatechange',i);window.attachEvent('onload',i);}if(document.documentElement.doScroll&&window==window.top){var k=function(){try{document.documentElement.doScroll('left');}catch(l){setTimeout(k,0);return;}i();};k();}}e.exports=j;},3);
+ __d("Log",["sprintf"],function(a,b,c,d,e,f,g){var h={DEBUG:3,INFO:2,WARNING:1,ERROR:0};function i(k,l){var m=Array.prototype.slice.call(arguments,2),n=g.apply(null,m),o=window.console;if(o&&j.level>=l)o[k in o?k:'log'](n);}var j={level:-1,Level:h,debug:ES(i,'bind',true,null,'debug',h.DEBUG),info:ES(i,'bind',true,null,'info',h.INFO),warn:ES(i,'bind',true,null,'warn',h.WARNING),error:ES(i,'bind',true,null,'error',h.ERROR)};e.exports=j;},null);
+ __d("sdk.Content",["sdk.domReady","Log","UserAgent_DEPRECATED"],function(a,b,c,d,e,f,g,h,i){var j,k,l={append:function(m,n){if(!n)if(!j){j=n=document.getElementById('fb-root');if(!n){h.warn('The "fb-root" div has not been created, auto-creating');j=n=document.createElement('div');n.id='fb-root';if(i.ie()||!document.body){g(function(){document.body.appendChild(n);});}else document.body.appendChild(n);}n.className+=' fb_reset';}else n=j;if(typeof m=='string'){var o=document.createElement('div');n.appendChild(o).innerHTML=m;return o;}else return n.appendChild(m);},appendHidden:function(m){if(!n){var n=document.createElement('div'),o=n.style;o.position='absolute';o.top='-10000px';o.width=o.height=0;n=l.append(n);}return l.append(m,n);},submitToTarget:function(m,n){var o=document.createElement('form');o.action=m.url;o.target=m.target;o.method=(n)?'GET':'POST';l.appendHidden(o);for(var p in m.params)if(m.params.hasOwnProperty(p)){var q=m.params[p];if(q!==null&&q!==undefined){var r=document.createElement('input');r.name=p;r.value=q;o.appendChild(r);}}o.submit();o.parentNode.removeChild(o);}};e.exports=l;},null);
+ __d("dotAccess",[],function(a,b,c,d,e,f){function g(h,i,j){var k=i.split('.');do{var l=k.shift();h=h[l]||j&&(h[l]={});}while(k.length&&h);return h;}e.exports=g;},null);
+ __d("GlobalCallback",["DOMWrapper","dotAccess","guid","wrapFunction"],function(a,b,c,d,e,f,g,h,i,j){var k,l,m={setPrefix:function(n){k=h(g.getWindow(),n,true);l=n;},create:function(n,o){if(!k)this.setPrefix('__globalCallbacks');var p=i();k[p]=j(n,'entry',o||'GlobalCallback');return l+'.'+p;},remove:function(n){var o=n.substring(l.length+1);delete k[o];}};e.exports=m;},null);
+ __d("insertIframe",["guid","GlobalCallback"],function(a,b,c,d,e,f,g,h){function i(j){j.id=j.id||g();j.name=j.name||g();var k=false,l=false,m=function(){if(k&&!l){l=true;j.onload&&j.onload(j.root.firstChild);}},n=h.create(m);if(document.attachEvent){var o=('');j.root.innerHTML=('');k=true;setTimeout(function(){j.root.innerHTML=o;j.root.firstChild.src=j.url;j.onInsert&&j.onInsert(j.root.firstChild);},0);}else{var p=document.createElement('iframe');p.id=j.id;p.name=j.name;p.onload=m;p.scrolling='no';p.style.border='none';p.style.overflow='hidden';if(j.title)p.title=j.title;if(j.className)p.className=j.className;if(j.height!==undefined)p.style.height=j.height+'px';if(j.width!==undefined)if(j.width=='100%'){p.style.width=j.width;}else p.style.width=j.width+'px';j.root.appendChild(p);k=true;p.src=j.url;j.onInsert&&j.onInsert(p);}}e.exports=i;},null);
+ __d("Miny",[],function(a,b,c,d,e,f){var g='Miny1',h={encode:[],decode:{}},i='wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'.split('');function j(n){for(var o=h.encode.length;o2000)if(p.payload&&typeof p.payload==='string'){var t=j.encode(p.payload);if(t&&t.length>>18),g.charCodeAt((l>>>12)&63),g.charCodeAt((l>>>6)&63),g.charCodeAt(l&63));}var i='>___?456789:;<=_______'+'\0\1\2\3\4\5\6\7\b\t\n\13\f\r\16\17\20\21\22\23\24\25\26\27\30\31'+'______\32\33\34\35\36\37 !"#$%&\'()*+,-./0123';function j(l){l=(i.charCodeAt(l.charCodeAt(0)-43)<<18)|(i.charCodeAt(l.charCodeAt(1)-43)<<12)|(i.charCodeAt(l.charCodeAt(2)-43)<<6)|i.charCodeAt(l.charCodeAt(3)-43);return String.fromCharCode(l>>>16,(l>>>8)&255,l&255);}var k={encode:function(l){l=unescape(encodeURI(l));var m=(l.length+2)%3;l=(l+'\0\0'.slice(m)).replace(/[\s\S]{3}/g,h);return l.slice(0,l.length+m-2)+'=='.slice(m);},decode:function(l){l=l.replace(/[^A-Za-z0-9+\/]/g,'');var m=(l.length+3)&3;l=(l+'AAA'.slice(m)).replace(/..../g,j);l=l.slice(0,l.length+m-3);try{return decodeURIComponent(escape(l));}catch(n){throw new Error('Not valid UTF-8');}},encodeObject:function(l){return k.encode(ES('JSON','stringify',false,l));},decodeObject:function(l){return ES('JSON','parse',false,k.decode(l));},encodeNums:function(l){return String.fromCharCode.apply(String,ES(l,'map',true,function(m){return g.charCodeAt((m|-(m>63))&-(m>0)&63);}));}};e.exports=k;},null);
+ __d("sdk.SignedRequest",["Base64"],function(a,b,c,d,e,f,g){function h(j){if(!j)return null;var k=j.split('.',2)[1].replace(/\-/g,'+').replace(/\_/g,'/');return g.decodeObject(k);}var i={parse:h};e.exports=i;},null);
+ __d("URIRFC3986",[],function(a,b,c,d,e,f){var g=new RegExp('^'+'([^:/?#]+:)?'+'(//'+'([^\\\\/?#@]*@)?'+'('+'\\[[A-Fa-f0-9:.]+\\]|'+'[^\\/?#:]*'+')'+'(:[0-9]*)?'+')?'+'([^?#]*)'+'(\\?[^#]*)?'+'(#.*)?'),h={parse:function(i){if(ES(i,'trim',true)==='')return null;var j=i.match(g),k={};k.uri=j[0]?j[0]:null;k.scheme=j[1]?j[1].substr(0,j[1].length-1):null;k.authority=j[2]?j[2].substr(2):null;k.userinfo=j[3]?j[3].substr(0,j[3].length-1):null;k.host=j[2]?j[4]:null;k.port=j[5]?(j[5].substr(1)?parseInt(j[5].substr(1),10):null):null;k.path=j[6]?j[6]:null;k.query=j[7]?j[7].substr(1):null;k.fragment=j[8]?j[8].substr(1):null;k.isGenericURI=k.authority===null&&!!k.scheme;return k;}};e.exports=h;},null);
+ __d("createObjectFrom",[],function(a,b,c,d,e,f){function g(h,i){var j={},k=ES('Array','isArray',false,i);if(typeof i=='undefined')i=true;for(var l=h.length;l--;)j[h[l]]=k?i[l]:i;return j;}e.exports=g;},null);
+ __d("URISchemes",["createObjectFrom"],function(a,b,c,d,e,f,g){var h=g(['fb','fbcf','fbconnect','fb-messenger','fbrpc','file','ftp','http','https','mailto','ms-app','itms','itms-apps','itms-services','market','svn+ssh','fbstaging','tel','sms']),i={isAllowed:function(j){if(!j)return true;return h.hasOwnProperty(j.toLowerCase());}};e.exports=i;},null);
+ __d("copyProperties",[],function(a,b,c,d,e,f){function g(h,i,j,k,l,m,n){h=h||{};var o=[i,j,k,l,m],p=0,q;while(o[p]){q=o[p++];for(var r in q)h[r]=q[r];if(q.hasOwnProperty&&q.hasOwnProperty('toString')&&(typeof q.toString!='undefined')&&(h.toString!==q.toString))h.toString=q.toString;}return h;}e.exports=g;},null);
+ __d("eprintf",[],function(a,b,c,d,e,f){var g=function(h){var i=ES(Array.prototype.slice.call(arguments),'map',true,function(l){return String(l);}),j=h.split('%s').length-1;if(j!==i.length-1)return g('eprintf args number mismatch: %s',ES('JSON','stringify',false,i));var k=1;return h.replace(/%s/g,function(l){return String(i[k++]);});};e.exports=g;},null);
+ __d("ex",["eprintf"],function(a,b,c,d,e,f,g){var h=function(){var i=Array.prototype.slice.call(arguments,0);i=ES(i,'map',true,function(j){return String(j);});if(i[0].split('%s').length!==i.length)return h('ex args number mismatch: %s',ES('JSON','stringify',false,i));return h._prefix+ES('JSON','stringify',false,i)+h._suffix;};h._prefix='';e.exports=h;},null);
+ __d("invariant",[],function(a,b,c,d,e,f){"use strict";var g=function(h,i,j,k,l,m,n,o){if(!h){var p;if(i===undefined){p=new Error('Minified exception occurred; use the non-minified dev environment '+'for the full error message and additional helpful warnings.');}else{var q=[j,k,l,m,n,o],r=0;p=new Error('Invariant Violation: '+i.replace(/%s/g,function(){return q[r++];}));}p.framesToPop=1;throw p;}};e.exports=g;},null);
+ __d("URIBase",["URIRFC3986","URISchemes","copyProperties","ex","invariant"],function(a,b,c,d,e,f,g,h,i,j,k){var l=new RegExp('[\\x00-\\x2c\\x2f\\x3b-\\x40\\x5c\\x5e\\x60\\x7b-\\x7f'+'\\uFDD0-\\uFDEF\\uFFF0-\\uFFFF'+'\\u2047\\u2048\\uFE56\\uFE5F\\uFF03\\uFF0F\\uFF1F]'),m=new RegExp('^(?:[^/]*:|'+'[\\x00-\\x1f]*/[\\x00-\\x1f]*/)');function n(p,q,r,s){if(!q)return true;if(q instanceof o){p.setProtocol(q.getProtocol());p.setDomain(q.getDomain());p.setPort(q.getPort());p.setPath(q.getPath());p.setQueryData(s.deserialize(s.serialize(q.getQueryData())));p.setFragment(q.getFragment());p.setForceFragmentSeparator(q.getForceFragmentSeparator());return true;}q=ES(q.toString(),'trim',true);var t=g.parse(q)||{};if(!r&&!h.isAllowed(t.scheme))return false;p.setProtocol(t.scheme||'');if(!r&&l.test(t.host))return false;p.setDomain(t.host||'');p.setPort(t.port||'');p.setPath(t.path||'');if(r){p.setQueryData(s.deserialize(t.query)||{});}else try{p.setQueryData(s.deserialize(t.query)||{});}catch(u){return false;}p.setFragment(t.fragment||'');if(t.fragment==='')p.setForceFragmentSeparator(true);if(t.userinfo!==null)if(r){throw new Error(j('URI.parse: invalid URI (userinfo is not allowed in a URI): %s',p.toString()));}else return false;if(!p.getDomain()&&ES(p.getPath(),'indexOf',true,'\\')!==-1)if(r){throw new Error(j('URI.parse: invalid URI (no domain but multiple back-slashes): %s',p.toString()));}else return false;if(!p.getProtocol()&&m.test(q))if(r){throw new Error(j('URI.parse: invalid URI (unsafe protocol-relative URLs): %s',p.toString()));}else return false;return true;}function o(p,q){"use strict";k(q);this.$URIBase0=q;this.$URIBase1='';this.$URIBase2='';this.$URIBase3='';this.$URIBase4='';this.$URIBase5='';this.$URIBase6={};this.$URIBase7=false;n(this,p,true,q);}o.prototype.setProtocol=function(p){"use strict";k(h.isAllowed(p));this.$URIBase1=p;return this;};o.prototype.getProtocol=function(p){"use strict";return this.$URIBase1;};o.prototype.setSecure=function(p){"use strict";return this.setProtocol(p?'https':'http');};o.prototype.isSecure=function(){"use strict";return this.getProtocol()==='https';};o.prototype.setDomain=function(p){"use strict";if(l.test(p))throw new Error(j('URI.setDomain: unsafe domain specified: %s for url %s',p,this.toString()));this.$URIBase2=p;return this;};o.prototype.getDomain=function(){"use strict";return this.$URIBase2;};o.prototype.setPort=function(p){"use strict";this.$URIBase3=p;return this;};o.prototype.getPort=function(){"use strict";return this.$URIBase3;};o.prototype.setPath=function(p){"use strict";this.$URIBase4=p;return this;};o.prototype.getPath=function(){"use strict";return this.$URIBase4;};o.prototype.addQueryData=function(p,q){"use strict";if(Object.prototype.toString.call(p)==='[object Object]'){i(this.$URIBase6,p);}else this.$URIBase6[p]=q;return this;};o.prototype.setQueryData=function(p){"use strict";this.$URIBase6=p;return this;};o.prototype.getQueryData=function(){"use strict";return this.$URIBase6;};o.prototype.removeQueryData=function(p){"use strict";if(!ES('Array','isArray',false,p))p=[p];for(var q=0,r=p.length;q0||this.getFragment());};o.prototype.toString=function(){"use strict";var p='';if(this.$URIBase1)p+=this.$URIBase1+'://';if(this.$URIBase2)p+=this.$URIBase2;if(this.$URIBase3)p+=':'+this.$URIBase3;if(this.$URIBase4){p+=this.$URIBase4;}else if(p)p+='/';var q=this.$URIBase0.serialize(this.$URIBase6);if(q)p+='?'+q;if(this.$URIBase5){p+='#'+this.$URIBase5;}else if(this.$URIBase7)p+='#';return p;};o.prototype.getOrigin=function(){"use strict";return this.$URIBase1+'://'+this.$URIBase2+(this.$URIBase3?':'+this.$URIBase3:'');};o.isValidURI=function(p,q){return n(new o(null,q),p,false,q);};e.exports=o;},null);
+ __d("sdk.URI",["Assert","QueryString","URIBase"],function(a,b,c,d,e,f,g,h,i){var j=/\.facebook\.com$/,k={serialize:function(o){return o?h.encode(o):'';},deserialize:function(o){return o?h.decode(o):{};}};for(var l in i)if(i.hasOwnProperty(l))n[l]=i[l];var m=i===null?null:i.prototype;n.prototype=ES('Object','create',false,m);n.prototype.constructor=n;n.__superConstructor__=i;function n(o){"use strict";g.isString(o,'The passed argument was of invalid type.');if(!(this instanceof n))return new n(o);i.call(this,o,k);}n.prototype.isFacebookURI=function(){"use strict";return j.test(this.getDomain());};n.prototype.valueOf=function(){"use strict";return this.toString();};e.exports=n;},null);
+ __d("sdk.Event",[],function(a,b,c,d,e,f){var g={SUBSCRIBE:'event.subscribe',UNSUBSCRIBE:'event.unsubscribe',subscribers:function(){if(!this._subscribersMap)this._subscribersMap={};return this._subscribersMap;},subscribe:function(h,i){var j=this.subscribers();if(!j[h]){j[h]=[i];}else if(ES(j[h],'indexOf',true,i)==-1)j[h].push(i);if(h!=this.SUBSCRIBE&&h!=this.UNSUBSCRIBE)this.fire(this.SUBSCRIBE,h,j[h]);},unsubscribe:function(h,i){var j=this.subscribers()[h];if(j)ES(j,'forEach',true,function(k,l){if(k==i)j.splice(l,1);});if(h!=this.SUBSCRIBE&&h!=this.UNSUBSCRIBE)this.fire(this.UNSUBSCRIBE,h,j);},monitor:function(h,i){if(!i()){var j=this,k=function(){if(i.apply(i,arguments))j.unsubscribe(h,k);};this.subscribe(h,k);}},clear:function(h){delete this.subscribers()[h];},fire:function(h){var i=Array.prototype.slice.call(arguments,1),j=this.subscribers()[h];if(j)ES(j,'forEach',true,function(k){if(k)k.apply(this,i);});}};e.exports=g;},null);
+ __d("Queue",["copyProperties"],function(a,b,c,d,e,f,g){var h={};function i(j){"use strict";this._opts=g({interval:0,processor:null},j);this._queue=[];this._stopped=true;}i.prototype._dispatch=function(j){"use strict";if(this._stopped||this._queue.length===0)return;if(!this._opts.processor){this._stopped=true;throw new Error('No processor available');}if(this._opts.interval){this._opts.processor.call(this,this._queue.shift());this._timeout=setTimeout(ES(this._dispatch,'bind',true,this),this._opts.interval);}else while(this._queue.length)this._opts.processor.call(this,this._queue.shift());};i.prototype.enqueue=function(j){"use strict";if(this._opts.processor&&!this._stopped){this._opts.processor.call(this,j);}else this._queue.push(j);return this;};i.prototype.start=function(j){"use strict";if(j)this._opts.processor=j;this._stopped=false;this._dispatch();return this;};i.prototype.isStarted=function(){"use strict";return !this._stopped;};i.prototype.dispatch=function(){"use strict";this._dispatch(true);};i.prototype.stop=function(j){"use strict";this._stopped=true;if(j)clearTimeout(this._timeout);return this;};i.prototype.merge=function(j,k){"use strict";this._queue[k?'unshift':'push'].apply(this._queue,j._queue);j._queue=[];this._dispatch();return this;};i.prototype.getLength=function(){"use strict";return this._queue.length;};i.get=function(j,k){"use strict";var l;if(j in h){l=h[j];}else l=h[j]=new i(k);return l;};i.exists=function(j){"use strict";return j in h;};i.remove=function(j){"use strict";return delete h[j];};e.exports=i;},null);
+ __d("JSONRPC",["Log"],function(a,b,c,d,e,f,g){function h(i){"use strict";this.$JSONRPC0=0;this.$JSONRPC1={};this.remote=ES(function(j){this.$JSONRPC2=j;return this.remote;},'bind',true,this);this.local={};this.$JSONRPC3=i;}h.prototype.stub=function(i){"use strict";this.remote[i]=ES(function(){var j=Array.prototype.slice.call(arguments,0),k={jsonrpc:'2.0',method:i};if(typeof j[j.length-1]=='function'){k.id=++this.$JSONRPC0;this.$JSONRPC1[k.id]=j.pop();}k.params=j;this.$JSONRPC3(ES('JSON','stringify',false,k),this.$JSONRPC2||{method:i});},'bind',true,this);};h.prototype.read=function(i,j){"use strict";var k=ES('JSON','parse',false,i),l=k.id;if(!k.method){if(!this.$JSONRPC1[l]){g.warn('Could not find callback %s',l);return;}var m=this.$JSONRPC1[l];delete this.$JSONRPC1[l];delete k.id;delete k.jsonrpc;m(k);return;}var n=this,o=this.local[k.method],p;if(l){p=function(s,t){var u={jsonrpc:'2.0',id:l};u[s]=t;setTimeout(function(){n.$JSONRPC3(ES('JSON','stringify',false,u),j);},0);};}else p=function(){};if(!o){g.error('Method "%s" has not been defined',k.method);p('error',{code:-32601,message:'Method not found',data:k.method});return;}k.params.push(ES(p,'bind',true,null,'result'));k.params.push(ES(p,'bind',true,null,'error'));try{var r=o.apply(j||null,k.params);if(typeof r!=='undefined')p('result',r);}catch(q){g.error('Invokation of RPC method %s resulted in the error: %s',k.method,q.message);p('error',{code:-32603,message:'Internal error',data:q.message});}};e.exports=h;},null);
+ __d("sdk.RPC",["Assert","JSONRPC","Queue"],function(a,b,c,d,e,f,g,h,i){var j=new i(),k=new h(function(m){j.enqueue(m);}),l={local:k.local,remote:k.remote,stub:ES(k.stub,'bind',true,k),setInQueue:function(m){g.isInstanceOf(i,m);m.start(function(n){k.read(n);});},getOutQueue:function(){return j;}};e.exports=l;},null);
+ __d("sdk.Scribe",["QueryString","sdk.Runtime","UrlMap"],function(a,b,c,d,e,f,g,h,i){function j(l,m){if(typeof m.extra=='object')m.extra.revision=h.getRevision();(new Image()).src=g.appendToUrl(i.resolve('www',true)+'/common/scribe_endpoint.php',{c:l,m:ES('JSON','stringify',false,m)});}var k={log:j};e.exports=k;},null);
+ __d("emptyFunction",["copyProperties"],function(a,b,c,d,e,f,g){function h(j){return function(){return j;};}function i(){}g(i,{thatReturns:h,thatReturnsFalse:h(false),thatReturnsTrue:h(true),thatReturnsNull:h(null),thatReturnsThis:function(){return this;},thatReturnsArgument:function(j){return j;}});e.exports=i;},null);
+ __d("htmlSpecialChars",[],function(a,b,c,d,e,f){var g=/&/g,h=//g,j=/"/g,k=/'/g;function l(m){if(typeof m=='undefined'||m===null||!m.toString)return '';if(m===false){return '0';}else if(m===true)return '1';return m.toString().replace(g,'&').replace(j,'"').replace(k,''').replace(h,'<').replace(i,'>');}e.exports=l;},null);
+ __d("Flash",["DOMEventListener","DOMWrapper","QueryString","UserAgent_DEPRECATED","copyProperties","guid","htmlSpecialChars"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){var n={},o,p=h.getWindow().document;function q(v){var w=p.getElementById(v);if(w)w.parentNode.removeChild(w);delete n[v];}function r(){for(var v in n)if(n.hasOwnProperty(v))q(v);}function s(v){return v.replace(/\d+/g,function(w){return '000'.substring(w.length)+w;});}function t(v){if(!o){if(j.ie()>=9)g.add(window,'unload',r);o=true;}n[v]=v;}var u={embed:function(v,w,x,y){var z=l();v=m(v).replace(/&/g,'&');x=k({allowscriptaccess:'always',flashvars:y,movie:v},x||{});if(typeof x.flashvars=='object')x.flashvars=i.encode(x.flashvars);var aa=[];for(var ba in x)if(x.hasOwnProperty(ba)&&x[ba])aa.push(' ');var ca=w.appendChild(p.createElement('span')),da=''+aa.join('')+' ';ca.innerHTML=da;var ea=ca.firstChild;t(z);return ea;},remove:q,getVersion:function(){var v='Shockwave Flash',w='application/x-shockwave-flash',x='ShockwaveFlash.ShockwaveFlash',y;if(navigator.plugins&&typeof navigator.plugins[v]=='object'){var z=navigator.plugins[v].description;if(z&&navigator.mimeTypes&&navigator.mimeTypes[w]&&navigator.mimeTypes[w].enabledPlugin)y=z.match(/\d+/g);}if(!y)try{y=(new ActiveXObject(x)).GetVariable('$version').match(/(\d+),(\d+),(\d+),(\d+)/);y=Array.prototype.slice.call(y,1);}catch(aa){}return y;},checkMinVersion:function(v){var w=u.getVersion();if(!w)return false;return s(w.join('.'))>=s(v);},isAvailable:function(){return !!u.getVersion();}};e.exports=u;},null);
+ __d("XDM",["DOMEventListener","DOMWrapper","emptyFunction","Flash","GlobalCallback","guid","Log","UserAgent_DEPRECATED","wrapFunction"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p={},q={transports:[]},r=h.getWindow();function s(u){var v={},w=u.length,x=q.transports;while(w--)v[u[w]]=1;w=x.length;while(w--){var y=x[w],z=p[y];if(!v[y]&&z.isAvailable())return y;}}var t={register:function(u,v){m.debug('Registering %s as XDM provider',u);q.transports.push(u);p[u]=v;},create:function(u){if(!u.whenReady&&!u.onMessage){m.error('An instance without whenReady or onMessage makes no sense');throw new Error('An instance without whenReady or '+'onMessage makes no sense');}if(!u.channel){m.warn('Missing channel name, selecting at random');u.channel=l();}if(!u.whenReady)u.whenReady=i;if(!u.onMessage)u.onMessage=i;var v=u.transport||s(u.blacklist||[]),w=p[v];if(w&&w.isAvailable()){m.debug('%s is available',v);w.init(u);return v;}}};t.register('flash',(function(){var u=false,v,w=false,x=15000,y;return {isAvailable:function(){return j.checkMinVersion('8.0.24');},init:function(z){m.debug('init flash: '+z.channel);var aa={send:function(da,ea,fa,ga){m.debug('sending to: %s (%s)',ea,ga);v.postMessage(da,ea,ga);}};if(u){z.whenReady(aa);return;}var ba=z.root.appendChild(r.document.createElement('div')),ca=k.create(function(){k.remove(ca);clearTimeout(y);m.info('xdm.swf called the callback');var da=k.create(function(ea,fa){ea=decodeURIComponent(ea);fa=decodeURIComponent(fa);m.debug('received message %s from %s',ea,fa);z.onMessage(ea,fa);},'xdm.swf:onMessage');v.init(z.channel,da);z.whenReady(aa);},'xdm.swf:load');v=j.embed(z.flashUrl,ba,null,{protocol:location.protocol.replace(':',''),host:location.host,callback:ca,log:w});y=setTimeout(function(){m.warn('The Flash component did not load within %s ms - '+'verify that the container is not set to hidden or invisible '+'using CSS as this will cause some browsers to not load '+'the components',x);},x);u=true;}};})());t.register('postmessage',(function(){var u=false;return {isAvailable:function(){return !!r.postMessage;},init:function(v){m.debug('init postMessage: '+v.channel);var w='_FB_'+v.channel,x={send:function(y,z,aa,ba){if(r===aa){m.error('Invalid windowref, equal to window (self)');throw new Error();}m.debug('sending to: %s (%s)',z,ba);var ca=function(){aa.postMessage('_FB_'+ba+y,z);};if(n.ie()==8||n.ieCompatibilityMode()){setTimeout(ca,0);}else ca();}};if(u){v.whenReady(x);return;}g.add(r,'message',o(function(event){var y=event.data,z=event.origin||'native';if(!/^(https?:\/\/|native$)/.test(z)){m.debug('Received message from invalid origin type: %s',z);return;}if(typeof y!='string'){m.warn('Received message of type %s from %s, expected a string',typeof y,z);return;}m.debug('received message %s from %s',y,z);if(y.substring(0,w.length)==w)y=y.substring(w.length);v.onMessage(y,z);},'entry','onMessage'));v.whenReady(x);u=true;}};})());e.exports=t;},null);
+ __d("isFacebookURI",[],function(a,b,c,d,e,f){var g=null,h=['http','https'];function i(j){if(!g)g=new RegExp('(^|\\.)facebook\\.com$','i');if(j.isEmpty())return false;if(!j.getDomain()&&!j.getProtocol())return true;return (ES(h,'indexOf',true,j.getProtocol())!==-1&&g.test(j.getDomain()));}e.exports=i;},null);
+ __d("sdk.XD",["sdk.Content","sdk.Event","Log","QueryString","Queue","sdk.RPC","sdk.Runtime","sdk.Scribe","sdk.URI","UrlMap","JSSDKXDConfig","XDM","isFacebookURI","sdk.createIframe","sdk.feature","guid"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v){var w=new k(),x=new k(),y=new k(),z,aa,ba=v(),ca=q.useCdn?'cdn':'www',da=u('use_bundle')?q.XdBundleUrl:q.XdUrl,ea=p.resolve(ca,false)+da,fa=p.resolve(ca,true)+da,ga=v(),ha=location.protocol+'//'+location.host,ia,ja=false,ka='Facebook Cross Domain Communication Frame',la={},ma=new k();l.setInQueue(ma);function na(ta){i.info('Remote XD can talk to facebook.com (%s)',ta);m.setEnvironment(ta==='canvas'?m.ENVIRONMENTS.CANVAS:m.ENVIRONMENTS.PAGETAB);}function oa(ta,ua){if(!ua){i.error('No senderOrigin');throw new Error();}var va=/^https?/.exec(ua)[0];switch(ta.xd_action){case 'proxy_ready':var wa,xa;if(va=='https'){wa=y;xa=aa;}else{wa=x;xa=z;}if(ta.registered){na(ta.registered);w=wa.merge(w);}i.info('Proxy ready, starting queue %s containing %s messages',va+'ProxyQueue',wa.getLength());wa.start(function(za){ia.send(typeof za==='string'?za:j.encode(za),ua,xa.contentWindow,ga+'_'+va);});break;case 'plugin_ready':i.info('Plugin %s ready, protocol: %s',ta.name,va);la[ta.name]={protocol:va};if(k.exists(ta.name)){var ya=k.get(ta.name);i.debug('Enqueuing %s messages for %s in %s',ya.getLength(),ta.name,va+'ProxyQueue');(va=='https'?y:x).merge(ya);}break;}if(ta.data)pa(ta.data,ua);}function pa(ta,ua){if(ua&&ua!=='native'&&!s(o(ua)))return;if(typeof ta=='string'){if(/^FB_RPC:/.test(ta)){ma.enqueue(ta.substring(7));return;}if(ta.substring(0,1)=='{'){try{ta=ES('JSON','parse',false,ta);}catch(va){i.warn('Failed to decode %s as JSON',ta);return;}}else ta=j.decode(ta);}if(!ua)if(ta.xd_sig==ba)ua=ta.xd_origin;if(ta.xd_action){oa(ta,ua);return;}if(ta.access_token)m.setSecure(/^https/.test(ha));if(ta.cb){var wa=sa._callbacks[ta.cb];if(!sa._forever[ta.cb])delete sa._callbacks[ta.cb];if(wa)wa(ta);}}function qa(ta,ua){if(ta=='facebook'){ua.relation='parent.parent';w.enqueue(ua);}else{ua.relation='parent.frames["'+ta+'"]';var va=la[ta];if(va){i.debug('Enqueuing message for plugin %s in %s',ta,va.protocol+'ProxyQueue');(va.protocol=='https'?y:x).enqueue(ua);}else{i.debug('Buffering message for plugin %s',ta);k.get(ta).enqueue(ua);}}}l.getOutQueue().start(function(ta){qa('facebook','FB_RPC:'+ta);});function ra(ta){if(ja)return;var ua=g.appendHidden(document.createElement('div')),va=r.create({blacklist:null,root:ua,channel:ga,flashUrl:q.Flash.path,whenReady:function(wa){ia=wa;var xa={channel:ga,origin:location.protocol+'//'+location.host,transport:va,xd_name:ta},ya='#'+j.encode(xa);if(m.getSecure()!==true)z=t({url:ea+ya,name:'fb_xdm_frame_http',id:'fb_xdm_frame_http',root:ua,'aria-hidden':true,title:ka,tabindex:-1});aa=t({url:fa+ya,name:'fb_xdm_frame_https',id:'fb_xdm_frame_https',root:ua,'aria-hidden':true,title:ka,tabindex:-1});},onMessage:pa});if(!va)n.log('jssdk_error',{appId:m.getClientID(),error:'XD_TRANSPORT',extra:{message:'Failed to create a valid transport'}});ja=true;}var sa={rpc:l,_callbacks:{},_forever:{},_channel:ga,_origin:ha,onMessage:pa,recv:pa,init:ra,sendToFacebook:qa,inform:function(ta,ua,va,wa){qa('facebook',{method:ta,params:ES('JSON','stringify',false,ua||{}),behavior:wa||'p',relation:va});},handler:function(ta,ua,va,wa){var xa='#'+j.encode({cb:this.registerCallback(ta,va,wa),origin:ha+'/'+ga,domain:location.hostname,relation:ua||'opener'});return (location.protocol=='https:'?fa:ea)+xa;},registerCallback:function(ta,ua,va){va=va||v();if(ua)sa._forever[va]=true;sa._callbacks[va]=ta;return va;}};h.subscribe('init:post',function(ta){ra(ta.xdProxyName);var ua=u('xd_timeout');if(ua)setTimeout(function(){var va=aa&&(!!z==x.isStarted()&&!!aa==y.isStarted());if(!va)n.log('jssdk_error',{appId:m.getClientID(),error:'XD_INITIALIZATION',extra:{message:'Failed to initialize in '+ua+'ms'}});},ua);});e.exports=sa;},null);
+ __d("sdk.Auth",["sdk.Cookie","sdk.createIframe","DOMWrapper","sdk.feature","sdk.getContextType","guid","sdk.Impressions","Log","ObservableMixin","sdk.Runtime","sdk.SignedRequest","UrlMap","sdk.URI","sdk.XD"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t){var u,v,w=new o();function x(da,ea){var fa=p.getUserID(),ga='';if(da)if(da.userID){ga=da.userID;}else if(da.signedRequest){var ha=q.parse(da.signedRequest);if(ha&&ha.user_id)ga=ha.user_id;}var ia=p.getLoginStatus(),ja=(ia==='unknown'&&da)||(p.getUseCookie()&&p.getCookieUserID()!==ga),ka=fa&&!da,la=da&&fa&&fa!=ga,ma=da!=u,na=ea!=(ia||'unknown');p.setLoginStatus(ea);p.setAccessToken(da&&da.accessToken||null);p.setUserID(ga);u=da;var oa={authResponse:da,status:ea};if(ka||la)w.inform('logout',oa);if(ja||la)w.inform('login',oa);if(ma)w.inform('authresponse.change',oa);if(na)w.inform('status.change',oa);return oa;}function y(){return u;}function z(da,ea,fa){return function(ga){var ha;if(ga&&ga.access_token){var ia=q.parse(ga.signed_request);ea={accessToken:ga.access_token,userID:ia.user_id,expiresIn:parseInt(ga.expires_in,10),signedRequest:ga.signed_request};if(ga.granted_scopes)ea.grantedScopes=ga.granted_scopes;if(p.getUseCookie()){var ja=ea.expiresIn===0?0:ES('Date','now',false)+ea.expiresIn*1000,ka=g.getDomain();if(!ka&&ga.base_domain)g.setDomain('.'+ga.base_domain);g.setSignedRequestCookie(ga.signed_request,ja);}ha='connected';x(ea,ha);}else if(fa==='logout'||fa==='login_status'){if(ga.error&&ga.error==='not_authorized'){ha='not_authorized';}else ha='unknown';x(null,ha);if(p.getUseCookie())g.clearSignedRequestCookie();}if(ga&&ga.https==1)p.setSecure(true);if(da)da({authResponse:ea,status:p.getLoginStatus()});return ea;};}function aa(da){var ea,fa=ES('Date','now',false);if(v){clearTimeout(v);v=null;}var ga=z(da,u,'login_status'),ha=s(r.resolve('www',true)+'/connect/ping').setQueryData({client_id:p.getClientID(),response_type:'token,signed_request,code',domain:location.hostname,origin:k(),redirect_uri:t.handler(function(ia){if(j('e2e_ping_tracking',true)){var ja={init:fa,close:ES('Date','now',false),method:'ping'};n.debug('e2e: %s',ES('JSON','stringify',false,ja));m.log(114,{payload:ja});}ea.parentNode.removeChild(ea);if(ga(ia))v=setTimeout(function(){aa(function(){});},1200000);},'parent'),sdk:'joey',kid_directed_site:p.getKidDirectedSite()});ea=h({root:i.getRoot(),name:l(),url:ha.toString(),style:{display:'none'}});}var ba;function ca(da,ea){if(!p.getClientID()){n.warn('FB.getLoginStatus() called before calling FB.init().');return;}if(da)if(!ea&&ba=='loaded'){da({status:p.getLoginStatus(),authResponse:y()});return;}else w.subscribe('FB.loginStatus',da);if(!ea&&ba=='loading')return;ba='loading';var fa=function(ga){ba='loaded';w.inform('FB.loginStatus',ga);w.clearSubscribers('FB.loginStatus');};aa(fa);}ES('Object','assign',false,w,{getLoginStatus:ca,fetchLoginStatus:aa,setAuthResponse:x,getAuthResponse:y,parseSignedRequest:q.parse,xdResponseWrapper:z});e.exports=w;},null);
+ __d("toArray",["invariant"],function(a,b,c,d,e,f,g){function h(i){var j=i.length;g(!ES('Array','isArray',false,i)&&(typeof i==='object'||typeof i==='function'));g(typeof j==='number');g(j===0||(j-1) in i);if(i.hasOwnProperty)try{return Array.prototype.slice.call(i);}catch(k){}var l=Array(j);for(var m=0;m=0;}function q(z,aa){g.isTruthy(z,'element not specified');g.isString(aa);if(!p(z,aa))z.className=n(z,'className')+' '+aa;}function r(z,aa){g.isTruthy(z,'element not specified');g.isString(aa);var ba=new RegExp('\\s*'+aa,'g');z.className=ES(n(z,'className').replace(ba,''),'trim',true);}function s(z,aa,ba){g.isString(z);aa=aa||document.body;ba=ba||'*';if(aa.querySelectorAll)return h(aa.querySelectorAll(ba+'.'+z));var ca=aa.getElementsByTagName(ba),da=[];for(var ea=0,fa=ca.length;ea2000){h.remove(n.callback);return false;}p.onerror=function(){q({error:{type:'http',message:'unknown error'}});};var r=function(){setTimeout(function(){q({error:{type:'http',message:'unknown error'}});},0);};if(p.addEventListener){p.addEventListener('load',r,false);}else p.onreadystatechange=function(){if(/loaded|complete/.test(this.readyState))r();};p.src=l;g.getRoot().appendChild(p);return true;}var k={execute:j};e.exports=k;},null);
+ __d("ApiClient",["ArgumentError","Assert","CORSRequest","FlashRequest","flattenObject","JSONPRequest","Log","ObservableMixin","sprintf","sdk.URI","UrlMap","ApiClientConfig","invariant"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s){var t,u,v,w={get:true,post:true,'delete':true,put:true},x={fql_query:true,fql_multiquery:true,friends_get:true,notifications_get:true,stream_get:true,users_getinfo:true},y=[],z=[],aa=null,ba=50,ca=105440539523;function da(la,ma,na,oa){if(v)na=ES('Object','assign',false,{},v,na);na.access_token=na.access_token||t;na.pretty=na.pretty||0;na=k(na);var pa={jsonp:l,cors:i,flash:j},qa;if(na.transport){qa=[na.transport];delete na.transport;}else qa=['jsonp','cors','flash'];for(var ra=0;ra0);var la=y,ma=z;y=[];z=[];aa=null;ga('/','POST',{batch:ES('JSON','stringify',false,la),include_headers:false,batch_app_id:u||ca},function(na){if(ES('Array','isArray',false,na)){ES(na,'forEach',true,function(oa,pa){ma[pa](ES('JSON','parse',false,oa.body));});}else ES(ma,'forEach',true,function(oa){return oa({error:{message:'Fatal: batch call failed.'}});});});}function ja(la,ma){h.isObject(la);h.isString(la.method,'method missing');if(!ma)m.warn('No callback passed to the ApiClient');var na=la.method.toLowerCase().replace('.','_');la.format='json-strings';la.api_key=u;var oa=na in x?'api_read':'api',pa=q.resolve(oa)+'/restserver.php',qa=ES(ea,'bind',true,null,ma,'/restserver.php','get',la);da(pa,'get',la,qa);}var ka=ES('Object','assign',false,new n(),{setAccessToken:function(la){t=la;},setClientID:function(la){u=la;},setDefaultParams:function(la){v=la;},rest:ja,graph:ga,scheduleBatchCall:ha});j.setSwfUrl(r.FlashRequest.swfUrl);e.exports=ka;},null);
+ __d("sdk.PlatformVersioning",["sdk.Runtime","ManagedError"],function(a,b,c,d,e,f,g,h){var i=/^v\d+\.\d\d?$/,j={REGEX:i,assertVersionIsSet:function(){if(!g.getVersion())throw new h('init not called with valid version');},assertValidVersion:function(k){if(!i.test(k))throw new h('invalid version specified');}};e.exports=j;},null);
+ __d("sdk.api",["ApiClient","sdk.PlatformVersioning","sdk.Runtime","sdk.URI"],function(a,b,c,d,e,f,g,h,i,j){var k;i.subscribe('ClientID.change',function(m){g.setClientID(m);});i.subscribe('AccessToken.change',function(m){k=m;g.setAccessToken(m);});g.setDefaultParams({sdk:'joey'});g.subscribe('request.complete',function(m,n,o,p){var q=false;if(p&&typeof p=='object')if(p.error){if(p.error=='invalid_token'||(p.error.type=='OAuthException'&&p.error.code==190))q=true;}else if(p.error_code)if(p.error_code=='190')q=true;if(q&&k===i.getAccessToken())i.setAccessToken(null);});g.subscribe('request.complete',function(m,n,o,p){if(((m=='/me/permissions'&&n==='delete')||(m=='/restserver.php'&&o.method=='Auth.revokeAuthorization'))&&p===true)i.setAccessToken(null);});function l(m){if(typeof m==='string'){if(i.getIsVersioned()){h.assertVersionIsSet();if(!/https?/.test(m)&&m.charAt(0)!=='/')m='/'+m;m=j(m).setDomain(null).setProtocol(null).toString();if(!h.REGEX.test(m.substring(1,ES(m,'indexOf',true,'/',1))))m='/'+i.getVersion()+m;var n=[m].concat(Array.prototype.slice.call(arguments,1));g.graph.apply(g,n);}else g.graph.apply(g,arguments);}else g.rest.apply(g,arguments);}e.exports=l;},null);
+ __d("legacy:fb.api",["FB","sdk.api"],function(a,b,c,d,e,f,g,h){g.provide('',{api:h});},3);
+ __d("merge",[],function(a,b,c,d,e,f){"use strict";var g=function(h,i){return ES('Object','assign',false,{},h,i);};e.exports=g;},null);
+ __d("sdk.AppEvents",["Assert","sdk.Impressions","merge","sdk.Runtime"],function(a,b,c,d,e,f,g,h,i,j){var k={COMPLETED_REGISTRATION:'fb_mobile_complete_registration',VIEWED_CONTENT:'fb_mobile_content_view',SEARCHED:'fb_mobile_search',RATED:'fb_mobile_rate',COMPLETED_TUTORIAL:'fb_mobile_tutorial_completion',ADDED_TO_CART:'fb_mobile_add_to_cart',ADDED_TO_WISHLIST:'fb_mobile_add_to_wishlist',INITIATED_CHECKOUT:'fb_mobile_initiated_checkout',ADDED_PAYMENT_INFO:'fb_mobile_add_payment_info',ACHIEVED_LEVEL:'fb_mobile_level_achieved',UNLOCKED_ACHIEVEMENT:'fb_mobile_achievement_unlocked',SPENT_CREDITS:'fb_mobile_spent_credits'},l={ACTIVATED_APP:'fb_mobile_activate_app',PURCHASED:'fb_mobile_purchase'},m={CURRENCY:'fb_currency',REGISTRATION_METHOD:'fb_registration_method',CONTENT_TYPE:'fb_content_type',CONTENT_ID:'fb_content_id',SEARCH_STRING:'fb_search_string',SUCCESS:'fb_success',MAX_RATING_VALUE:'fb_max_rating_value',PAYMENT_INFO_AVAILABLE:'fb_payment_info_available',NUM_ITEMS:'fb_num_items',LEVEL:'fb_level',DESCRIPTION:'fb_description'},n=40,o='^[0-9a-zA-Z_]+[0-9a-zA-Z _-]*$';function p(t,u,v,w){g.isTrue(q(u),'Invalid event name: '+u+'. '+'It must be between 1 and '+n+' characters, '+'and must be contain only alphanumerics, _, - or spaces, '+'starting with alphanumeric or _.');var x={ae:1,ev:u,vts:v,canvas:j.isCanvasEnvironment()?1:0};if(w)x.cd=w;h.impression({api_key:t,payload:ES('JSON','stringify',false,x)});}function q(t){if(t===null||t.length===0||t.length>n||!(new RegExp(o)).test(t))return false;return true;}function r(t,u,v,w){var x={};x[m.CURRENCY]=v;p(t,l.PURCHASED,u,i(w,x));}function s(t){p(t,l.ACTIVATED_APP);}e.exports={activateApp:s,logEvent:p,logPurchase:r,isValidEventName:q,EventNames:k,ParameterNames:m};},null);
+ __d("legacy:fb.appevents",["Assert","sdk.AppEvents","FB","sdk.feature","sdk.Runtime"],function(a,b,c,d,e,f,g,h,i,j,k){i.provide('AppEvents',{logEvent:function(l,m,n){g.isTrue(j('allow_non_canvas_app_events')||k.isCanvasEnvironment(),'You can only use this function in Facebook Canvas environment');g.isString(l,'Invalid eventName');g.maybeNumber(m,'Invalid valueToSum');g.maybeObject(n,'Invalid params');var o=k.getClientID();g.isTrue(o!==null&&o.length>0,'You need to call FB.init() with App ID first.');h.logEvent(o,l,m,n);},logPurchase:function(l,m,n){g.isTrue(j('allow_non_canvas_app_events')||k.isCanvasEnvironment(),'You can only use this function in Facebook Canvas environment');g.isNumber(l,'Invalid purchaseAmount');g.isString(m,'Invalid currency');g.maybeObject(n,'Invalid params');var o=k.getClientID();g.isTrue(o!==null&&o.length>0,'You need to call FB.init() with App ID first.');h.logPurchase(o,l,m,n);},activateApp:function(){g.isTrue(j('allow_non_canvas_app_events')||k.isCanvasEnvironment(),'You can only use this function in Facebook Canvas environment');var l=k.getClientID();g.isTrue(l!==null&&l.length>0,'You need to call FB.init() with App ID first.');h.activateApp(l);},EventNames:h.EventNames,ParameterNames:h.ParameterNames});},3);
+ __d("sdk.Canvas.Environment",["sdk.RPC"],function(a,b,c,d,e,f,g){function h(k){g.remote.getPageInfo(function(l){k(l.result);});}function i(k,l){g.remote.scrollTo({x:k||0,y:l||0});}g.stub('getPageInfo');g.stub('scrollTo');var j={getPageInfo:h,scrollTo:i};e.exports=j;},null);
+ __d("sdk.Intl",["Log"],function(a,b,c,d,e,f,g){var h=('['+'.!?'+'\u3002'+'\uFF01'+'\uFF1F'+'\u0964'+'\u2026'+'\u0EAF'+'\u1801'+'\u0E2F'+'\uFF0E'+']');function i(l){if(typeof l!='string')return false;return !!l.match(new RegExp(h+'['+')"'+"'"+'\u00BB'+'\u0F3B'+'\u0F3D'+'\u2019'+'\u201D'+'\u203A'+'\u3009'+'\u300B'+'\u300D'+'\u300F'+'\u3011'+'\u3015'+'\u3017'+'\u3019'+'\u301B'+'\u301E'+'\u301F'+'\uFD3F'+'\uFF07'+'\uFF09'+'\uFF3D'+'\\s'+']*$'));}function j(l,m){if(m!==undefined)if(typeof m!='object'){g.error('The second arg to FB.Intl.tx() must be an Object for '+'FB.Intl.tx('+l+', ...)');}else{var n;for(var o in m)if(m.hasOwnProperty(o)){if(i(m[o])){n=new RegExp('\\{'+o+'\\}'+h+'*','g');}else n=new RegExp('\\{'+o+'\\}','g');l=l.replace(n,m[o]);}}return l;}function k(){throw new Error('Placeholder function');}k._=j;e.exports={tx:k};},null);
+ __d("sdk.Dialog",["sdk.Canvas.Environment","sdk.Content","sdk.DOM","DOMEventListener","sdk.Intl","ObservableMixin","sdk.Runtime","Type","UserAgent_DEPRECATED","sdk.feature"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){var q=590,r=500,s=240,t=575,u=function(){var y;if(p('dialog_resize_refactor')){var z=v();y=z&&(z.height>=q||z.width>=r);}else y=!!o.ipad();u=function(){return y;};return y;};function v(){if(p('dialog_resize_refactor')){var y=i.getViewportInfo();if(y.height&&y.width)return {width:Math.min(y.width,q),height:Math.min(y.height,r)};}return null;}var w=n.extend({constructor:function y(z,aa){this.parent();this.id=z;this.display=aa;this._e2e={};if(!x._dialogs){x._dialogs={};x._addOrientationHandler();}x._dialogs[z]=this;this.trackEvent('init');},trackEvent:function(y,z){if(this._e2e[y])return this;this._e2e[y]=z||ES('Date','now',false);if(y=='close')this.inform('e2e:end',this._e2e);return this;},trackEvents:function(y){if(typeof y==='string')y=ES('JSON','parse',false,y);for(var z in y)if(y.hasOwnProperty(z))this.trackEvent(z,y[z]);return this;}},l),x={newInstance:function(y,z){return new w(y,z);},_dialogs:null,_lastYOffset:0,_loaderEl:null,_overlayEl:null,_stack:[],_active:null,get:function(y){return x._dialogs[y];},_findRoot:function(y){while(y){if(i.containsCss(y,'fb_dialog'))return y;y=y.parentNode;}},_createWWWLoader:function(y){y=y?y:460;return x.create({content:(''+'
'+''),width:y});},_createMobileLoader:function(){var y=o.nativeApp()?'':(''+' '+' '+' '+' '+' '+' '+' '+'
');return x.create({classes:'loading'+(u()?' centered':''),content:('')});},_restoreBodyPosition:function(){if(!u()){var y=document.getElementsByTagName('body')[0];i.removeCss(y,'fb_hidden');}},_showTabletOverlay:function(){if(!u())return;if(!x._overlayEl){x._overlayEl=document.createElement('div');x._overlayEl.setAttribute('id','fb_dialog_ipad_overlay');h.append(x._overlayEl,null);}x._overlayEl.className='';},_hideTabletOverlay:function(){if(u())x._overlayEl.className='hidden';},showLoader:function(y,z){x._showTabletOverlay();if(!x._loaderEl)x._loaderEl=x._findRoot(o.mobile()?x._createMobileLoader():x._createWWWLoader(z));if(!y)y=function(){};var aa=document.getElementById('fb_dialog_loader_close');i.removeCss(aa,'fb_hidden');aa.onclick=function(){x._hideLoader();x._restoreBodyPosition();x._hideTabletOverlay();y();};var ba=document.getElementById('fb_dialog_ipad_overlay');if(ba)ba.ontouchstart=aa.onclick;x._makeActive(x._loaderEl);},_hideLoader:function(){if(x._loaderEl&&x._loaderEl==x._active)x._loaderEl.style.top='-10000px';},_makeActive:function(y){x._setDialogSizes();x._lowerActive();x._active=y;if(m.isEnvironment(m.ENVIRONMENTS.CANVAS))g.getPageInfo(function(z){x._centerActive(z);});x._centerActive();},_lowerActive:function(){if(!x._active)return;x._active.style.top='-10000px';x._active=null;},_removeStacked:function(y){x._stack=ES(x._stack,'filter',true,function(z){return z!=y;});},_centerActive:function(y){var z=x._active;if(!z)return;var aa=i.getViewportInfo(),ba=parseInt(z.offsetWidth,10),ca=parseInt(z.offsetHeight,10),da=aa.scrollLeft+(aa.width-ba)/2,ea=(aa.height-ca)/2.5;if(dafa)ga=fa;ga+=aa.scrollTop;if(o.mobile()){var ha=100;if(u()){ha+=(aa.height-ca)/2;}else{var ia=document.getElementsByTagName('body')[0];i.addCss(ia,'fb_hidden');if(p('dialog_resize_refactor'))ia.style.width='auto';ga=10000;}var ja=i.getByClass('fb_dialog_padding',z);if(ja.length)ja[0].style.height=ha+'px';}z.style.left=(da>0?da:0)+'px';z.style.top=(ga>0?ga:0)+'px';},_setDialogSizes:function(){if(!o.mobile()||u())return;for(var y in x._dialogs)if(x._dialogs.hasOwnProperty(y)){var z=document.getElementById(y);if(z){z.style.width=x.getDefaultSize().width+'px';z.style.height=x.getDefaultSize().height+'px';}}},getDefaultSize:function(){if(o.mobile()){var y=v();if(y)return y;if(o.ipad())return {width:r,height:q};if(o.android()){return {width:screen.availWidth,height:screen.availHeight};}else{var z=window.innerWidth,aa=window.innerHeight,ba=z/aa>1.2;return {width:z,height:Math.max(aa,(ba?screen.width:screen.height))};}}return {width:t,height:s};},_handleOrientationChange:function(y){var z=p('dialog_resize_refactor',false)?i.getViewportInfo().width:screen.availWidth;if(o.android()&&z==x._availScreenWidth){setTimeout(x._handleOrientationChange,50);return;}x._availScreenWidth=z;if(u()){x._centerActive();}else{var aa=x.getDefaultSize().width;for(var ba in x._dialogs)if(x._dialogs.hasOwnProperty(ba)){var ca=document.getElementById(ba);if(ca)ca.style.width=aa+'px';}}},_addOrientationHandler:function(){if(!o.mobile())return;var y="onorientationchange" in window?'orientationchange':'resize';x._availScreenWidth=p('dialog_resize_refactor',false)?i.getViewportInfo().width:screen.availWidth;j.add(window,y,x._handleOrientationChange);},create:function(y){y=y||{};var z=document.createElement('div'),aa=document.createElement('div'),ba='fb_dialog';if(y.closeIcon&&y.onClose){var ca=document.createElement('a');ca.className='fb_dialog_close_icon';ca.onclick=y.onClose;z.appendChild(ca);}ba+=' '+(y.classes||'');if(o.ie()){ba+=' fb_dialog_legacy';ES(['vert_left','vert_right','horiz_top','horiz_bottom','top_left','top_right','bottom_left','bottom_right'],'forEach',true,function(fa){var ga=document.createElement('span');ga.className='fb_dialog_'+fa;z.appendChild(ga);});}else ba+=o.mobile()?' fb_dialog_mobile':' fb_dialog_advanced';if(y.content)h.append(y.content,aa);z.className=ba;var da=parseInt(y.width,10);if(!isNaN(da))z.style.width=da+'px';aa.className='fb_dialog_content';z.appendChild(aa);if(o.mobile()){var ea=document.createElement('div');ea.className='fb_dialog_padding';z.appendChild(ea);}h.append(z);if(y.visible)x.show(z);return aa;},show:function(y){var z=x._findRoot(y);if(z){x._removeStacked(z);x._hideLoader();x._makeActive(z);x._stack.push(z);if('fbCallID' in y)x.get(y.fbCallID).inform('iframe_show').trackEvent('show');}},hide:function(y){var z=x._findRoot(y);x._hideLoader();if(z==x._active){x._lowerActive();x._restoreBodyPosition();x._hideTabletOverlay();if('fbCallID' in y)x.get(y.fbCallID).inform('iframe_hide').trackEvent('hide');}},remove:function(y){y=x._findRoot(y);if(y){var z=x._active==y;x._removeStacked(y);if(z){x._hideLoader();if(x._stack.length>0){x.show(x._stack.pop());}else{x._lowerActive();x._restoreBodyPosition();x._hideTabletOverlay();}}else if(x._active===null&&x._stack.length>0)x.show(x._stack.pop());setTimeout(function(){y.parentNode.removeChild(y);},3000);}},isActive:function(y){var z=x._findRoot(y);return z&&z===x._active;}};e.exports=x;},null);
+ __d("sdk.Frictionless",["sdk.Auth","sdk.api","sdk.Event","sdk.Dialog"],function(a,b,c,d,e,f,g,h,i,j){var k={_allowedRecipients:{},_useFrictionless:false,_updateRecipients:function(){k._allowedRecipients={};h('/me/apprequestformerrecipients',function(l){if(!l||l.error)return;ES(l.data,'forEach',true,function(m){k._allowedRecipients[m.recipient_id]=true;});});},init:function(){k._useFrictionless=true;g.getLoginStatus(function(l){if(l.status=='connected')k._updateRecipients();});i.subscribe('auth.login',function(l){if(l.authResponse)k._updateRecipients();});},_processRequestResponse:function(l,m){return function(n){var o=n&&n.updated_frictionless;if(k._useFrictionless&&o)k._updateRecipients();if(n){if(!m&&n.frictionless){j._hideLoader();j._restoreBodyPosition();j._hideIPadOverlay();}delete n.frictionless;delete n.updated_frictionless;}l&&l(n);};},isAllowed:function(l){if(!l)return false;if(typeof l==='number')return l in k._allowedRecipients;if(typeof l==='string')l=l.split(',');l=ES(l,'map',true,function(o){return ES(String(o),'trim',true);});var m=true,n=false;ES(l,'forEach',true,function(o){m=m&&o in k._allowedRecipients;n=true;});return m&&n;}};i.subscribe('init:post',function(l){if(l.frictionlessRequests)k.init();});e.exports=k;},null);
+ __d("sdk.Native",["Log","UserAgent_DEPRECATED"],function(a,b,c,d,e,f,g,h){var i='fbNativeReady',j={onready:function(k){if(!h.nativeApp()){g.error('FB.Native.onready only works when the page is rendered '+'in a WebView of the native Facebook app. Test if this is the '+'case calling FB.UA.nativeApp()');return;}if(window.__fbNative&&!this.nativeReady)ES('Object','assign',false,this,window.__fbNative);if(this.nativeReady){k();}else{var l=function(m){window.removeEventListener(i,l);this.onready(k);};window.addEventListener(i,l,false);}}};e.exports=j;},null);
+ __d("resolveURI",[],function(a,b,c,d,e,f){function g(h){if(!h)return window.location.href;h=h.replace(/&/g,'&').replace(/"/g,'"');var i=document.createElement('div');i.innerHTML=' ';return i.firstChild.href;}e.exports=g;},null);
+ __d("sdk.UIServer",["sdk.Auth","sdk.Content","createObjectFrom","sdk.Dialog","sdk.DOM","sdk.Event","flattenObject","sdk.Frictionless","sdk.getContextType","guid","insertIframe","Log","sdk.Native","QueryString","resolveURI","sdk.RPC","sdk.Runtime","JSSDKConfig","UrlMap","UserAgent_DEPRECATED","sdk.XD"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa){var ba={transform:function(ea){if(ea.params.display==='touch'&&ea.params.access_token&&window.postMessage){ea.params.channel=da._xdChannelHandler(ea.id,'parent');if(!z.nativeApp())ea.params.in_iframe=1;return ea;}else return da.genericTransform(ea);},getXdRelation:function(ea){var fa=ea.display;if(fa==='touch'&&window.postMessage&&ea.in_iframe)return 'parent';return da.getXdRelation(ea);}},ca={'stream.share':{size:{width:670,height:340},url:'sharer.php',transform:function(ea){if(!ea.params.u)ea.params.u=window.location.toString();ea.params.display='popup';return ea;}},apprequests:{transform:function(ea){ea=ba.transform(ea);ea.params.frictionless=n&&n._useFrictionless;if(ea.params.frictionless){if(n.isAllowed(ea.params.to)){ea.params.display='iframe';ea.params.in_iframe=true;ea.hideLoader=true;}ea.cb=n._processRequestResponse(ea.cb,ea.hideLoader);}ea.closeIcon=false;return ea;},getXdRelation:ba.getXdRelation},feed:ba,'permissions.oauth':{url:'dialog/oauth',size:{width:(z.mobile()?null:475),height:(z.mobile()?null:183)},transform:function(ea){if(!w.getClientID()){r.error('FB.login() called before FB.init().');return;}if(g.getAuthResponse()&&!ea.params.scope&&!ea.params.auth_type){r.error('FB.login() called when user is already connected.');ea.cb&&ea.cb({status:w.getLoginStatus(),authResponse:g.getAuthResponse()});return;}var fa=ea.cb,ga=ea.id;delete ea.cb;var ha=ES('Object','keys',false,ES('Object','assign',false,ea.params.response_type?i(ea.params.response_type.split(',')):{},{token:true,signed_request:true})).join(',');if(ea.params.display==='async'){ES('Object','assign',false,ea.params,{client_id:w.getClientID(),origin:o(),response_type:ha,domain:location.hostname});ea.cb=g.xdResponseWrapper(fa,g.getAuthResponse(),'permissions.oauth');}else ES('Object','assign',false,ea.params,{client_id:w.getClientID(),redirect_uri:u(da.xdHandler(fa,ga,'opener',g.getAuthResponse(),'permissions.oauth')),origin:o(),response_type:ha,domain:location.hostname});return ea;}},'auth.logout':{url:'logout.php',transform:function(ea){if(!w.getClientID()){r.error('FB.logout() called before calling FB.init().');}else if(!g.getAuthResponse()){r.error('FB.logout() called without an access token.');}else{ea.params.next=da.xdHandler(ea.cb,ea.id,'parent',g.getAuthResponse(),'logout');return ea;}}},'login.status':{url:'dialog/oauth',transform:function(ea){var fa=ea.cb,ga=ea.id;delete ea.cb;ES('Object','assign',false,ea.params,{client_id:w.getClientID(),redirect_uri:da.xdHandler(fa,ga,'parent',g.getAuthResponse(),'login_status'),origin:o(),response_type:'token,signed_request,code',domain:location.hostname});return ea;}}},da={Methods:ca,_loadedNodes:{},_defaultCb:{},_resultToken:'"xxRESULTTOKENxx"',genericTransform:function(ea){if(ea.params.display=='dialog'||ea.params.display=='iframe')ES('Object','assign',false,ea.params,{display:'iframe',channel:da._xdChannelHandler(ea.id,'parent.parent')},true);return ea;},checkOauthDisplay:function(ea){var fa=ea.scope||ea.perms||w.getScope();if(!fa)return ea.display;var ga=fa.split(/\s|,/g);for(var ha=0;ha2000;},getDisplayMode:function(ea,fa){if(fa.display==='hidden'||fa.display==='none')return fa.display;var ga=w.isEnvironment(w.ENVIRONMENTS.CANVAS)||w.isEnvironment(w.ENVIRONMENTS.PAGETAB);if(ga&&!fa.display)return 'async';if(z.mobile()||fa.display==='touch')return 'touch';if(!w.getAccessToken()&&(fa.display=='iframe'||fa.display=='dialog')&&!ea.loggedOutIframe){r.error('"dialog" mode can only be used when the user is connected.');return 'popup';}if(ea.connectDisplay&&!ga)return ea.connectDisplay;return fa.display||(w.getAccessToken()?'dialog':'popup');},getXdRelation:function(ea){var fa=ea.display;if(fa==='popup'||fa==='touch')return 'opener';if(fa==='dialog'||fa==='iframe'||fa==='hidden'||fa==='none')return 'parent';if(fa==='async')return 'parent.frames['+window.name+']';},popup:function(ea){var fa=typeof window.screenX!='undefined'?window.screenX:window.screenLeft,ga=typeof window.screenY!='undefined'?window.screenY:window.screenTop,ha=typeof window.outerWidth!='undefined'?window.outerWidth:document.documentElement.clientWidth,ia=typeof window.outerHeight!='undefined'?window.outerHeight:(document.documentElement.clientHeight-22),ja=z.mobile()?null:ea.size.width,ka=z.mobile()?null:ea.size.height,la=(fa<0)?window.screen.width+fa:fa,ma=parseInt(la+((ha-ja)/2),10),na=parseInt(ga+((ia-ka)/2.5),10),oa=[];if(ja!==null)oa.push('width='+ja);if(ka!==null)oa.push('height='+ka);oa.push('left='+ma);oa.push('top='+na);oa.push('scrollbars=1');if(ea.name=='permissions.request'||ea.name=='permissions.oauth')oa.push('location=1,toolbar=0');oa=oa.join(',');var pa;if(ea.post){pa=window.open('about:blank',ea.id,oa);if(pa){da.setLoadedNode(ea,pa,'popup');h.submitToTarget({url:ea.url,target:ea.id,params:ea.params});}}else{pa=window.open(ea.url,ea.id,oa);if(pa)da.setLoadedNode(ea,pa,'popup');}if(!pa)return;if(ea.id in da._defaultCb)da._popupMonitor();},setLoadedNode:function(ea,fa,ga){if(ea.params&&ea.params.display!='popup')fa.fbCallID=ea.id;fa={node:fa,type:ga,fbCallID:ea.id};da._loadedNodes[ea.id]=fa;},getLoadedNode:function(ea){var fa=typeof ea=='object'?ea.id:ea,ga=da._loadedNodes[fa];return ga?ga.node:null;},hidden:function(ea){ea.className='FB_UI_Hidden';ea.root=h.appendHidden('');da._insertIframe(ea);},iframe:function(ea){ea.className='FB_UI_Dialog';var fa=function(){da._triggerDefault(ea.id);};ea.root=j.create({onClose:fa,closeIcon:ea.closeIcon===undefined?true:ea.closeIcon,classes:(z.ipad()?'centered':'')});if(!ea.hideLoader)j.showLoader(fa,ea.size.width);k.addCss(ea.root,'fb_dialog_iframe');da._insertIframe(ea);},touch:function(ea){if(ea.params&&ea.params.in_iframe){if(ea.ui_created){j.showLoader(function(){da._triggerDefault(ea.id);},0);}else da.iframe(ea);}else if(z.nativeApp()&&!ea.ui_created){ea.frame=ea.id;s.onready(function(){da.setLoadedNode(ea,s.open(ea.url+'#cb='+ea.frameName),'native');});da._popupMonitor();}else if(!ea.ui_created)da.popup(ea);},async:function(ea){ea.params.redirect_uri=location.protocol+'//'+location.host+location.pathname;delete ea.params.access_token;v.remote.showDialog(ea.params,function(fa){var ga=fa.result;if(ga&&ga.e2e){var ha=j.get(ea.id);ha.trackEvents(ga.e2e);ha.trackEvent('close');delete ga.e2e;}ea.cb(ga);});},getDefaultSize:function(){return j.getDefaultSize();},_insertIframe:function(ea){da._loadedNodes[ea.id]=false;var fa=function(ga){if(ea.id in da._loadedNodes)da.setLoadedNode(ea,ga,'iframe');};if(ea.post){q({url:'about:blank',root:ea.root,className:ea.className,width:ea.size.width,height:ea.size.height,id:ea.id,onInsert:fa,onload:function(ga){h.submitToTarget({url:ea.url,target:ga.name,params:ea.params});}});}else q({url:ea.url,root:ea.root,className:ea.className,width:ea.size.width,height:ea.size.height,id:ea.id,name:ea.frameName,onInsert:fa});},_handleResizeMessage:function(ea,fa){var ga=da.getLoadedNode(ea);if(!ga)return;if(fa.height)ga.style.height=fa.height+'px';if(fa.width)ga.style.width=fa.width+'px';aa.inform('resize.ack',fa||{},'parent.frames['+ga.name+']');if(!j.isActive(ga))j.show(ga);},_triggerDefault:function(ea){da._xdRecv({frame:ea},da._defaultCb[ea]||function(){});},_popupMonitor:function(){var ea;for(var fa in da._loadedNodes)if(da._loadedNodes.hasOwnProperty(fa)&&fa in da._defaultCb){var ga=da._loadedNodes[fa];if(ga.type!='popup'&&ga.type!='native')continue;var ha=ga.node;try{if(ha.closed){da._triggerDefault(fa);}else ea=true;}catch(ia){}}if(ea&&!da._popupInterval){da._popupInterval=setInterval(da._popupMonitor,100);}else if(!ea&&da._popupInterval){clearInterval(da._popupInterval);da._popupInterval=null;}},_xdChannelHandler:function(ea,fa){return aa.handler(function(ga){var ha=da.getLoadedNode(ea);if(!ha)return;if(ga.type=='resize'){da._handleResizeMessage(ea,ga);}else if(ga.type=='hide'){j.hide(ha);}else if(ga.type=='rendered'){var ia=j._findRoot(ha);j.show(ia);}else if(ga.type=='fireevent')l.fire(ga.event);},fa,true,null);},_xdNextHandler:function(ea,fa,ga,ha){if(ha)da._defaultCb[fa]=ea;return aa.handler(function(ia){da._xdRecv(ia,ea);},ga)+'&frame='+fa;},_xdRecv:function(ea,fa){var ga=da.getLoadedNode(ea.frame);if(ga)if(ga.close){try{ga.close();if(/iPhone.*Version\/(5|6)/.test(navigator.userAgent)&&RegExp.$1!=='5')window.focus();da._popupCount--;}catch(ha){}}else if(k.containsCss(ga,'FB_UI_Hidden')){setTimeout(function(){ga.parentNode.parentNode.removeChild(ga.parentNode);},3000);}else if(k.containsCss(ga,'FB_UI_Dialog'))j.remove(ga);delete da._loadedNodes[ea.frame];delete da._defaultCb[ea.frame];if(ea.e2e){var ia=j.get(ea.frame);ia.trackEvents(ea.e2e);ia.trackEvent('close');delete ea.e2e;}fa(ea);},_xdResult:function(ea,fa,ga,ha){return (da._xdNextHandler(function(ia){ea&&ea(ia.result&&ia.result!=da._resultToken&&ES('JSON','parse',false,ia.result));},fa,ga,ha)+'&result='+encodeURIComponent(da._resultToken));},xdHandler:function(ea,fa,ga,ha,ia){return da._xdNextHandler(g.xdResponseWrapper(ea,ha,ia),fa,ga,true);}};v.stub('showDialog');e.exports=da;},null);
+ __d("sdk.ui",["Assert","sdk.Impressions","Log","sdk.PlatformVersioning","sdk.Runtime","sdk.UIServer","sdk.feature"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(o,p){g.isObject(o);g.maybeFunction(p);if(k.getIsVersioned()){j.assertVersionIsSet();if(o.version){j.assertValidVersion(o.version);}else o.version=k.getVersion();}o=ES('Object','assign',false,{},o);if(!o.method){i.error('"method" is a required parameter for FB.ui().');return null;}if(o.method=='pay.prompt')o.method='pay';var q=o.method;if(o.redirect_uri){i.warn('When using FB.ui, you should not specify a redirect_uri.');delete o.redirect_uri;}if((q=='permissions.request'||q=='permissions.oauth')&&(o.display=='iframe'||o.display=='dialog'))o.display=l.checkOauthDisplay(o);var r=m('e2e_tracking',true);if(r)o.e2e={};var s=l.prepareCall(o,p||function(){});if(!s)return null;var t=s.params.display;if(t==='dialog'){t='iframe';}else if(t==='none')t='hidden';var u=l[t];if(!u){i.error('"display" must be one of "popup", '+'"dialog", "iframe", "touch", "async", "hidden", or "none"');return null;}if(r)s.dialog.subscribe('e2e:end',function(v){v.method=q;v.display=t;i.debug('e2e: %s',ES('JSON','stringify',false,v));h.log(114,{payload:v});});u(s);return s.dialog;}e.exports=n;},null);
+ __d("legacy:fb.auth",["sdk.Auth","sdk.Cookie","copyProperties","sdk.Event","FB","Log","sdk.Runtime","sdk.SignedRequest","sdk.ui"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){k.provide('',{getLoginStatus:function(){return g.getLoginStatus.apply(g,arguments);},getAuthResponse:function(){return g.getAuthResponse();},getAccessToken:function(){return m.getAccessToken()||null;},getUserID:function(){return m.getUserID()||m.getCookieUserID();},login:function(p,q){if(q&&q.perms&&!q.scope){q.scope=q.perms;delete q.perms;l.warn('OAuth2 specification states that \'perms\' '+'should now be called \'scope\'. Please update.');}var r=m.isEnvironment(m.ENVIRONMENTS.CANVAS)||m.isEnvironment(m.ENVIRONMENTS.PAGETAB);o(i({method:'permissions.oauth',display:r?'async':'popup',domain:location.hostname},q||{}),p);},logout:function(p){o({method:'auth.logout',display:'hidden'},p);}});g.subscribe('logout',ES(j.fire,'bind',true,j,'auth.logout'));g.subscribe('login',ES(j.fire,'bind',true,j,'auth.login'));g.subscribe('authresponse.change',ES(j.fire,'bind',true,j,'auth.authResponseChange'));g.subscribe('status.change',ES(j.fire,'bind',true,j,'auth.statusChange'));j.subscribe('init:post',function(p){if(p.status)g.getLoginStatus();if(m.getClientID())if(p.authResponse){g.setAuthResponse(p.authResponse,'connected');}else if(m.getUseCookie()){var q=h.loadSignedRequest(),r;if(q){try{r=n.parse(q);}catch(s){h.clearSignedRequestCookie();}if(r&&r.user_id)m.setCookieUserID(r.user_id);}h.loadMeta();}});},3);
+ __d("sdk.Canvas.IframeHandling",["DOMWrapper","sdk.RPC"],function(a,b,c,d,e,f,g,h){var i=null,j;function k(){var o=g.getWindow().document,p=o.body,q=o.documentElement,r=Math.max(p.offsetTop,0),s=Math.max(q.offsetTop,0),t=p.scrollHeight+r,u=p.offsetHeight+r,v=q.scrollHeight+s,w=q.offsetHeight+s;return Math.max(t,u,v,w);}function l(o){if(typeof o!='object')o={};var p=0,q=0;if(!o.height){o.height=k();p=16;q=4;}if(!o.frame)o.frame=window.name||'iframe_canvas';if(j){var r=j.height,s=o.height-r;if(s<=q&&s>=-p)return false;}j=o;h.remote.setSize(o);return true;}function m(o,p){if(p===undefined&&typeof o==='number'){p=o;o=true;}if(o||o===undefined){if(i===null)i=setInterval(function(){l();},p||100);l();}else if(i!==null){clearInterval(i);i=null;}}h.stub('setSize');var n={setSize:l,setAutoGrow:m};e.exports=n;},null);
+ __d("sdk.Canvas.Navigation",["sdk.RPC"],function(a,b,c,d,e,f,g){function h(j){g.local.navigate=function(k){j({path:k});};g.remote.setNavigationEnabled(true);}g.stub('setNavigationEnabled');var i={setUrlHandler:h};e.exports=i;},null);
+ __d("sdk.Canvas.Plugin",["sdk.api","sdk.RPC","Log","UserAgent_DEPRECATED","sdk.Runtime","createArrayFrom"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m='CLSID:D27CDB6E-AE6D-11CF-96B8-444553540000',n='CLSID:444785F1-DE89-4295-863A-D46C3A781394',o=null,p=!(j.osx()>=10.9&&(j.chrome()>=31||j.webkit()>=537.71||j.firefox()>=25));function q(aa){aa._hideunity_savedstyle={};aa._hideunity_savedstyle.left=aa.style.left;aa._hideunity_savedstyle.position=aa.style.position;aa._hideunity_savedstyle.width=aa.style.width;aa._hideunity_savedstyle.height=aa.style.height;aa.style.left='-10000px';aa.style.position='absolute';aa.style.width='1px';aa.style.height='1px';}function r(aa){if(aa._hideunity_savedstyle){aa.style.left=aa._hideunity_savedstyle.left;aa.style.position=aa._hideunity_savedstyle.position;aa.style.width=aa._hideunity_savedstyle.width;aa.style.height=aa._hideunity_savedstyle.height;}}function s(aa){aa._old_visibility=aa.style.visibility;aa.style.visibility='hidden';}function t(aa){aa.style.visibility=aa._old_visibility||'';delete aa._old_visibility;}function u(aa){var ba=aa.type?aa.type.toLowerCase():null,ca=ba==='application/x-shockwave-flash'||(aa.classid&&aa.classid.toUpperCase()==m);if(!ca)return false;var da=/opaque|transparent/i;if(da.test(aa.getAttribute('wmode')))return false;for(var ea=0;ea1/l||m=='*'||~ES(m,'indexOf',true,j.getClientID()))return;setTimeout(p,30000);}function r(u){n=u;}function s(u){o.push(u);}var t={COLLECT_AUTOMATIC:k.AUTOMATIC,COLLECT_MANUAL:k.MANUAL,addStaticResource:s,setCollectionMode:r,_maybeSample:q};e.exports=t;},null);
+ __d("legacy:fb.canvas.prefetcher",["FB","sdk.Canvas.Prefetcher","sdk.Event","sdk.Runtime"],function(a,b,c,d,e,f,g,h,i,j){g.provide('Canvas.Prefetcher',h);i.subscribe('init:post',function(k){if(j.isEnvironment(j.ENVIRONMENTS.CANVAS))h._maybeSample();});},3);
+ __d("legacy:fb.canvas.presence",["sdk.RPC","sdk.Event"],function(a,b,c,d,e,f,g,h){h.subscribe(h.SUBSCRIBE,i);h.subscribe(h.UNSUBSCRIBE,j);g.stub('useFriendsOnline');function i(k,l){if(k!='canvas.friendsOnlineUpdated')return;if(l.length===1)g.remote.useFriendsOnline(true);}function j(k,l){if(k!='canvas.friendsOnlineUpdated')return;if(l.length===0)g.remote.useFriendsOnline(false);}},3);
+ __d("legacy:fb.event",["FB","sdk.Event","sdk.Runtime","sdk.Scribe","sdk.feature"],function(a,b,c,d,e,f,g,h,i,j,k){var l=[],m=null,n=k('event_subscriptions_log',false);g.provide('Event',{subscribe:function(o,p){if(n){l.push(o);if(!m)m=setTimeout(function(){j.log('jssdk_error',{appId:i.getClientID(),error:'EVENT_SUBSCRIPTIONS_LOG',extra:{line:0,name:'EVENT_SUBSCRIPTIONS_LOG',script:'N/A',stack:'N/A',message:l.sort().join(',')}});l.length=0;m=null;},n);}return h.subscribe(o,p);},unsubscribe:ES(h.unsubscribe,'bind',true,h)});},3);
+ __d("legacy:fb.frictionless",["FB","sdk.Frictionless"],function(a,b,c,d,e,f,g,h){g.provide('Frictionless',h);},3);
+ __d("sdk.init",["sdk.Cookie","sdk.ErrorHandling","sdk.Event","Log","ManagedError","sdk.PlatformVersioning","QueryString","sdk.Runtime","sdk.URI","createArrayFrom"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){function q(s){var t=(typeof s=='number'&&s>0)||(typeof s=='string'&&/^[0-9a-f]{21,}$|^[0-9]{1,21}$/.test(s));if(t)return s.toString();j.warn('Invalid App Id: Must be a number or numeric string representing '+'the application id.');return null;}function r(s){if(n.getInitialized())j.warn('FB.init has already been called - this could indicate a problem');if(n.getIsVersioned()){if(Object.prototype.toString.call(s)!=='[object Object]')throw new k('Invalid argument');if(s.authResponse)j.warn('Setting authResponse is not supported');if(!s.version)s.version=o(location.href).getQueryData().sdk_version;l.assertValidVersion(s.version);n.setVersion(s.version);}else{if(/number|string/.test(typeof s)){j.warn('FB.init called with invalid parameters');s={apiKey:s};}s=ES('Object','assign',false,{status:true},s||{});}var t=q(s.appId||s.apiKey);if(t!==null)n.setClientID(t);if('scope' in s)n.setScope(s.scope);if(s.cookie){n.setUseCookie(true);if(typeof s.cookie==='string')g.setDomain(s.cookie);}if(s.kidDirectedSite)n.setKidDirectedSite(true);n.setInitialized(true);i.fire('init:post',s);}setTimeout(function(){var s=/(connect\.facebook\.net|\.facebook\.com\/assets.php).*?#(.*)/;ES(p(document.getElementsByTagName('script')),'forEach',true,function(t){if(t.src){var u=s.exec(t.src);if(u){var v=m.decode(u[2]);for(var w in v)if(v.hasOwnProperty(w)){var x=v[w];if(x=='0')v[w]=0;}r(v);}}});if(window.fbAsyncInit&&!window.fbAsyncInit.hasRun){window.fbAsyncInit.hasRun=true;h.unguard(window.fbAsyncInit)();}},0);e.exports=r;},null);
+ __d("legacy:fb.init",["FB","sdk.init"],function(a,b,c,d,e,f,g,h){g.provide('',{init:h});},3);
+ __d("legacy:fb.pay",["copyProperties","sdk.Runtime","sdk.UIServer","sdk.XD","sdk.feature","FB"],function(a,b,c,d,e,f,g,h,i,j,k){b('FB');var l={error_code:1383001,error_message:'An unknown error caused the dialog to be closed'},m=function(n){return function(o){if(o&&typeof o.response==='string'){n(ES('JSON','parse',false,o.response));}else if(typeof o==='object'){n(o);}else n(l);};};g(i.Methods,{pay:{size:{width:555,height:120},connectDisplay:'popup',transform:function(n){if(k('launch_payment_dialog_via_pac')){n.cb=m(n.cb);return n;}else{n.cb=m(n.cb);if(!h.isEnvironment(h.ENVIRONMENTS.CANVAS)){n.params.order_info=ES('JSON','stringify',false,n.params.order_info);return n;}var o=j.handler(n.cb,'parent.frames['+(window.name||'iframe_canvas')+']');n.params.channel=o;n.params.uiserver=true;j.inform('Pay.Prompt',n.params);}}}});},3);
+ __d("legacy:fb.ui",["FB","sdk.ui"],function(a,b,c,d,e,f,g,h){g.provide('',{ui:h});},3);
+ __d("runOnce",[],function(a,b,c,d,e,f){function g(h){var i,j;return function(){if(!i){i=true;j=h();}return j;};}e.exports=g;},null);
+ __d("XFBML",["Assert","createArrayFrom","sdk.DOM","sdk.feature","sdk.Impressions","Log","ObservableMixin","runOnce","UserAgent_DEPRECATED"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p={},q={},r=0,s=new m();function t(ba,ca){return ba[ca]+'';}function u(ba){return ba.scopeName?(ba.scopeName+':'+ba.nodeName):'';}function v(ba){return p[t(ba,'nodeName').toLowerCase()]||p[u(ba).toLowerCase()];}function w(ba){var ca=ES(ES(t(ba,'className'),'trim',true).split(/\s+/),'filter',true,function(da){return q.hasOwnProperty(da);});if(ca.length===0)return undefined;if(ba.getAttribute('fb-xfbml-state')||!ba.childNodes||ba.childNodes.length===0||(ba.childNodes.length===1&&ba.childNodes[0].nodeType===3)||(ba.children.length===1&&t(ba.children[0],'className')==='fb-xfbml-parse-ignore'))return q[ca[0]];}function x(ba){var ca={};ES(h(ba.attributes),'forEach',true,function(da){ca[t(da,'name')]=t(da,'value');});return ca;}function y(ba,ca,da){var ea=document.createElement('div');i.addCss(ba,ca+'-'+da);ES(h(ba.childNodes),'forEach',true,function(fa){ea.appendChild(fa);});ES(h(ba.attributes),'forEach',true,function(fa){ea.setAttribute(fa.name,fa.value);});ba.parentNode.replaceChild(ea,ba);return ea;}function z(ba,ca,da){g.isTrue(ba&&ba.nodeType&&ba.nodeType===1&&!!ba.getElementsByTagName,'Invalid DOM node passed to FB.XFBML.parse()');g.isFunction(ca,'Invalid callback passed to FB.XFBML.parse()');var ea=++r;l.info('XFBML Parsing Start %s',ea);var fa=1,ga=0,ha=function(){fa--;if(fa===0){l.info('XFBML Parsing Finish %s, %s tags found',ea,ga);ca();s.inform('render',ea,ga);}g.isTrue(fa>=0,'onrender() has been called too many times');};ES(h(ba.getElementsByTagName('*')),'forEach',true,function(ja){if(!da&&ja.getAttribute('fb-xfbml-state'))return;if(ja.nodeType!==1)return;var ka=v(ja)||w(ja);if(!ka)return;if(o.ie()<9&&ja.scopeName)ja=y(ja,ka.xmlns,ka.localName);fa++;ga++;var la=new ka.ctor(ja,ka.xmlns,ka.localName,x(ja));la.subscribe('render',n(function(){ja.setAttribute('fb-xfbml-state','rendered');ha();}));var ma=function(){if(ja.getAttribute('fb-xfbml-state')=='parsed'){s.subscribe('render.queue',ma);}else{ja.setAttribute('fb-xfbml-state','parsed');la.process();}};ma();});s.inform('parse',ea,ga);var ia=30000;setTimeout(function(){if(fa>0)l.warn('%s tags failed to render in %s ms',fa,ia);},ia);ha();}s.subscribe('render',function(){var ba=s.getSubscribers('render.queue');s.clearSubscribers('render.queue');ES(ba,'forEach',true,function(ca){ca();});});ES('Object','assign',false,s,{registerTag:function(ba){var ca=ba.xmlns+':'+ba.localName;g.isUndefined(p[ca],ca+' already registered');p[ca]=ba;q[ba.xmlns+'-'+ba.localName]=ba;},parse:function(ba,ca){z(ba||document.body,ca||function(){},true);},parseNew:function(){z(document.body,function(){},false);}});if(j('log_tag_count')){var aa=function(ba,ca){s.unsubscribe('parse',aa);setTimeout(ES(k.log,'bind',true,null,102,{tag_count:ca}),5000);};s.subscribe('parse',aa);}e.exports=s;},null);
+ __d("PluginPipe",["sdk.Content","sdk.feature","guid","insertIframe","Miny","ObservableMixin","JSSDKPluginPipeConfig","sdk.Runtime","UrlMap","UserAgent_DEPRECATED","XFBML"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q){var r=new l(),s=m.threshold,t=[];function u(){return !!(h('plugin_pipe')&&n.getSecure()!==undefined&&(p.chrome()||p.firefox())&&m.enabledApps[n.getClientID()]);}function v(){var x=t;t=[];if(x.length<=s){ES(x,'forEach',true,function(aa){j(aa.config);});return;}var y=x.length+1;function z(){y--;if(y===0)w(x);}ES(x,'forEach',true,function(aa){var ba={};for(var ca in aa.config)ba[ca]=aa.config[ca];ba.url=o.resolve('www',n.getSecure())+'/plugins/plugin_pipe_shell.php';ba.onload=z;j(ba);});z();}q.subscribe('parse',v);function w(x){var y=document.createElement('span');g.appendHidden(y);var z={};ES(x,'forEach',true,function(ea){z[ea.config.name]={plugin:ea.tag,params:ea.params};});var aa=ES('JSON','stringify',false,z),ba=k.encode(aa);ES(x,'forEach',true,function(ea){var fa=document.getElementsByName(ea.config.name)[0];fa.onload=ea.config.onload;});var ca=o.resolve('www',n.getSecure())+'/plugins/pipe.php',da=i();j({url:'about:blank',root:y,name:da,className:'fb_hidden fb_invisible',onload:function(){g.submitToTarget({url:ca,target:da,params:{plugins:ba.length-1)?n:l;});},isValid:function(){for(var k=this.dom;k;k=k.parentNode)if(k==document.body)return true;},clear:function(){g.html(this.dom,'');}},i);e.exports=j;},null);
+ __d("sdk.XFBML.IframeWidget",["sdk.Arbiter","sdk.Auth","sdk.Content","sdk.DOM","sdk.Event","sdk.XFBML.Element","guid","insertIframe","QueryString","sdk.Runtime","sdk.ui","UrlMap","sdk.XD"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s){var t=l.extend({_iframeName:null,_showLoader:true,_refreshOnAuthChange:false,_allowReProcess:false,_fetchPreCachedLoader:false,_visibleAfter:'load',_widgetPipeEnabled:false,_borderReset:false,_repositioned:false,getUrlBits:function(){throw new Error('Inheriting class needs to implement getUrlBits().');},setupAndValidate:function(){return true;},oneTimeSetup:function(){},getSize:function(){},getIframeName:function(){return this._iframeName;},getIframeTitle:function(){return 'Facebook Social Plugin';},getChannelUrl:function(){if(!this._channelUrl){var x=this;this._channelUrl=s.handler(function(y){x.fire('xd.'+y.type,y);},'parent.parent',true);}return this._channelUrl;},getIframeNode:function(){return this.dom.getElementsByTagName('iframe')[0];},arbiterInform:function(event,x,y){s.sendToFacebook(this.getIframeName(),{method:event,params:ES('JSON','stringify',false,x||{}),behavior:y||g.BEHAVIOR_PERSISTENT});},_arbiterInform:function(event,x,y){var z='parent.frames["'+this.getIframeNode().name+'"]';s.inform(event,x,z,y);},getDefaultWebDomain:function(){return r.resolve('www');},process:function(x){if(this._done){if(!this._allowReProcess&&!x)return;this.clear();}else this._oneTimeSetup();this._done=true;this._iframeName=this.getIframeName()||this._iframeName||m();if(!this.setupAndValidate()){this.fire('render');return;}if(this._showLoader)this._addLoader();j.addCss(this.dom,'fb_iframe_widget');if(this._visibleAfter!='immediate'){j.addCss(this.dom,'fb_hide_iframes');}else this.subscribe('iframe.onload',ES(this.fire,'bind',true,this,'render'));var y=this.getSize()||{},z=this.getFullyQualifiedURL();if(y.width=='100%')j.addCss(this.dom,'fb_iframe_widget_fluid');this.clear();n({url:z,root:this.dom.appendChild(document.createElement('span')),name:this._iframeName,title:this.getIframeTitle(),className:p.getRtl()?'fb_rtl':'fb_ltr',height:y.height,width:y.width,onload:ES(this.fire,'bind',true,this,'iframe.onload')});this._resizeFlow(y);this.loaded=false;this.subscribe('iframe.onload',ES(function(){this.loaded=true;if(!this._isResizeHandled)j.addCss(this.dom,'fb_hide_iframes');},'bind',true,this));},generateWidgetPipeIframeName:function(){u++;return 'fb_iframe_'+u;},getFullyQualifiedURL:function(){var x=this._getURL();x+='?'+o.encode(this._getQS());if(x.length>2000){x='about:blank';var y=ES(function(){this._postRequest();this.unsubscribe('iframe.onload',y);},'bind',true,this);this.subscribe('iframe.onload',y);}return x;},_getWidgetPipeShell:function(){return r.resolve('www')+'/common/widget_pipe_shell.php';},_oneTimeSetup:function(){this.subscribe('xd.resize',ES(this._handleResizeMsg,'bind',true,this));this.subscribe('xd.resize',ES(this._bubbleResizeEvent,'bind',true,this));this.subscribe('xd.resize.iframe',ES(this._resizeIframe,'bind',true,this));this.subscribe('xd.resize.flow',ES(this._resizeFlow,'bind',true,this));this.subscribe('xd.resize.flow',ES(this._bubbleResizeEvent,'bind',true,this));this.subscribe('xd.refreshLoginStatus',function(){h.getLoginStatus(function(){},true);});this.subscribe('xd.logout',function(){q({method:'auth.logout',display:'hidden'},function(){});});if(this._refreshOnAuthChange)this._setupAuthRefresh();if(this._visibleAfter=='load')this.subscribe('iframe.onload',ES(this._makeVisible,'bind',true,this));this.subscribe('xd.verify',ES(function(x){this.arbiterInform('xd/verify',x.token);},'bind',true,this));this.oneTimeSetup();},_makeVisible:function(){this._removeLoader();j.removeCss(this.dom,'fb_hide_iframes');this.fire('render');},_setupAuthRefresh:function(){h.getLoginStatus(ES(function(x){var y=x.status;k.subscribe('auth.statusChange',ES(function(z){if(!this.isValid())return;if(y=='unknown'||z.status=='unknown')this.process(true);y=z.status;},'bind',true,this));},'bind',true,this));},_handleResizeMsg:function(x){if(!this.isValid())return;this._resizeIframe(x);this._resizeFlow(x);if(!this._borderReset){this.getIframeNode().style.border='none';this._borderReset=true;}this._isResizeHandled=true;this._makeVisible();},_bubbleResizeEvent:function(x){var y={height:x.height,width:x.width,pluginID:this.getAttribute('plugin-id')};k.fire('xfbml.resize',y);},_resizeIframe:function(x){var y=this.getIframeNode();if(x.reposition==="true")this._repositionIframe(x);x.height&&(y.style.height=x.height+'px');x.width&&(y.style.width=x.width+'px');this._updateIframeZIndex();},_resizeFlow:function(x){var y=this.dom.getElementsByTagName('span')[0];x.height&&(y.style.height=x.height+'px');x.width&&(y.style.width=x.width+'px');this._updateIframeZIndex();},_updateIframeZIndex:function(){var x=this.dom.getElementsByTagName('span')[0],y=this.getIframeNode(),z=y.style.height===x.style.height&&y.style.width===x.style.width,aa=z?'removeCss':'addCss';j[aa](y,'fb_iframe_widget_lift');},_repositionIframe:function(x){var y=this.getIframeNode(),z=parseInt(j.getStyle(y,'width'),10),aa=j.getPosition(y).x,ba=j.getViewportInfo().width,ca=parseInt(x.width,10);if(aa+ca>ba&&aa>ca){y.style.left=z-ca+'px';this.arbiterInform('xd/reposition',{type:'horizontal'});this._repositioned=true;}else if(this._repositioned){y.style.left='0px';this.arbiterInform('xd/reposition',{type:'restore'});this._repositioned=false;}},_addLoader:function(){if(!this._loaderDiv){j.addCss(this.dom,'fb_iframe_widget_loader');this._loaderDiv=document.createElement('div');this._loaderDiv.className='FB_Loader';this.dom.appendChild(this._loaderDiv);}},_removeLoader:function(){if(this._loaderDiv){j.removeCss(this.dom,'fb_iframe_widget_loader');if(this._loaderDiv.parentNode)this._loaderDiv.parentNode.removeChild(this._loaderDiv);this._loaderDiv=null;}},_getQS:function(){return ES('Object','assign',false,{api_key:p.getClientID(),locale:p.getLocale(),sdk:'joey',kid_directed_site:p.getKidDirectedSite(),ref:this.getAttribute('ref')},this.getUrlBits().params);},_getURL:function(){var x=this.getDefaultWebDomain(),y='';return x+'/plugins/'+y+this.getUrlBits().name+'.php';},_postRequest:function(){i.submitToTarget({url:this._getURL(),target:this.getIframeNode().name,params:this._getQS()});}}),u=0,v={};function w(){var x={};for(var y in v){var z=v[y];x[y]={widget:z.getUrlBits().name,params:z._getQS()};}return x;}e.exports=t;},null);
+ __d("sdk.XFBML.Comments",["sdk.Event","sdk.XFBML.IframeWidget","QueryString","sdk.Runtime","JSSDKConfig","UrlMap","UserAgent_DEPRECATED"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){var n=h.extend({_visibleAfter:'immediate',_refreshOnAuthChange:true,setupAndValidate:function(){var o={channel_url:this.getChannelUrl(),colorscheme:this.getAttribute('colorscheme'),skin:this.getAttribute('skin'),numposts:this.getAttribute('num-posts',10),width:this._getLengthAttribute('width'),href:this.getAttribute('href'),permalink:this.getAttribute('permalink'),publish_feed:this.getAttribute('publish_feed'),order_by:this.getAttribute('order_by'),mobile:this._getBoolAttribute('mobile')};if(!o.width&&!o.permalink)o.width=550;if(k.initSitevars.enableMobileComments&&m.mobile()&&o.mobile!==false){o.mobile=true;delete o.width;}if(!o.skin)o.skin=o.colorscheme;if(!o.href){o.migrated=this.getAttribute('migrated');o.xid=this.getAttribute('xid');o.title=this.getAttribute('title',document.title);o.url=this.getAttribute('url',document.URL);o.quiet=this.getAttribute('quiet');o.reverse=this.getAttribute('reverse');o.simple=this.getAttribute('simple');o.css=this.getAttribute('css');o.notify=this.getAttribute('notify');if(!o.xid){var p=ES(document.URL,'indexOf',true,'#');if(p>0){o.xid=encodeURIComponent(document.URL.substring(0,p));}else o.xid=encodeURIComponent(document.URL);}if(o.migrated)o.href=l.resolve('www')+'/plugins/comments_v1.php?'+'app_id='+j.getClientID()+'&xid='+encodeURIComponent(o.xid)+'&url='+encodeURIComponent(o.url);}else{var q=this.getAttribute('fb_comment_id');if(!q){q=i.decode(document.URL.substring(ES(document.URL,'indexOf',true,'?')+1)).fb_comment_id;if(q&&ES(q,'indexOf',true,'#')>0)q=q.substring(0,ES(q,'indexOf',true,'#'));}if(q){o.fb_comment_id=q;this.subscribe('render',ES(function(){if(!window.location.hash)window.location.hash=this.getIframeNode().id;},'bind',true,this));}}this._attr=o;return true;},oneTimeSetup:function(){this.subscribe('xd.addComment',ES(this._handleCommentMsg,'bind',true,this));this.subscribe('xd.commentCreated',ES(this._handleCommentCreatedMsg,'bind',true,this));this.subscribe('xd.commentRemoved',ES(this._handleCommentRemovedMsg,'bind',true,this));},getSize:function(){if(!this._attr.permalink)return {width:this._attr.mobile?'100%':this._attr.width,height:160};},getUrlBits:function(){return {name:'comments',params:this._attr};},getDefaultWebDomain:function(){return l.resolve(this._attr.mobile?'m':'www',true);},_handleCommentMsg:function(o){if(!this.isValid())return;g.fire('comments.add',{post:o.post,user:o.user,widget:this});},_handleCommentCreatedMsg:function(o){if(!this.isValid())return;var p={href:o.href,commentID:o.commentID,parentCommentID:o.parentCommentID,message:o.message};g.fire('comment.create',p);},_handleCommentRemovedMsg:function(o){if(!this.isValid())return;var p={href:o.href,commentID:o.commentID};g.fire('comment.remove',p);}});e.exports=n;},null);
+ __d("sdk.XFBML.CommentsCount",["ApiClient","sdk.DOM","sdk.XFBML.Element","sprintf"],function(a,b,c,d,e,f,g,h,i,j){var k=i.extend({process:function(){h.addCss(this.dom,'fb_comments_count_zero');var l=this.getAttribute('href',window.location.href);g.scheduleBatchCall('/v2.1/'+encodeURIComponent(l),{fields:'share'},ES(function(m){var n=(m.share&&m.share.comment_count)||0;h.html(this.dom,j('',n));if(n>0)h.removeCss(this.dom,'fb_comments_count_zero');this.fire('render');},'bind',true,this));}});e.exports=k;},null);
+ __d("safeEval",[],function(a,b,c,d,e,f){function g(h,i){if(h===null||typeof h==='undefined')return;if(typeof h!=='string')return h;if(/^\w+$/.test(h)&&typeof window[h]==='function')return window[h].apply(null,i||[]);return Function('return eval("'+h.replace(/"/g,'\\"')+'");').apply(null,i||[]);}e.exports=g;},null);
+ __d("sdk.Helper",["sdk.ErrorHandling","sdk.Event","UrlMap","safeEval","sprintf"],function(a,b,c,d,e,f,g,h,i,j,k){var l={isUser:function(m){return m<2.2e+09||(m>=1e+14&&m<=100099999989999)||(m>=8.9e+13&&m<=89999999999999);},upperCaseFirstChar:function(m){if(m.length>0){return m.substr(0,1).toUpperCase()+m.substr(1);}else return m;},getProfileLink:function(m,n,o){if(!o&&m)o=k('%s/profile.php?id=%s',i.resolve('www'),m.uid||m.id);if(o)n=k('%s ',o,n);return n;},invokeHandler:function(m,n,o){if(m)if(typeof m==='string'){g.unguard(j)(m,o);}else if(m.apply)g.unguard(m).apply(n,o||[]);},fireEvent:function(m,n){var o=n._attr.href;n.fire(m,o);h.fire(m,o,n);},executeFunctionByName:function(m){var n=Array.prototype.slice.call(arguments,1),o=m.split("."),p=o.pop(),q=window;for(var r=0;r"'\/]/g,h={'&':'&','<':'<','>':'>','"':'"',"'":''','/':'/'};function i(j){return j.replace(g,function(k){return h[k];});}e.exports=i;},null);
+ __d("sdk.XFBML.Name",["ApiClient","escapeHTML","sdk.Event","sdk.XFBML.Element","sdk.Helper","Log","sdk.Runtime"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){var n=({}).hasOwnProperty,o=j.extend({process:function(){ES('Object','assign',false,this,{_uid:this.getAttribute('uid'),_firstnameonly:this._getBoolAttribute('first-name-only'),_lastnameonly:this._getBoolAttribute('last-name-only'),_possessive:this._getBoolAttribute('possessive'),_reflexive:this._getBoolAttribute('reflexive'),_objective:this._getBoolAttribute('objective'),_linked:this._getBoolAttribute('linked',true),_subjectId:this.getAttribute('subject-id')});if(!this._uid){l.error('"uid" is a required attribute for ');this.fire('render');return;}var p=[];if(this._firstnameonly){p.push('first_name');}else if(this._lastnameonly){p.push('last_name');}else p.push('name');if(this._subjectId){p.push('gender');if(this._subjectId==m.getUserID())this._reflexive=true;}i.monitor('auth.statusChange',ES(function(){if(!this.isValid()){this.fire('render');return true;}if(!this._uid||this._uid=='loggedinuser')this._uid=m.getUserID();if(!this._uid)return;g.scheduleBatchCall('/v1.0/'+this._uid,{fields:p.join(',')},ES(function(q){if(n.call(q,'error')){l.warn('The name is not found for ID: '+this._uid);return;}if(this._subjectId==this._uid){this._renderPronoun(q);}else this._renderOther(q);this.fire('render');},'bind',true,this));},'bind',true,this));},_renderPronoun:function(p){var q='',r=this._objective;if(this._subjectId){r=true;if(this._subjectId===this._uid)this._reflexive=true;}if(this._uid==m.getUserID()&&this._getBoolAttribute('use-you',true)){if(this._possessive){if(this._reflexive){q='your own';}else q='your';}else if(this._reflexive){q='yourself';}else q='you';}else switch(p.gender){case 'male':if(this._possessive){q=this._reflexive?'his own':'his';}else if(this._reflexive){q='himself';}else if(r){q='him';}else q='he';break;case 'female':if(this._possessive){q=this._reflexive?'her own':'her';}else if(this._reflexive){q='herself';}else if(r){q='her';}else q='she';break;default:if(this._getBoolAttribute('use-they',true)){if(this._possessive){if(this._reflexive){q='their own';}else q='their';}else if(this._reflexive){q='themselves';}else if(r){q='them';}else q='they';}else if(this._possessive){if(this._reflexive){q='his/her own';}else q='his/her';}else if(this._reflexive){q='himself/herself';}else if(r){q='him/her';}else q='he/she';break;}if(this._getBoolAttribute('capitalize',false))q=k.upperCaseFirstChar(q);this.dom.innerHTML=q;},_renderOther:function(p){var q='',r='';if(this._uid==m.getUserID()&&this._getBoolAttribute('use-you',true)){if(this._reflexive){if(this._possessive){q='your own';}else q='yourself';}else if(this._possessive){q='your';}else q='you';}else if(p){if(null===p.first_name)p.first_name='';if(null===p.last_name)p.last_name='';if(this._firstnameonly&&p.first_name!==undefined){q=h(p.first_name);}else if(this._lastnameonly&&p.last_name!==undefined)q=h(p.last_name);if(!q)q=h(p.name);if(q!==''&&this._possessive)q+='\'s';}if(!q)q=h(this.getAttribute('if-cant-see','Facebook User'));if(q){if(this._getBoolAttribute('capitalize',false))q=k.upperCaseFirstChar(q);if(p&&this._linked){r=k.getProfileLink(p,q,this.getAttribute('href',null));}else r=q;}this.dom.innerHTML=r;}});e.exports=o;},null);
+ __d("sdk.XFBML.RecommendationsBar",["sdk.Arbiter","DOMEventListener","sdk.Event","sdk.XFBML.IframeWidget","resolveURI","sdk.Runtime"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m=j.extend({getUrlBits:function(){return {name:'recommendations_bar',params:this._attr};},setupAndValidate:function(){function n(w,x){var y=0,z=null;function aa(){x();z=null;y=ES('Date','now',false);}return function(){if(!z){var ba=ES('Date','now',false);if(ba-y=this._attr.trigger;}}});e.exports=m;},null);
+ __d("sdk.XFBML.Registration",["sdk.Auth","sdk.Helper","sdk.XFBML.IframeWidget","sdk.Runtime","UrlMap"],function(a,b,c,d,e,f,g,h,i,j,k){var l=i.extend({_visibleAfter:'immediate',_baseHeight:167,_fieldHeight:28,_skinnyWidth:520,_skinnyBaseHeight:173,_skinnyFieldHeight:52,setupAndValidate:function(){this._attr={action:this.getAttribute('action'),border_color:this.getAttribute('border-color'),channel_url:this.getChannelUrl(),client_id:j.getClientID(),fb_only:this._getBoolAttribute('fb-only',false),fb_register:this._getBoolAttribute('fb-register',false),fields:this.getAttribute('fields'),height:this._getPxAttribute('height'),redirect_uri:this.getAttribute('redirect-uri',window.location.href),no_footer:this._getBoolAttribute('no-footer'),no_header:this._getBoolAttribute('no-header'),onvalidate:this.getAttribute('onvalidate'),width:this._getPxAttribute('width',600),target:this.getAttribute('target')};if(this._attr.onvalidate)this.subscribe('xd.validate',ES(function(m){var n=ES('JSON','parse',false,m.value),o=ES(function(q){this.arbiterInform('Registration.Validation',{errors:q,id:m.id});},'bind',true,this),p=h.executeFunctionByName(this._attr.onvalidate,n,o);if(p)o(p);},'bind',true,this));this.subscribe('xd.authLogin',ES(this._onAuthLogin,'bind',true,this));this.subscribe('xd.authLogout',ES(this._onAuthLogout,'bind',true,this));return true;},getSize:function(){return {width:this._attr.width,height:this._getHeight()};},_getHeight:function(){if(this._attr.height)return this._attr.height;var m;if(!this._attr.fields){m=['name'];}else try{m=ES('JSON','parse',false,this._attr.fields);}catch(n){m=this._attr.fields.split(/,/);}if(this._attr.width 0 && !this.encoding) {
+ var pack = this.packetBuffer.shift();
+ this.packet(pack);
+ }
+ };
+
+ /**
+ * Clean up transport subscriptions and packet buffer.
+ *
+ * @api private
+ */
+
+ Manager.prototype.cleanup = function(){
+ var sub;
+ while (sub = this.subs.shift()) sub.destroy();
+
+ this.packetBuffer = [];
+ this.encoding = false;
+
+ this.decoder.destroy();
+ };
+
+ /**
+ * Close the current socket.
+ *
+ * @api private
+ */
+
+ Manager.prototype.close =
+ Manager.prototype.disconnect = function(){
+ this.skipReconnect = true;
+ this.backoff.reset();
+ this.readyState = 'closed';
+ this.engine && this.engine.close();
+ };
+
+ /**
+ * Called upon engine close.
+ *
+ * @api private
+ */
+
+ Manager.prototype.onclose = function(reason){
+ debug('close');
+ this.cleanup();
+ this.backoff.reset();
+ this.readyState = 'closed';
+ this.emit('close', reason);
+ if (this._reconnection && !this.skipReconnect) {
+ this.reconnect();
+ }
+ };
+
+ /**
+ * Attempt a reconnection.
+ *
+ * @api private
+ */
+
+ Manager.prototype.reconnect = function(){
+ if (this.reconnecting || this.skipReconnect) return this;
+
+ var self = this;
+
+ if (this.backoff.attempts >= this._reconnectionAttempts) {
+ debug('reconnect failed');
+ this.backoff.reset();
+ this.emitAll('reconnect_failed');
+ this.reconnecting = false;
+ } else {
+ var delay = this.backoff.duration();
+ debug('will wait %dms before reconnect attempt', delay);
+
+ this.reconnecting = true;
+ var timer = setTimeout(function(){
+ if (self.skipReconnect) return;
+
+ debug('attempting reconnect');
+ self.emitAll('reconnect_attempt', self.backoff.attempts);
+ self.emitAll('reconnecting', self.backoff.attempts);
+
+ // check again for the case socket closed in above events
+ if (self.skipReconnect) return;
+
+ self.open(function(err){
+ if (err) {
+ debug('reconnect attempt error');
+ self.reconnecting = false;
+ self.reconnect();
+ self.emitAll('reconnect_error', err.data);
+ } else {
+ debug('reconnect success');
+ self.onreconnect();
+ }
+ });
+ }, delay);
+
+ this.subs.push({
+ destroy: function(){
+ clearTimeout(timer);
+ }
+ });
+ }
+ };
+
+ /**
+ * Called upon successful reconnect.
+ *
+ * @api private
+ */
+
+ Manager.prototype.onreconnect = function(){
+ var attempt = this.backoff.attempts;
+ this.reconnecting = false;
+ this.backoff.reset();
+ this.updateSocketIds();
+ this.emitAll('reconnect', attempt);
+ };
+
+},{"./on":4,"./socket":5,"./url":6,"backo2":7,"component-bind":8,"component-emitter":9,"debug":10,"engine.io-client":11,"indexof":42,"object-component":43,"socket.io-parser":46}],4:[function(_dereq_,module,exports){
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = on;
+
+ /**
+ * Helper for subscriptions.
+ *
+ * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
+ * @param {String} event name
+ * @param {Function} callback
+ * @api public
+ */
+
+ function on(obj, ev, fn) {
+ obj.on(ev, fn);
+ return {
+ destroy: function(){
+ obj.removeListener(ev, fn);
+ }
+ };
+ }
+
+},{}],5:[function(_dereq_,module,exports){
+
+ /**
+ * Module dependencies.
+ */
+
+ var parser = _dereq_('socket.io-parser');
+ var Emitter = _dereq_('component-emitter');
+ var toArray = _dereq_('to-array');
+ var on = _dereq_('./on');
+ var bind = _dereq_('component-bind');
+ var debug = _dereq_('debug')('socket.io-client:socket');
+ var hasBin = _dereq_('has-binary');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = exports = Socket;
+
+ /**
+ * Internal events (blacklisted).
+ * These events can't be emitted by the user.
+ *
+ * @api private
+ */
+
+ var events = {
+ connect: 1,
+ connect_error: 1,
+ connect_timeout: 1,
+ disconnect: 1,
+ error: 1,
+ reconnect: 1,
+ reconnect_attempt: 1,
+ reconnect_failed: 1,
+ reconnect_error: 1,
+ reconnecting: 1
+ };
+
+ /**
+ * Shortcut to `Emitter#emit`.
+ */
+
+ var emit = Emitter.prototype.emit;
+
+ /**
+ * `Socket` constructor.
+ *
+ * @api public
+ */
+
+ function Socket(io, nsp){
+ this.io = io;
+ this.nsp = nsp;
+ this.json = this; // compat
+ this.ids = 0;
+ this.acks = {};
+ if (this.io.autoConnect) this.open();
+ this.receiveBuffer = [];
+ this.sendBuffer = [];
+ this.connected = false;
+ this.disconnected = true;
+ }
+
+ /**
+ * Mix in `Emitter`.
+ */
+
+ Emitter(Socket.prototype);
+
+ /**
+ * Subscribe to open, close and packet events
+ *
+ * @api private
+ */
+
+ Socket.prototype.subEvents = function() {
+ if (this.subs) return;
+
+ var io = this.io;
+ this.subs = [
+ on(io, 'open', bind(this, 'onopen')),
+ on(io, 'packet', bind(this, 'onpacket')),
+ on(io, 'close', bind(this, 'onclose'))
+ ];
+ };
+
+ /**
+ * "Opens" the socket.
+ *
+ * @api public
+ */
+
+ Socket.prototype.open =
+ Socket.prototype.connect = function(){
+ if (this.connected) return this;
+
+ this.subEvents();
+ this.io.open(); // ensure open
+ if ('open' == this.io.readyState) this.onopen();
+ return this;
+ };
+
+ /**
+ * Sends a `message` event.
+ *
+ * @return {Socket} self
+ * @api public
+ */
+
+ Socket.prototype.send = function(){
+ var args = toArray(arguments);
+ args.unshift('message');
+ this.emit.apply(this, args);
+ return this;
+ };
+
+ /**
+ * Override `emit`.
+ * If the event is in `events`, it's emitted normally.
+ *
+ * @param {String} event name
+ * @return {Socket} self
+ * @api public
+ */
+
+ Socket.prototype.emit = function(ev){
+ if (events.hasOwnProperty(ev)) {
+ emit.apply(this, arguments);
+ return this;
+ }
+
+ var args = toArray(arguments);
+ var parserType = parser.EVENT; // default
+ if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
+ var packet = { type: parserType, data: args };
+
+ // event ack callback
+ if ('function' == typeof args[args.length - 1]) {
+ debug('emitting packet with ack id %d', this.ids);
+ this.acks[this.ids] = args.pop();
+ packet.id = this.ids++;
+ }
+
+ if (this.connected) {
+ this.packet(packet);
+ } else {
+ this.sendBuffer.push(packet);
+ }
+
+ return this;
+ };
+
+ /**
+ * Sends a packet.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+ Socket.prototype.packet = function(packet){
+ packet.nsp = this.nsp;
+ this.io.packet(packet);
+ };
+
+ /**
+ * Called upon engine `open`.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onopen = function(){
+ debug('transport is open - connecting');
+
+ // write connect packet if necessary
+ if ('/' != this.nsp) {
+ this.packet({ type: parser.CONNECT });
+ }
+ };
+
+ /**
+ * Called upon engine `close`.
+ *
+ * @param {String} reason
+ * @api private
+ */
+
+ Socket.prototype.onclose = function(reason){
+ debug('close (%s)', reason);
+ this.connected = false;
+ this.disconnected = true;
+ delete this.id;
+ this.emit('disconnect', reason);
+ };
+
+ /**
+ * Called with socket packet.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+ Socket.prototype.onpacket = function(packet){
+ if (packet.nsp != this.nsp) return;
+
+ switch (packet.type) {
+ case parser.CONNECT:
+ this.onconnect();
+ break;
+
+ case parser.EVENT:
+ this.onevent(packet);
+ break;
+
+ case parser.BINARY_EVENT:
+ this.onevent(packet);
+ break;
+
+ case parser.ACK:
+ this.onack(packet);
+ break;
+
+ case parser.BINARY_ACK:
+ this.onack(packet);
+ break;
+
+ case parser.DISCONNECT:
+ this.ondisconnect();
+ break;
+
+ case parser.ERROR:
+ this.emit('error', packet.data);
+ break;
+ }
+ };
+
+ /**
+ * Called upon a server event.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+ Socket.prototype.onevent = function(packet){
+ var args = packet.data || [];
+ debug('emitting event %j', args);
+
+ if (null != packet.id) {
+ debug('attaching ack callback to event');
+ args.push(this.ack(packet.id));
+ }
+
+ if (this.connected) {
+ emit.apply(this, args);
+ } else {
+ this.receiveBuffer.push(args);
+ }
+ };
+
+ /**
+ * Produces an ack callback to emit with an event.
+ *
+ * @api private
+ */
+
+ Socket.prototype.ack = function(id){
+ var self = this;
+ var sent = false;
+ return function(){
+ // prevent double callbacks
+ if (sent) return;
+ sent = true;
+ var args = toArray(arguments);
+ debug('sending ack %j', args);
+
+ var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
+ self.packet({
+ type: type,
+ id: id,
+ data: args
+ });
+ };
+ };
+
+ /**
+ * Called upon a server acknowlegement.
+ *
+ * @param {Object} packet
+ * @api private
+ */
+
+ Socket.prototype.onack = function(packet){
+ debug('calling ack %s with %j', packet.id, packet.data);
+ var fn = this.acks[packet.id];
+ fn.apply(this, packet.data);
+ delete this.acks[packet.id];
+ };
+
+ /**
+ * Called upon server connect.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onconnect = function(){
+ this.connected = true;
+ this.disconnected = false;
+ this.emit('connect');
+ this.emitBuffered();
+ };
+
+ /**
+ * Emit buffered events (received and emitted).
+ *
+ * @api private
+ */
+
+ Socket.prototype.emitBuffered = function(){
+ var i;
+ for (i = 0; i < this.receiveBuffer.length; i++) {
+ emit.apply(this, this.receiveBuffer[i]);
+ }
+ this.receiveBuffer = [];
+
+ for (i = 0; i < this.sendBuffer.length; i++) {
+ this.packet(this.sendBuffer[i]);
+ }
+ this.sendBuffer = [];
+ };
+
+ /**
+ * Called upon server disconnect.
+ *
+ * @api private
+ */
+
+ Socket.prototype.ondisconnect = function(){
+ debug('server disconnect (%s)', this.nsp);
+ this.destroy();
+ this.onclose('io server disconnect');
+ };
+
+ /**
+ * Called upon forced client/server side disconnections,
+ * this method ensures the manager stops tracking us and
+ * that reconnections don't get triggered for this.
+ *
+ * @api private.
+ */
+
+ Socket.prototype.destroy = function(){
+ if (this.subs) {
+ // clean subscriptions to avoid reconnections
+ for (var i = 0; i < this.subs.length; i++) {
+ this.subs[i].destroy();
+ }
+ this.subs = null;
+ }
+
+ this.io.destroy(this);
+ };
+
+ /**
+ * Disconnects the socket manually.
+ *
+ * @return {Socket} self
+ * @api public
+ */
+
+ Socket.prototype.close =
+ Socket.prototype.disconnect = function(){
+ if (this.connected) {
+ debug('performing disconnect (%s)', this.nsp);
+ this.packet({ type: parser.DISCONNECT });
+ }
+
+ // remove socket from pool
+ this.destroy();
+
+ if (this.connected) {
+ // fire events
+ this.onclose('io client disconnect');
+ }
+ return this;
+ };
+
+},{"./on":4,"component-bind":8,"component-emitter":9,"debug":10,"has-binary":38,"socket.io-parser":46,"to-array":50}],6:[function(_dereq_,module,exports){
+ (function (global){
+
+ /**
+ * Module dependencies.
+ */
+
+ var parseuri = _dereq_('parseuri');
+ var debug = _dereq_('debug')('socket.io-client:url');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = url;
+
+ /**
+ * URL parser.
+ *
+ * @param {String} url
+ * @param {Object} An object meant to mimic window.location.
+ * Defaults to window.location.
+ * @api public
+ */
+
+ function url(uri, loc){
+ var obj = uri;
+
+ // default to window.location
+ var loc = loc || global.location;
+ if (null == uri) uri = loc.protocol + '//' + loc.host;
+
+ // relative path support
+ if ('string' == typeof uri) {
+ if ('/' == uri.charAt(0)) {
+ if ('/' == uri.charAt(1)) {
+ uri = loc.protocol + uri;
+ } else {
+ uri = loc.hostname + uri;
+ }
+ }
+
+ if (!/^(https?|wss?):\/\//.test(uri)) {
+ debug('protocol-less url %s', uri);
+ if ('undefined' != typeof loc) {
+ uri = loc.protocol + '//' + uri;
+ } else {
+ uri = 'https://' + uri;
+ }
+ }
+
+ // parse
+ debug('parse %s', uri);
+ obj = parseuri(uri);
+ }
+
+ // make sure we treat `localhost:80` and `localhost` equally
+ if (!obj.port) {
+ if (/^(http|ws)$/.test(obj.protocol)) {
+ obj.port = '80';
+ }
+ else if (/^(http|ws)s$/.test(obj.protocol)) {
+ obj.port = '443';
+ }
+ }
+
+ obj.path = obj.path || '/';
+
+ // define unique id
+ obj.id = obj.protocol + '://' + obj.host + ':' + obj.port;
+ // define href
+ obj.href = obj.protocol + '://' + obj.host + (loc && loc.port == obj.port ? '' : (':' + obj.port));
+
+ return obj;
+ }
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"debug":10,"parseuri":44}],7:[function(_dereq_,module,exports){
+
+ /**
+ * Expose `Backoff`.
+ */
+
+ module.exports = Backoff;
+
+ /**
+ * Initialize backoff timer with `opts`.
+ *
+ * - `min` initial timeout in milliseconds [100]
+ * - `max` max timeout [10000]
+ * - `jitter` [0]
+ * - `factor` [2]
+ *
+ * @param {Object} opts
+ * @api public
+ */
+
+ function Backoff(opts) {
+ opts = opts || {};
+ this.ms = opts.min || 100;
+ this.max = opts.max || 10000;
+ this.factor = opts.factor || 2;
+ this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
+ this.attempts = 0;
+ }
+
+ /**
+ * Return the backoff duration.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+ Backoff.prototype.duration = function(){
+ var ms = this.ms * Math.pow(this.factor, this.attempts++);
+ if (this.jitter) {
+ var rand = Math.random();
+ var deviation = Math.floor(rand * this.jitter * ms);
+ ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;
+ }
+ return Math.min(ms, this.max) | 0;
+ };
+
+ /**
+ * Reset the number of attempts.
+ *
+ * @api public
+ */
+
+ Backoff.prototype.reset = function(){
+ this.attempts = 0;
+ };
+
+ /**
+ * Set the minimum duration
+ *
+ * @api public
+ */
+
+ Backoff.prototype.setMin = function(min){
+ this.ms = min;
+ };
+
+ /**
+ * Set the maximum duration
+ *
+ * @api public
+ */
+
+ Backoff.prototype.setMax = function(max){
+ this.max = max;
+ };
+
+ /**
+ * Set the jitter
+ *
+ * @api public
+ */
+
+ Backoff.prototype.setJitter = function(jitter){
+ this.jitter = jitter;
+ };
+
+
+},{}],8:[function(_dereq_,module,exports){
+ /**
+ * Slice reference.
+ */
+
+ var slice = [].slice;
+
+ /**
+ * Bind `obj` to `fn`.
+ *
+ * @param {Object} obj
+ * @param {Function|String} fn or string
+ * @return {Function}
+ * @api public
+ */
+
+ module.exports = function(obj, fn){
+ if ('string' == typeof fn) fn = obj[fn];
+ if ('function' != typeof fn) throw new Error('bind() requires a function');
+ var args = slice.call(arguments, 2);
+ return function(){
+ return fn.apply(obj, args.concat(slice.call(arguments)));
+ }
+ };
+
+},{}],9:[function(_dereq_,module,exports){
+
+ /**
+ * Expose `Emitter`.
+ */
+
+ module.exports = Emitter;
+
+ /**
+ * Initialize a new `Emitter`.
+ *
+ * @api public
+ */
+
+ function Emitter(obj) {
+ if (obj) return mixin(obj);
+ };
+
+ /**
+ * Mixin the emitter properties.
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+ function mixin(obj) {
+ for (var key in Emitter.prototype) {
+ obj[key] = Emitter.prototype[key];
+ }
+ return obj;
+ }
+
+ /**
+ * Listen on the given `event` with `fn`.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+ Emitter.prototype.on =
+ Emitter.prototype.addEventListener = function(event, fn){
+ this._callbacks = this._callbacks || {};
+ (this._callbacks[event] = this._callbacks[event] || [])
+ .push(fn);
+ return this;
+ };
+
+ /**
+ * Adds an `event` listener that will be invoked a single
+ * time then automatically removed.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+ Emitter.prototype.once = function(event, fn){
+ var self = this;
+ this._callbacks = this._callbacks || {};
+
+ function on() {
+ self.off(event, on);
+ fn.apply(this, arguments);
+ }
+
+ on.fn = fn;
+ this.on(event, on);
+ return this;
+ };
+
+ /**
+ * Remove the given callback for `event` or all
+ * registered callbacks.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+ Emitter.prototype.off =
+ Emitter.prototype.removeListener =
+ Emitter.prototype.removeAllListeners =
+ Emitter.prototype.removeEventListener = function(event, fn){
+ this._callbacks = this._callbacks || {};
+
+ // all
+ if (0 == arguments.length) {
+ this._callbacks = {};
+ return this;
+ }
+
+ // specific event
+ var callbacks = this._callbacks[event];
+ if (!callbacks) return this;
+
+ // remove all handlers
+ if (1 == arguments.length) {
+ delete this._callbacks[event];
+ return this;
+ }
+
+ // remove specific handler
+ var cb;
+ for (var i = 0; i < callbacks.length; i++) {
+ cb = callbacks[i];
+ if (cb === fn || cb.fn === fn) {
+ callbacks.splice(i, 1);
+ break;
+ }
+ }
+ return this;
+ };
+
+ /**
+ * Emit `event` with the given args.
+ *
+ * @param {String} event
+ * @param {Mixed} ...
+ * @return {Emitter}
+ */
+
+ Emitter.prototype.emit = function(event){
+ this._callbacks = this._callbacks || {};
+ var args = [].slice.call(arguments, 1)
+ , callbacks = this._callbacks[event];
+
+ if (callbacks) {
+ callbacks = callbacks.slice(0);
+ for (var i = 0, len = callbacks.length; i < len; ++i) {
+ callbacks[i].apply(this, args);
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Return array of callbacks for `event`.
+ *
+ * @param {String} event
+ * @return {Array}
+ * @api public
+ */
+
+ Emitter.prototype.listeners = function(event){
+ this._callbacks = this._callbacks || {};
+ return this._callbacks[event] || [];
+ };
+
+ /**
+ * Check if this emitter has `event` handlers.
+ *
+ * @param {String} event
+ * @return {Boolean}
+ * @api public
+ */
+
+ Emitter.prototype.hasListeners = function(event){
+ return !! this.listeners(event).length;
+ };
+
+},{}],10:[function(_dereq_,module,exports){
+
+ /**
+ * Expose `debug()` as the module.
+ */
+
+ module.exports = debug;
+
+ /**
+ * Create a debugger with the given `name`.
+ *
+ * @param {String} name
+ * @return {Type}
+ * @api public
+ */
+
+ function debug(name) {
+ if (!debug.enabled(name)) return function(){};
+
+ return function(fmt){
+ fmt = coerce(fmt);
+
+ var curr = new Date;
+ var ms = curr - (debug[name] || curr);
+ debug[name] = curr;
+
+ fmt = name
+ + ' '
+ + fmt
+ + ' +' + debug.humanize(ms);
+
+ // This hackery is required for IE8
+ // where `console.log` doesn't have 'apply'
+ window.console
+ && console.log
+ && Function.prototype.apply.call(console.log, console, arguments);
+ }
+ }
+
+ /**
+ * The currently active debug mode names.
+ */
+
+ debug.names = [];
+ debug.skips = [];
+
+ /**
+ * Enables a debug mode by name. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} name
+ * @api public
+ */
+
+ debug.enable = function(name) {
+ try {
+ localStorage.debug = name;
+ } catch(e){}
+
+ var split = (name || '').split(/[\s,]+/)
+ , len = split.length;
+
+ for (var i = 0; i < len; i++) {
+ name = split[i].replace('*', '.*?');
+ if (name[0] === '-') {
+ debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
+ }
+ else {
+ debug.names.push(new RegExp('^' + name + '$'));
+ }
+ }
+ };
+
+ /**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+ debug.disable = function(){
+ debug.enable('');
+ };
+
+ /**
+ * Humanize the given `ms`.
+ *
+ * @param {Number} m
+ * @return {String}
+ * @api private
+ */
+
+ debug.humanize = function(ms) {
+ var sec = 1000
+ , min = 60 * 1000
+ , hour = 60 * min;
+
+ if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
+ if (ms >= min) return (ms / min).toFixed(1) + 'm';
+ if (ms >= sec) return (ms / sec | 0) + 's';
+ return ms + 'ms';
+ };
+
+ /**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+ debug.enabled = function(name) {
+ for (var i = 0, len = debug.skips.length; i < len; i++) {
+ if (debug.skips[i].test(name)) {
+ return false;
+ }
+ }
+ for (var i = 0, len = debug.names.length; i < len; i++) {
+ if (debug.names[i].test(name)) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ /**
+ * Coerce `val`.
+ */
+
+ function coerce(val) {
+ if (val instanceof Error) return val.stack || val.message;
+ return val;
+ }
+
+// persist
+
+ try {
+ if (window.localStorage) debug.enable(localStorage.debug);
+ } catch(e){}
+
+},{}],11:[function(_dereq_,module,exports){
+
+ module.exports = _dereq_('./lib/');
+
+},{"./lib/":12}],12:[function(_dereq_,module,exports){
+
+ module.exports = _dereq_('./socket');
+
+ /**
+ * Exports parser
+ *
+ * @api public
+ *
+ */
+ module.exports.parser = _dereq_('engine.io-parser');
+
+},{"./socket":13,"engine.io-parser":25}],13:[function(_dereq_,module,exports){
+ (function (global){
+ /**
+ * Module dependencies.
+ */
+
+ var transports = _dereq_('./transports');
+ var Emitter = _dereq_('component-emitter');
+ var debug = _dereq_('debug')('engine.io-client:socket');
+ var index = _dereq_('indexof');
+ var parser = _dereq_('engine.io-parser');
+ var parseuri = _dereq_('parseuri');
+ var parsejson = _dereq_('parsejson');
+ var parseqs = _dereq_('parseqs');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = Socket;
+
+ /**
+ * Noop function.
+ *
+ * @api private
+ */
+
+ function noop(){}
+
+ /**
+ * Socket constructor.
+ *
+ * @param {String|Object} uri or options
+ * @param {Object} options
+ * @api public
+ */
+
+ function Socket(uri, opts){
+ if (!(this instanceof Socket)) return new Socket(uri, opts);
+
+ opts = opts || {};
+
+ if (uri && 'object' == typeof uri) {
+ opts = uri;
+ uri = null;
+ }
+
+ if (uri) {
+ uri = parseuri(uri);
+ opts.host = uri.host;
+ opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
+ opts.port = uri.port;
+ if (uri.query) opts.query = uri.query;
+ }
+
+ this.secure = null != opts.secure ? opts.secure :
+ (global.location && 'https:' == location.protocol);
+
+ if (opts.host) {
+ var pieces = opts.host.split(':');
+ opts.hostname = pieces.shift();
+ if (pieces.length) {
+ opts.port = pieces.pop();
+ } else if (!opts.port) {
+ // if no port is specified manually, use the protocol default
+ opts.port = this.secure ? '443' : '80';
+ }
+ }
+
+ this.agent = opts.agent || false;
+ this.hostname = opts.hostname ||
+ (global.location ? location.hostname : 'localhost');
+ this.port = opts.port || (global.location && location.port ?
+ location.port :
+ (this.secure ? 443 : 80));
+ this.query = opts.query || {};
+ if ('string' == typeof this.query) this.query = parseqs.decode(this.query);
+ this.upgrade = false !== opts.upgrade;
+ this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
+ this.forceJSONP = !!opts.forceJSONP;
+ this.jsonp = false !== opts.jsonp;
+ this.forceBase64 = !!opts.forceBase64;
+ this.enablesXDR = !!opts.enablesXDR;
+ this.timestampParam = opts.timestampParam || 't';
+ this.timestampRequests = opts.timestampRequests;
+ this.transports = opts.transports || ['polling', 'websocket'];
+ this.readyState = '';
+ this.writeBuffer = [];
+ this.callbackBuffer = [];
+ this.policyPort = opts.policyPort || 843;
+ this.rememberUpgrade = opts.rememberUpgrade || false;
+ this.binaryType = null;
+ this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
+
+ // SSL options for Node.js client
+ this.pfx = opts.pfx || null;
+ this.key = opts.key || null;
+ this.passphrase = opts.passphrase || null;
+ this.cert = opts.cert || null;
+ this.ca = opts.ca || null;
+ this.ciphers = opts.ciphers || null;
+ this.rejectUnauthorized = opts.rejectUnauthorized || null;
+
+ this.open();
+ }
+
+ Socket.priorWebsocketSuccess = false;
+
+ /**
+ * Mix in `Emitter`.
+ */
+
+ Emitter(Socket.prototype);
+
+ /**
+ * Protocol version.
+ *
+ * @api public
+ */
+
+ Socket.protocol = parser.protocol; // this is an int
+
+ /**
+ * Expose deps for legacy compatibility
+ * and standalone browser access.
+ */
+
+ Socket.Socket = Socket;
+ Socket.Transport = _dereq_('./transport');
+ Socket.transports = _dereq_('./transports');
+ Socket.parser = _dereq_('engine.io-parser');
+
+ /**
+ * Creates transport of the given type.
+ *
+ * @param {String} transport name
+ * @return {Transport}
+ * @api private
+ */
+
+ Socket.prototype.createTransport = function (name) {
+ debug('creating transport "%s"', name);
+ var query = clone(this.query);
+
+ // append engine.io protocol identifier
+ query.EIO = parser.protocol;
+
+ // transport name
+ query.transport = name;
+
+ // session id if we already have one
+ if (this.id) query.sid = this.id;
+
+ var transport = new transports[name]({
+ agent: this.agent,
+ hostname: this.hostname,
+ port: this.port,
+ secure: this.secure,
+ path: this.path,
+ query: query,
+ forceJSONP: this.forceJSONP,
+ jsonp: this.jsonp,
+ forceBase64: this.forceBase64,
+ enablesXDR: this.enablesXDR,
+ timestampRequests: this.timestampRequests,
+ timestampParam: this.timestampParam,
+ policyPort: this.policyPort,
+ socket: this,
+ pfx: this.pfx,
+ key: this.key,
+ passphrase: this.passphrase,
+ cert: this.cert,
+ ca: this.ca,
+ ciphers: this.ciphers,
+ rejectUnauthorized: this.rejectUnauthorized
+ });
+
+ return transport;
+ };
+
+ function clone (obj) {
+ var o = {};
+ for (var i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ o[i] = obj[i];
+ }
+ }
+ return o;
+ }
+
+ /**
+ * Initializes transport to use and starts probe.
+ *
+ * @api private
+ */
+ Socket.prototype.open = function () {
+ var transport;
+ if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
+ transport = 'websocket';
+ } else if (0 == this.transports.length) {
+ // Emit error on next tick so it can be listened to
+ var self = this;
+ setTimeout(function() {
+ self.emit('error', 'No transports available');
+ }, 0);
+ return;
+ } else {
+ transport = this.transports[0];
+ }
+ this.readyState = 'opening';
+
+ // Retry with the next transport if the transport is disabled (jsonp: false)
+ var transport;
+ try {
+ transport = this.createTransport(transport);
+ } catch (e) {
+ this.transports.shift();
+ this.open();
+ return;
+ }
+
+ transport.open();
+ this.setTransport(transport);
+ };
+
+ /**
+ * Sets the current transport. Disables the existing one (if any).
+ *
+ * @api private
+ */
+
+ Socket.prototype.setTransport = function(transport){
+ debug('setting transport %s', transport.name);
+ var self = this;
+
+ if (this.transport) {
+ debug('clearing existing transport %s', this.transport.name);
+ this.transport.removeAllListeners();
+ }
+
+ // set up transport
+ this.transport = transport;
+
+ // set up transport listeners
+ transport
+ .on('drain', function(){
+ self.onDrain();
+ })
+ .on('packet', function(packet){
+ self.onPacket(packet);
+ })
+ .on('error', function(e){
+ self.onError(e);
+ })
+ .on('close', function(){
+ self.onClose('transport close');
+ });
+ };
+
+ /**
+ * Probes a transport.
+ *
+ * @param {String} transport name
+ * @api private
+ */
+
+ Socket.prototype.probe = function (name) {
+ debug('probing transport "%s"', name);
+ var transport = this.createTransport(name, { probe: 1 })
+ , failed = false
+ , self = this;
+
+ Socket.priorWebsocketSuccess = false;
+
+ function onTransportOpen(){
+ if (self.onlyBinaryUpgrades) {
+ var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
+ failed = failed || upgradeLosesBinary;
+ }
+ if (failed) return;
+
+ debug('probe transport "%s" opened', name);
+ transport.send([{ type: 'ping', data: 'probe' }]);
+ transport.once('packet', function (msg) {
+ if (failed) return;
+ if ('pong' == msg.type && 'probe' == msg.data) {
+ debug('probe transport "%s" pong', name);
+ self.upgrading = true;
+ self.emit('upgrading', transport);
+ if (!transport) return;
+ Socket.priorWebsocketSuccess = 'websocket' == transport.name;
+
+ debug('pausing current transport "%s"', self.transport.name);
+ self.transport.pause(function () {
+ if (failed) return;
+ if ('closed' == self.readyState) return;
+ debug('changing transport and sending upgrade packet');
+
+ cleanup();
+
+ self.setTransport(transport);
+ transport.send([{ type: 'upgrade' }]);
+ self.emit('upgrade', transport);
+ transport = null;
+ self.upgrading = false;
+ self.flush();
+ });
+ } else {
+ debug('probe transport "%s" failed', name);
+ var err = new Error('probe error');
+ err.transport = transport.name;
+ self.emit('upgradeError', err);
+ }
+ });
+ }
+
+ function freezeTransport() {
+ if (failed) return;
+
+ // Any callback called by transport should be ignored since now
+ failed = true;
+
+ cleanup();
+
+ transport.close();
+ transport = null;
+ }
+
+ //Handle any error that happens while probing
+ function onerror(err) {
+ var error = new Error('probe error: ' + err);
+ error.transport = transport.name;
+
+ freezeTransport();
+
+ debug('probe transport "%s" failed because of error: %s', name, err);
+
+ self.emit('upgradeError', error);
+ }
+
+ function onTransportClose(){
+ onerror("transport closed");
+ }
+
+ //When the socket is closed while we're probing
+ function onclose(){
+ onerror("socket closed");
+ }
+
+ //When the socket is upgraded while we're probing
+ function onupgrade(to){
+ if (transport && to.name != transport.name) {
+ debug('"%s" works - aborting "%s"', to.name, transport.name);
+ freezeTransport();
+ }
+ }
+
+ //Remove all listeners on the transport and on self
+ function cleanup(){
+ transport.removeListener('open', onTransportOpen);
+ transport.removeListener('error', onerror);
+ transport.removeListener('close', onTransportClose);
+ self.removeListener('close', onclose);
+ self.removeListener('upgrading', onupgrade);
+ }
+
+ transport.once('open', onTransportOpen);
+ transport.once('error', onerror);
+ transport.once('close', onTransportClose);
+
+ this.once('close', onclose);
+ this.once('upgrading', onupgrade);
+
+ transport.open();
+
+ };
+
+ /**
+ * Called when connection is deemed open.
+ *
+ * @api public
+ */
+
+ Socket.prototype.onOpen = function () {
+ debug('socket open');
+ this.readyState = 'open';
+ Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
+ this.emit('open');
+ this.flush();
+
+ // we check for `readyState` in case an `open`
+ // listener already closed the socket
+ if ('open' == this.readyState && this.upgrade && this.transport.pause) {
+ debug('starting upgrade probes');
+ for (var i = 0, l = this.upgrades.length; i < l; i++) {
+ this.probe(this.upgrades[i]);
+ }
+ }
+ };
+
+ /**
+ * Handles a packet.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onPacket = function (packet) {
+ if ('opening' == this.readyState || 'open' == this.readyState) {
+ debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
+
+ this.emit('packet', packet);
+
+ // Socket is live - any packet counts
+ this.emit('heartbeat');
+
+ switch (packet.type) {
+ case 'open':
+ this.onHandshake(parsejson(packet.data));
+ break;
+
+ case 'pong':
+ this.setPing();
+ break;
+
+ case 'error':
+ var err = new Error('server error');
+ err.code = packet.data;
+ this.emit('error', err);
+ break;
+
+ case 'message':
+ this.emit('data', packet.data);
+ this.emit('message', packet.data);
+ break;
+ }
+ } else {
+ debug('packet received with socket readyState "%s"', this.readyState);
+ }
+ };
+
+ /**
+ * Called upon handshake completion.
+ *
+ * @param {Object} handshake obj
+ * @api private
+ */
+
+ Socket.prototype.onHandshake = function (data) {
+ this.emit('handshake', data);
+ this.id = data.sid;
+ this.transport.query.sid = data.sid;
+ this.upgrades = this.filterUpgrades(data.upgrades);
+ this.pingInterval = data.pingInterval;
+ this.pingTimeout = data.pingTimeout;
+ this.onOpen();
+ // In case open handler closes socket
+ if ('closed' == this.readyState) return;
+ this.setPing();
+
+ // Prolong liveness of socket on heartbeat
+ this.removeListener('heartbeat', this.onHeartbeat);
+ this.on('heartbeat', this.onHeartbeat);
+ };
+
+ /**
+ * Resets ping timeout.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onHeartbeat = function (timeout) {
+ clearTimeout(this.pingTimeoutTimer);
+ var self = this;
+ self.pingTimeoutTimer = setTimeout(function () {
+ if ('closed' == self.readyState) return;
+ self.onClose('ping timeout');
+ }, timeout || (self.pingInterval + self.pingTimeout));
+ };
+
+ /**
+ * Pings server every `this.pingInterval` and expects response
+ * within `this.pingTimeout` or closes connection.
+ *
+ * @api private
+ */
+
+ Socket.prototype.setPing = function () {
+ var self = this;
+ clearTimeout(self.pingIntervalTimer);
+ self.pingIntervalTimer = setTimeout(function () {
+ debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
+ self.ping();
+ self.onHeartbeat(self.pingTimeout);
+ }, self.pingInterval);
+ };
+
+ /**
+ * Sends a ping packet.
+ *
+ * @api public
+ */
+
+ Socket.prototype.ping = function () {
+ this.sendPacket('ping');
+ };
+
+ /**
+ * Called on `drain` event
+ *
+ * @api private
+ */
+
+ Socket.prototype.onDrain = function() {
+ for (var i = 0; i < this.prevBufferLen; i++) {
+ if (this.callbackBuffer[i]) {
+ this.callbackBuffer[i]();
+ }
+ }
+
+ this.writeBuffer.splice(0, this.prevBufferLen);
+ this.callbackBuffer.splice(0, this.prevBufferLen);
+
+ // setting prevBufferLen = 0 is very important
+ // for example, when upgrading, upgrade packet is sent over,
+ // and a nonzero prevBufferLen could cause problems on `drain`
+ this.prevBufferLen = 0;
+
+ if (this.writeBuffer.length == 0) {
+ this.emit('drain');
+ } else {
+ this.flush();
+ }
+ };
+
+ /**
+ * Flush write buffers.
+ *
+ * @api private
+ */
+
+ Socket.prototype.flush = function () {
+ if ('closed' != this.readyState && this.transport.writable &&
+ !this.upgrading && this.writeBuffer.length) {
+ debug('flushing %d packets in socket', this.writeBuffer.length);
+ this.transport.send(this.writeBuffer);
+ // keep track of current length of writeBuffer
+ // splice writeBuffer and callbackBuffer on `drain`
+ this.prevBufferLen = this.writeBuffer.length;
+ this.emit('flush');
+ }
+ };
+
+ /**
+ * Sends a message.
+ *
+ * @param {String} message.
+ * @param {Function} callback function.
+ * @return {Socket} for chaining.
+ * @api public
+ */
+
+ Socket.prototype.write =
+ Socket.prototype.send = function (msg, fn) {
+ this.sendPacket('message', msg, fn);
+ return this;
+ };
+
+ /**
+ * Sends a packet.
+ *
+ * @param {String} packet type.
+ * @param {String} data.
+ * @param {Function} callback function.
+ * @api private
+ */
+
+ Socket.prototype.sendPacket = function (type, data, fn) {
+ if ('closing' == this.readyState || 'closed' == this.readyState) {
+ return;
+ }
+
+ var packet = { type: type, data: data };
+ this.emit('packetCreate', packet);
+ this.writeBuffer.push(packet);
+ this.callbackBuffer.push(fn);
+ this.flush();
+ };
+
+ /**
+ * Closes the connection.
+ *
+ * @api private
+ */
+
+ Socket.prototype.close = function () {
+ if ('opening' == this.readyState || 'open' == this.readyState) {
+ this.readyState = 'closing';
+
+ var self = this;
+
+ function close() {
+ self.onClose('forced close');
+ debug('socket closing - telling transport to close');
+ self.transport.close();
+ }
+
+ function cleanupAndClose() {
+ self.removeListener('upgrade', cleanupAndClose);
+ self.removeListener('upgradeError', cleanupAndClose);
+ close();
+ }
+
+ function waitForUpgrade() {
+ // wait for upgrade to finish since we can't send packets while pausing a transport
+ self.once('upgrade', cleanupAndClose);
+ self.once('upgradeError', cleanupAndClose);
+ }
+
+ if (this.writeBuffer.length) {
+ this.once('drain', function() {
+ if (this.upgrading) {
+ waitForUpgrade();
+ } else {
+ close();
+ }
+ });
+ } else if (this.upgrading) {
+ waitForUpgrade();
+ } else {
+ close();
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Called upon transport error
+ *
+ * @api private
+ */
+
+ Socket.prototype.onError = function (err) {
+ debug('socket error %j', err);
+ Socket.priorWebsocketSuccess = false;
+ this.emit('error', err);
+ this.onClose('transport error', err);
+ };
+
+ /**
+ * Called upon transport close.
+ *
+ * @api private
+ */
+
+ Socket.prototype.onClose = function (reason, desc) {
+ if ('opening' == this.readyState || 'open' == this.readyState || 'closing' == this.readyState) {
+ debug('socket close with reason: "%s"', reason);
+ var self = this;
+
+ // clear timers
+ clearTimeout(this.pingIntervalTimer);
+ clearTimeout(this.pingTimeoutTimer);
+
+ // clean buffers in next tick, so developers can still
+ // grab the buffers on `close` event
+ setTimeout(function() {
+ self.writeBuffer = [];
+ self.callbackBuffer = [];
+ self.prevBufferLen = 0;
+ }, 0);
+
+ // stop event from firing again for transport
+ this.transport.removeAllListeners('close');
+
+ // ensure transport won't stay open
+ this.transport.close();
+
+ // ignore further transport communication
+ this.transport.removeAllListeners();
+
+ // set ready state
+ this.readyState = 'closed';
+
+ // clear session id
+ this.id = null;
+
+ // emit close event
+ this.emit('close', reason, desc);
+ }
+ };
+
+ /**
+ * Filters upgrades, returning only those matching client transports.
+ *
+ * @param {Array} server upgrades
+ * @api private
+ *
+ */
+
+ Socket.prototype.filterUpgrades = function (upgrades) {
+ var filteredUpgrades = [];
+ for (var i = 0, j = upgrades.length; i';
+ iframe = document.createElement(html);
+ } catch (e) {
+ iframe = document.createElement('iframe');
+ iframe.name = self.iframeId;
+ iframe.src = 'javascript:0';
+ }
+
+ iframe.id = self.iframeId;
+
+ self.form.appendChild(iframe);
+ self.iframe = iframe;
+ }
+
+ initIframe();
+
+ // escape \n to prevent it from being converted into \r\n by some UAs
+ // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
+ data = data.replace(rEscapedNewline, '\\\n');
+ this.area.value = data.replace(rNewline, '\\n');
+
+ try {
+ this.form.submit();
+ } catch(e) {}
+
+ if (this.iframe.attachEvent) {
+ this.iframe.onreadystatechange = function(){
+ if (self.iframe.readyState == 'complete') {
+ complete();
+ }
+ };
+ } else {
+ this.iframe.onload = complete;
+ }
+ };
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){
+ (function (global){
+ /**
+ * Module requirements.
+ */
+
+ var XMLHttpRequest = _dereq_('xmlhttprequest');
+ var Polling = _dereq_('./polling');
+ var Emitter = _dereq_('component-emitter');
+ var inherit = _dereq_('component-inherit');
+ var debug = _dereq_('debug')('engine.io-client:polling-xhr');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = XHR;
+ module.exports.Request = Request;
+
+ /**
+ * Empty function
+ */
+
+ function empty(){}
+
+ /**
+ * XHR Polling constructor.
+ *
+ * @param {Object} opts
+ * @api public
+ */
+
+ function XHR(opts){
+ Polling.call(this, opts);
+
+ if (global.location) {
+ var isSSL = 'https:' == location.protocol;
+ var port = location.port;
+
+ // some user agents have empty `location.port`
+ if (!port) {
+ port = isSSL ? 443 : 80;
+ }
+
+ this.xd = opts.hostname != global.location.hostname ||
+ port != opts.port;
+ this.xs = opts.secure != isSSL;
+ }
+ }
+
+ /**
+ * Inherits from Polling.
+ */
+
+ inherit(XHR, Polling);
+
+ /**
+ * XHR supports binary
+ */
+
+ XHR.prototype.supportsBinary = true;
+
+ /**
+ * Creates a request.
+ *
+ * @param {String} method
+ * @api private
+ */
+
+ XHR.prototype.request = function(opts){
+ opts = opts || {};
+ opts.uri = this.uri();
+ opts.xd = this.xd;
+ opts.xs = this.xs;
+ opts.agent = this.agent || false;
+ opts.supportsBinary = this.supportsBinary;
+ opts.enablesXDR = this.enablesXDR;
+
+ // SSL options for Node.js client
+ opts.pfx = this.pfx;
+ opts.key = this.key;
+ opts.passphrase = this.passphrase;
+ opts.cert = this.cert;
+ opts.ca = this.ca;
+ opts.ciphers = this.ciphers;
+ opts.rejectUnauthorized = this.rejectUnauthorized;
+
+ return new Request(opts);
+ };
+
+ /**
+ * Sends data.
+ *
+ * @param {String} data to send.
+ * @param {Function} called upon flush.
+ * @api private
+ */
+
+ XHR.prototype.doWrite = function(data, fn){
+ var isBinary = typeof data !== 'string' && data !== undefined;
+ var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
+ var self = this;
+ req.on('success', fn);
+ req.on('error', function(err){
+ self.onError('xhr post error', err);
+ });
+ this.sendXhr = req;
+ };
+
+ /**
+ * Starts a poll cycle.
+ *
+ * @api private
+ */
+
+ XHR.prototype.doPoll = function(){
+ debug('xhr poll');
+ var req = this.request();
+ var self = this;
+ req.on('data', function(data){
+ self.onData(data);
+ });
+ req.on('error', function(err){
+ self.onError('xhr poll error', err);
+ });
+ this.pollXhr = req;
+ };
+
+ /**
+ * Request constructor
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+ function Request(opts){
+ this.method = opts.method || 'GET';
+ this.uri = opts.uri;
+ this.xd = !!opts.xd;
+ this.xs = !!opts.xs;
+ this.async = false !== opts.async;
+ this.data = undefined != opts.data ? opts.data : null;
+ this.agent = opts.agent;
+ this.isBinary = opts.isBinary;
+ this.supportsBinary = opts.supportsBinary;
+ this.enablesXDR = opts.enablesXDR;
+
+ // SSL options for Node.js client
+ this.pfx = opts.pfx;
+ this.key = opts.key;
+ this.passphrase = opts.passphrase;
+ this.cert = opts.cert;
+ this.ca = opts.ca;
+ this.ciphers = opts.ciphers;
+ this.rejectUnauthorized = opts.rejectUnauthorized;
+
+ this.create();
+ }
+
+ /**
+ * Mix in `Emitter`.
+ */
+
+ Emitter(Request.prototype);
+
+ /**
+ * Creates the XHR object and sends the request.
+ *
+ * @api private
+ */
+
+ Request.prototype.create = function(){
+ var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };
+
+ // SSL options for Node.js client
+ opts.pfx = this.pfx;
+ opts.key = this.key;
+ opts.passphrase = this.passphrase;
+ opts.cert = this.cert;
+ opts.ca = this.ca;
+ opts.ciphers = this.ciphers;
+ opts.rejectUnauthorized = this.rejectUnauthorized;
+
+ var xhr = this.xhr = new XMLHttpRequest(opts);
+ var self = this;
+
+ try {
+ debug('xhr open %s: %s', this.method, this.uri);
+ xhr.open(this.method, this.uri, this.async);
+ if (this.supportsBinary) {
+ // This has to be done after open because Firefox is stupid
+ // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
+ xhr.responseType = 'arraybuffer';
+ }
+
+ if ('POST' == this.method) {
+ try {
+ if (this.isBinary) {
+ xhr.setRequestHeader('Content-type', 'application/octet-stream');
+ } else {
+ xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
+ }
+ } catch (e) {}
+ }
+
+ // ie6 check
+ if ('withCredentials' in xhr) {
+ xhr.withCredentials = true;
+ }
+
+ if (this.hasXDR()) {
+ xhr.onload = function(){
+ self.onLoad();
+ };
+ xhr.onerror = function(){
+ self.onError(xhr.responseText);
+ };
+ } else {
+ xhr.onreadystatechange = function(){
+ if (4 != xhr.readyState) return;
+ if (200 == xhr.status || 1223 == xhr.status) {
+ self.onLoad();
+ } else {
+ // make sure the `error` event handler that's user-set
+ // does not throw in the same tick and gets caught here
+ setTimeout(function(){
+ self.onError(xhr.status);
+ }, 0);
+ }
+ };
+ }
+
+ debug('xhr data %s', this.data);
+ xhr.send(this.data);
+ } catch (e) {
+ // Need to defer since .create() is called directly fhrom the constructor
+ // and thus the 'error' event can only be only bound *after* this exception
+ // occurs. Therefore, also, we cannot throw here at all.
+ setTimeout(function() {
+ self.onError(e);
+ }, 0);
+ return;
+ }
+
+ if (global.document) {
+ this.index = Request.requestsCount++;
+ Request.requests[this.index] = this;
+ }
+ };
+
+ /**
+ * Called upon successful response.
+ *
+ * @api private
+ */
+
+ Request.prototype.onSuccess = function(){
+ this.emit('success');
+ this.cleanup();
+ };
+
+ /**
+ * Called if we have data.
+ *
+ * @api private
+ */
+
+ Request.prototype.onData = function(data){
+ this.emit('data', data);
+ this.onSuccess();
+ };
+
+ /**
+ * Called upon error.
+ *
+ * @api private
+ */
+
+ Request.prototype.onError = function(err){
+ this.emit('error', err);
+ this.cleanup(true);
+ };
+
+ /**
+ * Cleans up house.
+ *
+ * @api private
+ */
+
+ Request.prototype.cleanup = function(fromError){
+ if ('undefined' == typeof this.xhr || null === this.xhr) {
+ return;
+ }
+ // xmlhttprequest
+ if (this.hasXDR()) {
+ this.xhr.onload = this.xhr.onerror = empty;
+ } else {
+ this.xhr.onreadystatechange = empty;
+ }
+
+ if (fromError) {
+ try {
+ this.xhr.abort();
+ } catch(e) {}
+ }
+
+ if (global.document) {
+ delete Request.requests[this.index];
+ }
+
+ this.xhr = null;
+ };
+
+ /**
+ * Called upon load.
+ *
+ * @api private
+ */
+
+ Request.prototype.onLoad = function(){
+ var data;
+ try {
+ var contentType;
+ try {
+ contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0];
+ } catch (e) {}
+ if (contentType === 'application/octet-stream') {
+ data = this.xhr.response;
+ } else {
+ if (!this.supportsBinary) {
+ data = this.xhr.responseText;
+ } else {
+ data = 'ok';
+ }
+ }
+ } catch (e) {
+ this.onError(e);
+ }
+ if (null != data) {
+ this.onData(data);
+ }
+ };
+
+ /**
+ * Check if it has XDomainRequest.
+ *
+ * @api private
+ */
+
+ Request.prototype.hasXDR = function(){
+ return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
+ };
+
+ /**
+ * Aborts the request.
+ *
+ * @api public
+ */
+
+ Request.prototype.abort = function(){
+ this.cleanup();
+ };
+
+ /**
+ * Aborts pending requests when unloading the window. This is needed to prevent
+ * memory leaks (e.g. when using IE) and to ensure that no spurious error is
+ * emitted.
+ */
+
+ if (global.document) {
+ Request.requestsCount = 0;
+ Request.requests = {};
+ if (global.attachEvent) {
+ global.attachEvent('onunload', unloadHandler);
+ } else if (global.addEventListener) {
+ global.addEventListener('beforeunload', unloadHandler, false);
+ }
+ }
+
+ function unloadHandler() {
+ for (var i in Request.requests) {
+ if (Request.requests.hasOwnProperty(i)) {
+ Request.requests[i].abort();
+ }
+ }
+ }
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./polling":18,"component-emitter":9,"component-inherit":21,"debug":22,"xmlhttprequest":20}],18:[function(_dereq_,module,exports){
+ /**
+ * Module dependencies.
+ */
+
+ var Transport = _dereq_('../transport');
+ var parseqs = _dereq_('parseqs');
+ var parser = _dereq_('engine.io-parser');
+ var inherit = _dereq_('component-inherit');
+ var debug = _dereq_('debug')('engine.io-client:polling');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = Polling;
+
+ /**
+ * Is XHR2 supported?
+ */
+
+ var hasXHR2 = (function() {
+ var XMLHttpRequest = _dereq_('xmlhttprequest');
+ var xhr = new XMLHttpRequest({ xdomain: false });
+ return null != xhr.responseType;
+ })();
+
+ /**
+ * Polling interface.
+ *
+ * @param {Object} opts
+ * @api private
+ */
+
+ function Polling(opts){
+ var forceBase64 = (opts && opts.forceBase64);
+ if (!hasXHR2 || forceBase64) {
+ this.supportsBinary = false;
+ }
+ Transport.call(this, opts);
+ }
+
+ /**
+ * Inherits from Transport.
+ */
+
+ inherit(Polling, Transport);
+
+ /**
+ * Transport name.
+ */
+
+ Polling.prototype.name = 'polling';
+
+ /**
+ * Opens the socket (triggers polling). We write a PING message to determine
+ * when the transport is open.
+ *
+ * @api private
+ */
+
+ Polling.prototype.doOpen = function(){
+ this.poll();
+ };
+
+ /**
+ * Pauses polling.
+ *
+ * @param {Function} callback upon buffers are flushed and transport is paused
+ * @api private
+ */
+
+ Polling.prototype.pause = function(onPause){
+ var pending = 0;
+ var self = this;
+
+ this.readyState = 'pausing';
+
+ function pause(){
+ debug('paused');
+ self.readyState = 'paused';
+ onPause();
+ }
+
+ if (this.polling || !this.writable) {
+ var total = 0;
+
+ if (this.polling) {
+ debug('we are currently polling - waiting to pause');
+ total++;
+ this.once('pollComplete', function(){
+ debug('pre-pause polling complete');
+ --total || pause();
+ });
+ }
+
+ if (!this.writable) {
+ debug('we are currently writing - waiting to pause');
+ total++;
+ this.once('drain', function(){
+ debug('pre-pause writing complete');
+ --total || pause();
+ });
+ }
+ } else {
+ pause();
+ }
+ };
+
+ /**
+ * Starts polling cycle.
+ *
+ * @api public
+ */
+
+ Polling.prototype.poll = function(){
+ debug('polling');
+ this.polling = true;
+ this.doPoll();
+ this.emit('poll');
+ };
+
+ /**
+ * Overloads onData to detect payloads.
+ *
+ * @api private
+ */
+
+ Polling.prototype.onData = function(data){
+ var self = this;
+ debug('polling got data %s', data);
+ var callback = function(packet, index, total) {
+ // if its the first message we consider the transport open
+ if ('opening' == self.readyState) {
+ self.onOpen();
+ }
+
+ // if its a close packet, we close the ongoing requests
+ if ('close' == packet.type) {
+ self.onClose();
+ return false;
+ }
+
+ // otherwise bypass onData and handle the message
+ self.onPacket(packet);
+ };
+
+ // decode payload
+ parser.decodePayload(data, this.socket.binaryType, callback);
+
+ // if an event did not trigger closing
+ if ('closed' != this.readyState) {
+ // if we got data we're not polling
+ this.polling = false;
+ this.emit('pollComplete');
+
+ if ('open' == this.readyState) {
+ this.poll();
+ } else {
+ debug('ignoring poll - transport state "%s"', this.readyState);
+ }
+ }
+ };
+
+ /**
+ * For polling, send a close packet.
+ *
+ * @api private
+ */
+
+ Polling.prototype.doClose = function(){
+ var self = this;
+
+ function close(){
+ debug('writing close packet');
+ self.write([{ type: 'close' }]);
+ }
+
+ if ('open' == this.readyState) {
+ debug('transport open - closing');
+ close();
+ } else {
+ // in case we're trying to close while
+ // handshaking is in progress (GH-164)
+ debug('transport not open - deferring close');
+ this.once('open', close);
+ }
+ };
+
+ /**
+ * Writes a packets payload.
+ *
+ * @param {Array} data packets
+ * @param {Function} drain callback
+ * @api private
+ */
+
+ Polling.prototype.write = function(packets){
+ var self = this;
+ this.writable = false;
+ var callbackfn = function() {
+ self.writable = true;
+ self.emit('drain');
+ };
+
+ var self = this;
+ parser.encodePayload(packets, this.supportsBinary, function(data) {
+ self.doWrite(data, callbackfn);
+ });
+ };
+
+ /**
+ * Generates uri for connection.
+ *
+ * @api private
+ */
+
+ Polling.prototype.uri = function(){
+ var query = this.query || {};
+ var schema = this.secure ? 'https' : 'http';
+ var port = '';
+
+ // cache busting is forced
+ if (false !== this.timestampRequests) {
+ query[this.timestampParam] = +new Date + '-' + Transport.timestamps++;
+ }
+
+ if (!this.supportsBinary && !query.sid) {
+ query.b64 = 1;
+ }
+
+ query = parseqs.encode(query);
+
+ // avoid port if default for schema
+ if (this.port && (('https' == schema && this.port != 443) ||
+ ('http' == schema && this.port != 80))) {
+ port = ':' + this.port;
+ }
+
+ // prepend ? to query
+ if (query.length) {
+ query = '?' + query;
+ }
+
+ return schema + '://' + this.hostname + port + this.path + query;
+ };
+
+},{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"xmlhttprequest":20}],19:[function(_dereq_,module,exports){
+ /**
+ * Module dependencies.
+ */
+
+ var Transport = _dereq_('../transport');
+ var parser = _dereq_('engine.io-parser');
+ var parseqs = _dereq_('parseqs');
+ var inherit = _dereq_('component-inherit');
+ var debug = _dereq_('debug')('engine.io-client:websocket');
+
+ /**
+ * `ws` exposes a WebSocket-compatible interface in
+ * Node, or the `WebSocket` or `MozWebSocket` globals
+ * in the browser.
+ */
+
+ var WebSocket = _dereq_('ws');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = WS;
+
+ /**
+ * WebSocket transport constructor.
+ *
+ * @api {Object} connection options
+ * @api public
+ */
+
+ function WS(opts){
+ var forceBase64 = (opts && opts.forceBase64);
+ if (forceBase64) {
+ this.supportsBinary = false;
+ }
+ Transport.call(this, opts);
+ }
+
+ /**
+ * Inherits from Transport.
+ */
+
+ inherit(WS, Transport);
+
+ /**
+ * Transport name.
+ *
+ * @api public
+ */
+
+ WS.prototype.name = 'websocket';
+
+ /*
+ * WebSockets support binary
+ */
+
+ WS.prototype.supportsBinary = true;
+
+ /**
+ * Opens socket.
+ *
+ * @api private
+ */
+
+ WS.prototype.doOpen = function(){
+ if (!this.check()) {
+ // let probe timeout
+ return;
+ }
+
+ var self = this;
+ var uri = this.uri();
+ var protocols = void(0);
+ var opts = { agent: this.agent };
+
+ // SSL options for Node.js client
+ opts.pfx = this.pfx;
+ opts.key = this.key;
+ opts.passphrase = this.passphrase;
+ opts.cert = this.cert;
+ opts.ca = this.ca;
+ opts.ciphers = this.ciphers;
+ opts.rejectUnauthorized = this.rejectUnauthorized;
+
+ this.ws = new WebSocket(uri, protocols, opts);
+
+ if (this.ws.binaryType === undefined) {
+ this.supportsBinary = false;
+ }
+
+ this.ws.binaryType = 'arraybuffer';
+ this.addEventListeners();
+ };
+
+ /**
+ * Adds event listeners to the socket
+ *
+ * @api private
+ */
+
+ WS.prototype.addEventListeners = function(){
+ var self = this;
+
+ this.ws.onopen = function(){
+ self.onOpen();
+ };
+ this.ws.onclose = function(){
+ self.onClose();
+ };
+ this.ws.onmessage = function(ev){
+ self.onData(ev.data);
+ };
+ this.ws.onerror = function(e){
+ self.onError('websocket error', e);
+ };
+ };
+
+ /**
+ * Override `onData` to use a timer on iOS.
+ * See: https://gist.github.com/mloughran/2052006
+ *
+ * @api private
+ */
+
+ if ('undefined' != typeof navigator
+ && /iPad|iPhone|iPod/i.test(navigator.userAgent)) {
+ WS.prototype.onData = function(data){
+ var self = this;
+ setTimeout(function(){
+ Transport.prototype.onData.call(self, data);
+ }, 0);
+ };
+ }
+
+ /**
+ * Writes data to socket.
+ *
+ * @param {Array} array of packets.
+ * @api private
+ */
+
+ WS.prototype.write = function(packets){
+ var self = this;
+ this.writable = false;
+ // encodePacket efficient as it uses WS framing
+ // no need for encodePayload
+ for (var i = 0, l = packets.length; i < l; i++) {
+ parser.encodePacket(packets[i], this.supportsBinary, function(data) {
+ //Sometimes the websocket has already been closed but the browser didn't
+ //have a chance of informing us about it yet, in that case send will
+ //throw an error
+ try {
+ self.ws.send(data);
+ } catch (e){
+ debug('websocket closed before onclose event');
+ }
+ });
+ }
+
+ function ondrain() {
+ self.writable = true;
+ self.emit('drain');
+ }
+ // fake drain
+ // defer to next tick to allow Socket to clear writeBuffer
+ setTimeout(ondrain, 0);
+ };
+
+ /**
+ * Called upon close
+ *
+ * @api private
+ */
+
+ WS.prototype.onClose = function(){
+ Transport.prototype.onClose.call(this);
+ };
+
+ /**
+ * Closes socket.
+ *
+ * @api private
+ */
+
+ WS.prototype.doClose = function(){
+ if (typeof this.ws !== 'undefined') {
+ this.ws.close();
+ }
+ };
+
+ /**
+ * Generates uri for connection.
+ *
+ * @api private
+ */
+
+ WS.prototype.uri = function(){
+ var query = this.query || {};
+ var schema = this.secure ? 'wss' : 'ws';
+ var port = '';
+
+ // avoid port if default for schema
+ if (this.port && (('wss' == schema && this.port != 443)
+ || ('ws' == schema && this.port != 80))) {
+ port = ':' + this.port;
+ }
+
+ // append timestamp to URI
+ if (this.timestampRequests) {
+ query[this.timestampParam] = +new Date;
+ }
+
+ // communicate binary support capabilities
+ if (!this.supportsBinary) {
+ query.b64 = 1;
+ }
+
+ query = parseqs.encode(query);
+
+ // prepend ? to query
+ if (query.length) {
+ query = '?' + query;
+ }
+
+ return schema + '://' + this.hostname + port + this.path + query;
+ };
+
+ /**
+ * Feature detection for WebSocket.
+ *
+ * @return {Boolean} whether this transport is available.
+ * @api public
+ */
+
+ WS.prototype.check = function(){
+ return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
+ };
+
+},{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"ws":37}],20:[function(_dereq_,module,exports){
+// browser shim for xmlhttprequest module
+ var hasCORS = _dereq_('has-cors');
+
+ module.exports = function(opts) {
+ var xdomain = opts.xdomain;
+
+ // scheme must be same when usign XDomainRequest
+ // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
+ var xscheme = opts.xscheme;
+
+ // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
+ // https://github.com/Automattic/engine.io-client/pull/217
+ var enablesXDR = opts.enablesXDR;
+
+ // XMLHttpRequest can be disabled on IE
+ try {
+ if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) {
+ return new XMLHttpRequest();
+ }
+ } catch (e) { }
+
+ // Use XDomainRequest for IE8 if enablesXDR is true
+ // because loading bar keeps flashing when using jsonp-polling
+ // https://github.com/yujiosaka/socke.io-ie8-loading-example
+ try {
+ if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) {
+ return new XDomainRequest();
+ }
+ } catch (e) { }
+
+ if (!xdomain) {
+ try {
+ return new ActiveXObject('Microsoft.XMLHTTP');
+ } catch(e) { }
+ }
+ }
+
+},{"has-cors":40}],21:[function(_dereq_,module,exports){
+
+ module.exports = function(a, b){
+ var fn = function(){};
+ fn.prototype = b.prototype;
+ a.prototype = new fn;
+ a.prototype.constructor = a;
+ };
+},{}],22:[function(_dereq_,module,exports){
+
+ /**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+ exports = module.exports = _dereq_('./debug');
+ exports.log = log;
+ exports.formatArgs = formatArgs;
+ exports.save = save;
+ exports.load = load;
+ exports.useColors = useColors;
+
+ /**
+ * Colors.
+ */
+
+ exports.colors = [
+ 'lightseagreen',
+ 'forestgreen',
+ 'goldenrod',
+ 'dodgerblue',
+ 'darkorchid',
+ 'crimson'
+ ];
+
+ /**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+ function useColors() {
+ // is webkit? http://stackoverflow.com/a/16459606/376773
+ return ('WebkitAppearance' in document.documentElement.style) ||
+ // is firebug? http://stackoverflow.com/a/398120/376773
+ (window.console && (console.firebug || (console.exception && console.table))) ||
+ // is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
+ }
+
+ /**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+ exports.formatters.j = function(v) {
+ return JSON.stringify(v);
+ };
+
+
+ /**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+ function formatArgs() {
+ var args = arguments;
+ var useColors = this.useColors;
+
+ args[0] = (useColors ? '%c' : '')
+ + this.namespace
+ + (useColors ? ' %c' : ' ')
+ + args[0]
+ + (useColors ? '%c ' : ' ')
+ + '+' + exports.humanize(this.diff);
+
+ if (!useColors) return args;
+
+ var c = 'color: ' + this.color;
+ args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
+
+ // the final "%c" is somewhat tricky, because there could be other
+ // arguments passed either before or after the %c, so we need to
+ // figure out the correct index to insert the CSS into
+ var index = 0;
+ var lastC = 0;
+ args[0].replace(/%[a-z%]/g, function(match) {
+ if ('%' === match) return;
+ index++;
+ if ('%c' === match) {
+ // we only are interested in the *last* %c
+ // (the user may have provided their own)
+ lastC = index;
+ }
+ });
+
+ args.splice(lastC, 0, c);
+ return args;
+ }
+
+ /**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+ function log() {
+ // This hackery is required for IE8,
+ // where the `console.log` function doesn't have 'apply'
+ return 'object' == typeof console
+ && 'function' == typeof console.log
+ && Function.prototype.apply.call(console.log, console, arguments);
+ }
+
+ /**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+ function save(namespaces) {
+ try {
+ if (null == namespaces) {
+ localStorage.removeItem('debug');
+ } else {
+ localStorage.debug = namespaces;
+ }
+ } catch(e) {}
+ }
+
+ /**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+ function load() {
+ var r;
+ try {
+ r = localStorage.debug;
+ } catch(e) {}
+ return r;
+ }
+
+ /**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+ exports.enable(load());
+
+},{"./debug":23}],23:[function(_dereq_,module,exports){
+
+ /**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+ exports = module.exports = debug;
+ exports.coerce = coerce;
+ exports.disable = disable;
+ exports.enable = enable;
+ exports.enabled = enabled;
+ exports.humanize = _dereq_('ms');
+
+ /**
+ * The currently active debug mode names, and names to skip.
+ */
+
+ exports.names = [];
+ exports.skips = [];
+
+ /**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lowercased letter, i.e. "n".
+ */
+
+ exports.formatters = {};
+
+ /**
+ * Previously assigned color.
+ */
+
+ var prevColor = 0;
+
+ /**
+ * Previous log timestamp.
+ */
+
+ var prevTime;
+
+ /**
+ * Select a color.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+ function selectColor() {
+ return exports.colors[prevColor++ % exports.colors.length];
+ }
+
+ /**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+ function debug(namespace) {
+
+ // define the `disabled` version
+ function disabled() {
+ }
+ disabled.enabled = false;
+
+ // define the `enabled` version
+ function enabled() {
+
+ var self = enabled;
+
+ // set `diff` timestamp
+ var curr = +new Date();
+ var ms = curr - (prevTime || curr);
+ self.diff = ms;
+ self.prev = prevTime;
+ self.curr = curr;
+ prevTime = curr;
+
+ // add the `color` if not set
+ if (null == self.useColors) self.useColors = exports.useColors();
+ if (null == self.color && self.useColors) self.color = selectColor();
+
+ var args = Array.prototype.slice.call(arguments);
+
+ args[0] = exports.coerce(args[0]);
+
+ if ('string' !== typeof args[0]) {
+ // anything else let's inspect with %o
+ args = ['%o'].concat(args);
+ }
+
+ // apply any `formatters` transformations
+ var index = 0;
+ args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
+ // if we encounter an escaped % then don't increase the array index
+ if (match === '%') return match;
+ index++;
+ var formatter = exports.formatters[format];
+ if ('function' === typeof formatter) {
+ var val = args[index];
+ match = formatter.call(self, val);
+
+ // now we need to remove `args[index]` since it's inlined in the `format`
+ args.splice(index, 1);
+ index--;
+ }
+ return match;
+ });
+
+ if ('function' === typeof exports.formatArgs) {
+ args = exports.formatArgs.apply(self, args);
+ }
+ var logFn = enabled.log || exports.log || console.log.bind(console);
+ logFn.apply(self, args);
+ }
+ enabled.enabled = true;
+
+ var fn = exports.enabled(namespace) ? enabled : disabled;
+
+ fn.namespace = namespace;
+
+ return fn;
+ }
+
+ /**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+ function enable(namespaces) {
+ exports.save(namespaces);
+
+ var split = (namespaces || '').split(/[\s,]+/);
+ var len = split.length;
+
+ for (var i = 0; i < len; i++) {
+ if (!split[i]) continue; // ignore empty strings
+ namespaces = split[i].replace(/\*/g, '.*?');
+ if (namespaces[0] === '-') {
+ exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+ } else {
+ exports.names.push(new RegExp('^' + namespaces + '$'));
+ }
+ }
+ }
+
+ /**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+ function disable() {
+ exports.enable('');
+ }
+
+ /**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+ function enabled(name) {
+ var i, len;
+ for (i = 0, len = exports.skips.length; i < len; i++) {
+ if (exports.skips[i].test(name)) {
+ return false;
+ }
+ }
+ for (i = 0, len = exports.names.length; i < len; i++) {
+ if (exports.names[i].test(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+ function coerce(val) {
+ if (val instanceof Error) return val.stack || val.message;
+ return val;
+ }
+
+},{"ms":24}],24:[function(_dereq_,module,exports){
+ /**
+ * Helpers.
+ */
+
+ var s = 1000;
+ var m = s * 60;
+ var h = m * 60;
+ var d = h * 24;
+ var y = d * 365.25;
+
+ /**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} options
+ * @return {String|Number}
+ * @api public
+ */
+
+ module.exports = function(val, options){
+ options = options || {};
+ if ('string' == typeof val) return parse(val);
+ return options.long
+ ? long(val)
+ : short(val);
+ };
+
+ /**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+ function parse(str) {
+ var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
+ if (!match) return;
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'y':
+ return n * y;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 's':
+ return n * s;
+ case 'ms':
+ return n;
+ }
+ }
+
+ /**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+ function short(ms) {
+ if (ms >= d) return Math.round(ms / d) + 'd';
+ if (ms >= h) return Math.round(ms / h) + 'h';
+ if (ms >= m) return Math.round(ms / m) + 'm';
+ if (ms >= s) return Math.round(ms / s) + 's';
+ return ms + 'ms';
+ }
+
+ /**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+ function long(ms) {
+ return plural(ms, d, 'day')
+ || plural(ms, h, 'hour')
+ || plural(ms, m, 'minute')
+ || plural(ms, s, 'second')
+ || ms + ' ms';
+ }
+
+ /**
+ * Pluralization helper.
+ */
+
+ function plural(ms, n, name) {
+ if (ms < n) return;
+ if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
+ return Math.ceil(ms / n) + ' ' + name + 's';
+ }
+
+},{}],25:[function(_dereq_,module,exports){
+ (function (global){
+ /**
+ * Module dependencies.
+ */
+
+ var keys = _dereq_('./keys');
+ var hasBinary = _dereq_('has-binary');
+ var sliceBuffer = _dereq_('arraybuffer.slice');
+ var base64encoder = _dereq_('base64-arraybuffer');
+ var after = _dereq_('after');
+ var utf8 = _dereq_('utf8');
+
+ /**
+ * Check if we are running an android browser. That requires us to use
+ * ArrayBuffer with polling transports...
+ *
+ * http://ghinda.net/jpeg-blob-ajax-android/
+ */
+
+ var isAndroid = navigator.userAgent.match(/Android/i);
+
+ /**
+ * Check if we are running in PhantomJS.
+ * Uploading a Blob with PhantomJS does not work correctly, as reported here:
+ * https://github.com/ariya/phantomjs/issues/11395
+ * @type boolean
+ */
+ var isPhantomJS = /PhantomJS/i.test(navigator.userAgent);
+
+ /**
+ * When true, avoids using Blobs to encode payloads.
+ * @type boolean
+ */
+ var dontSendBlobs = isAndroid || isPhantomJS;
+
+ /**
+ * Current protocol version.
+ */
+
+ exports.protocol = 3;
+
+ /**
+ * Packet types.
+ */
+
+ var packets = exports.packets = {
+ open: 0 // non-ws
+ , close: 1 // non-ws
+ , ping: 2
+ , pong: 3
+ , message: 4
+ , upgrade: 5
+ , noop: 6
+ };
+
+ var packetslist = keys(packets);
+
+ /**
+ * Premade error packet.
+ */
+
+ var err = { type: 'error', data: 'parser error' };
+
+ /**
+ * Create a blob api even for blob builder when vendor prefixes exist
+ */
+
+ var Blob = _dereq_('blob');
+
+ /**
+ * Encodes a packet.
+ *
+ * [ ]
+ *
+ * Example:
+ *
+ * 5hello world
+ * 3
+ * 4
+ *
+ * Binary is encoded in an identical principle
+ *
+ * @api private
+ */
+
+ exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
+ if ('function' == typeof supportsBinary) {
+ callback = supportsBinary;
+ supportsBinary = false;
+ }
+
+ if ('function' == typeof utf8encode) {
+ callback = utf8encode;
+ utf8encode = null;
+ }
+
+ var data = (packet.data === undefined)
+ ? undefined
+ : packet.data.buffer || packet.data;
+
+ if (global.ArrayBuffer && data instanceof ArrayBuffer) {
+ return encodeArrayBuffer(packet, supportsBinary, callback);
+ } else if (Blob && data instanceof global.Blob) {
+ return encodeBlob(packet, supportsBinary, callback);
+ }
+
+ // might be an object with { base64: true, data: dataAsBase64String }
+ if (data && data.base64) {
+ return encodeBase64Object(packet, callback);
+ }
+
+ // Sending data as a utf-8 string
+ var encoded = packets[packet.type];
+
+ // data fragment is optional
+ if (undefined !== packet.data) {
+ encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data);
+ }
+
+ return callback('' + encoded);
+
+ };
+
+ function encodeBase64Object(packet, callback) {
+ // packet data is an object { base64: true, data: dataAsBase64String }
+ var message = 'b' + exports.packets[packet.type] + packet.data.data;
+ return callback(message);
+ }
+
+ /**
+ * Encode packet helpers for binary types
+ */
+
+ function encodeArrayBuffer(packet, supportsBinary, callback) {
+ if (!supportsBinary) {
+ return exports.encodeBase64Packet(packet, callback);
+ }
+
+ var data = packet.data;
+ var contentArray = new Uint8Array(data);
+ var resultBuffer = new Uint8Array(1 + data.byteLength);
+
+ resultBuffer[0] = packets[packet.type];
+ for (var i = 0; i < contentArray.length; i++) {
+ resultBuffer[i+1] = contentArray[i];
+ }
+
+ return callback(resultBuffer.buffer);
+ }
+
+ function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
+ if (!supportsBinary) {
+ return exports.encodeBase64Packet(packet, callback);
+ }
+
+ var fr = new FileReader();
+ fr.onload = function() {
+ packet.data = fr.result;
+ exports.encodePacket(packet, supportsBinary, true, callback);
+ };
+ return fr.readAsArrayBuffer(packet.data);
+ }
+
+ function encodeBlob(packet, supportsBinary, callback) {
+ if (!supportsBinary) {
+ return exports.encodeBase64Packet(packet, callback);
+ }
+
+ if (dontSendBlobs) {
+ return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
+ }
+
+ var length = new Uint8Array(1);
+ length[0] = packets[packet.type];
+ var blob = new Blob([length.buffer, packet.data]);
+
+ return callback(blob);
+ }
+
+ /**
+ * Encodes a packet with binary data in a base64 string
+ *
+ * @param {Object} packet, has `type` and `data`
+ * @return {String} base64 encoded message
+ */
+
+ exports.encodeBase64Packet = function(packet, callback) {
+ var message = 'b' + exports.packets[packet.type];
+ if (Blob && packet.data instanceof Blob) {
+ var fr = new FileReader();
+ fr.onload = function() {
+ var b64 = fr.result.split(',')[1];
+ callback(message + b64);
+ };
+ return fr.readAsDataURL(packet.data);
+ }
+
+ var b64data;
+ try {
+ b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
+ } catch (e) {
+ // iPhone Safari doesn't let you apply with typed arrays
+ var typed = new Uint8Array(packet.data);
+ var basic = new Array(typed.length);
+ for (var i = 0; i < typed.length; i++) {
+ basic[i] = typed[i];
+ }
+ b64data = String.fromCharCode.apply(null, basic);
+ }
+ message += global.btoa(b64data);
+ return callback(message);
+ };
+
+ /**
+ * Decodes a packet. Changes format to Blob if requested.
+ *
+ * @return {Object} with `type` and `data` (if any)
+ * @api private
+ */
+
+ exports.decodePacket = function (data, binaryType, utf8decode) {
+ // String data
+ if (typeof data == 'string' || data === undefined) {
+ if (data.charAt(0) == 'b') {
+ return exports.decodeBase64Packet(data.substr(1), binaryType);
+ }
+
+ if (utf8decode) {
+ try {
+ data = utf8.decode(data);
+ } catch (e) {
+ return err;
+ }
+ }
+ var type = data.charAt(0);
+
+ if (Number(type) != type || !packetslist[type]) {
+ return err;
+ }
+
+ if (data.length > 1) {
+ return { type: packetslist[type], data: data.substring(1) };
+ } else {
+ return { type: packetslist[type] };
+ }
+ }
+
+ var asArray = new Uint8Array(data);
+ var type = asArray[0];
+ var rest = sliceBuffer(data, 1);
+ if (Blob && binaryType === 'blob') {
+ rest = new Blob([rest]);
+ }
+ return { type: packetslist[type], data: rest };
+ };
+
+ /**
+ * Decodes a packet encoded in a base64 string
+ *
+ * @param {String} base64 encoded message
+ * @return {Object} with `type` and `data` (if any)
+ */
+
+ exports.decodeBase64Packet = function(msg, binaryType) {
+ var type = packetslist[msg.charAt(0)];
+ if (!global.ArrayBuffer) {
+ return { type: type, data: { base64: true, data: msg.substr(1) } };
+ }
+
+ var data = base64encoder.decode(msg.substr(1));
+
+ if (binaryType === 'blob' && Blob) {
+ data = new Blob([data]);
+ }
+
+ return { type: type, data: data };
+ };
+
+ /**
+ * Encodes multiple messages (payload).
+ *
+ * :data
+ *
+ * Example:
+ *
+ * 11:hello world2:hi
+ *
+ * If any contents are binary, they will be encoded as base64 strings. Base64
+ * encoded strings are marked with a b before the length specifier
+ *
+ * @param {Array} packets
+ * @api private
+ */
+
+ exports.encodePayload = function (packets, supportsBinary, callback) {
+ if (typeof supportsBinary == 'function') {
+ callback = supportsBinary;
+ supportsBinary = null;
+ }
+
+ var isBinary = hasBinary(packets);
+
+ if (supportsBinary && isBinary) {
+ if (Blob && !dontSendBlobs) {
+ return exports.encodePayloadAsBlob(packets, callback);
+ }
+
+ return exports.encodePayloadAsArrayBuffer(packets, callback);
+ }
+
+ if (!packets.length) {
+ return callback('0:');
+ }
+
+ function setLengthHeader(message) {
+ return message.length + ':' + message;
+ }
+
+ function encodeOne(packet, doneCallback) {
+ exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) {
+ doneCallback(null, setLengthHeader(message));
+ });
+ }
+
+ map(packets, encodeOne, function(err, results) {
+ return callback(results.join(''));
+ });
+ };
+
+ /**
+ * Async array map using after
+ */
+
+ function map(ary, each, done) {
+ var result = new Array(ary.length);
+ var next = after(ary.length, done);
+
+ var eachWithIndex = function(i, el, cb) {
+ each(el, function(error, msg) {
+ result[i] = msg;
+ cb(error, result);
+ });
+ };
+
+ for (var i = 0; i < ary.length; i++) {
+ eachWithIndex(i, ary[i], next);
+ }
+ }
+
+ /*
+ * Decodes data when a payload is maybe expected. Possible binary contents are
+ * decoded from their base64 representation
+ *
+ * @param {String} data, callback method
+ * @api public
+ */
+
+ exports.decodePayload = function (data, binaryType, callback) {
+ if (typeof data != 'string') {
+ return exports.decodePayloadAsBinary(data, binaryType, callback);
+ }
+
+ if (typeof binaryType === 'function') {
+ callback = binaryType;
+ binaryType = null;
+ }
+
+ var packet;
+ if (data == '') {
+ // parser error - ignoring payload
+ return callback(err, 0, 1);
+ }
+
+ var length = ''
+ , n, msg;
+
+ for (var i = 0, l = data.length; i < l; i++) {
+ var chr = data.charAt(i);
+
+ if (':' != chr) {
+ length += chr;
+ } else {
+ if ('' == length || (length != (n = Number(length)))) {
+ // parser error - ignoring payload
+ return callback(err, 0, 1);
+ }
+
+ msg = data.substr(i + 1, n);
+
+ if (length != msg.length) {
+ // parser error - ignoring payload
+ return callback(err, 0, 1);
+ }
+
+ if (msg.length) {
+ packet = exports.decodePacket(msg, binaryType, true);
+
+ if (err.type == packet.type && err.data == packet.data) {
+ // parser error in individual packet - ignoring payload
+ return callback(err, 0, 1);
+ }
+
+ var ret = callback(packet, i + n, l);
+ if (false === ret) return;
+ }
+
+ // advance cursor
+ i += n;
+ length = '';
+ }
+ }
+
+ if (length != '') {
+ // parser error - ignoring payload
+ return callback(err, 0, 1);
+ }
+
+ };
+
+ /**
+ * Encodes multiple messages (payload) as binary.
+ *
+ * <1 = binary, 0 = string>[...]
+ *
+ * Example:
+ * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
+ *
+ * @param {Array} packets
+ * @return {ArrayBuffer} encoded payload
+ * @api private
+ */
+
+ exports.encodePayloadAsArrayBuffer = function(packets, callback) {
+ if (!packets.length) {
+ return callback(new ArrayBuffer(0));
+ }
+
+ function encodeOne(packet, doneCallback) {
+ exports.encodePacket(packet, true, true, function(data) {
+ return doneCallback(null, data);
+ });
+ }
+
+ map(packets, encodeOne, function(err, encodedPackets) {
+ var totalLength = encodedPackets.reduce(function(acc, p) {
+ var len;
+ if (typeof p === 'string'){
+ len = p.length;
+ } else {
+ len = p.byteLength;
+ }
+ return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
+ }, 0);
+
+ var resultArray = new Uint8Array(totalLength);
+
+ var bufferIndex = 0;
+ encodedPackets.forEach(function(p) {
+ var isString = typeof p === 'string';
+ var ab = p;
+ if (isString) {
+ var view = new Uint8Array(p.length);
+ for (var i = 0; i < p.length; i++) {
+ view[i] = p.charCodeAt(i);
+ }
+ ab = view.buffer;
+ }
+
+ if (isString) { // not true binary
+ resultArray[bufferIndex++] = 0;
+ } else { // true binary
+ resultArray[bufferIndex++] = 1;
+ }
+
+ var lenStr = ab.byteLength.toString();
+ for (var i = 0; i < lenStr.length; i++) {
+ resultArray[bufferIndex++] = parseInt(lenStr[i]);
+ }
+ resultArray[bufferIndex++] = 255;
+
+ var view = new Uint8Array(ab);
+ for (var i = 0; i < view.length; i++) {
+ resultArray[bufferIndex++] = view[i];
+ }
+ });
+
+ return callback(resultArray.buffer);
+ });
+ };
+
+ /**
+ * Encode as Blob
+ */
+
+ exports.encodePayloadAsBlob = function(packets, callback) {
+ function encodeOne(packet, doneCallback) {
+ exports.encodePacket(packet, true, true, function(encoded) {
+ var binaryIdentifier = new Uint8Array(1);
+ binaryIdentifier[0] = 1;
+ if (typeof encoded === 'string') {
+ var view = new Uint8Array(encoded.length);
+ for (var i = 0; i < encoded.length; i++) {
+ view[i] = encoded.charCodeAt(i);
+ }
+ encoded = view.buffer;
+ binaryIdentifier[0] = 0;
+ }
+
+ var len = (encoded instanceof ArrayBuffer)
+ ? encoded.byteLength
+ : encoded.size;
+
+ var lenStr = len.toString();
+ var lengthAry = new Uint8Array(lenStr.length + 1);
+ for (var i = 0; i < lenStr.length; i++) {
+ lengthAry[i] = parseInt(lenStr[i]);
+ }
+ lengthAry[lenStr.length] = 255;
+
+ if (Blob) {
+ var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
+ doneCallback(null, blob);
+ }
+ });
+ }
+
+ map(packets, encodeOne, function(err, results) {
+ return callback(new Blob(results));
+ });
+ };
+
+ /*
+ * Decodes data when a payload is maybe expected. Strings are decoded by
+ * interpreting each byte as a key code for entries marked to start with 0. See
+ * description of encodePayloadAsBinary
+ *
+ * @param {ArrayBuffer} data, callback method
+ * @api public
+ */
+
+ exports.decodePayloadAsBinary = function (data, binaryType, callback) {
+ if (typeof binaryType === 'function') {
+ callback = binaryType;
+ binaryType = null;
+ }
+
+ var bufferTail = data;
+ var buffers = [];
+
+ var numberTooLong = false;
+ while (bufferTail.byteLength > 0) {
+ var tailArray = new Uint8Array(bufferTail);
+ var isString = tailArray[0] === 0;
+ var msgLength = '';
+
+ for (var i = 1; ; i++) {
+ if (tailArray[i] == 255) break;
+
+ if (msgLength.length > 310) {
+ numberTooLong = true;
+ break;
+ }
+
+ msgLength += tailArray[i];
+ }
+
+ if(numberTooLong) return callback(err, 0, 1);
+
+ bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
+ msgLength = parseInt(msgLength);
+
+ var msg = sliceBuffer(bufferTail, 0, msgLength);
+ if (isString) {
+ try {
+ msg = String.fromCharCode.apply(null, new Uint8Array(msg));
+ } catch (e) {
+ // iPhone Safari doesn't let you apply to typed arrays
+ var typed = new Uint8Array(msg);
+ msg = '';
+ for (var i = 0; i < typed.length; i++) {
+ msg += String.fromCharCode(typed[i]);
+ }
+ }
+ }
+
+ buffers.push(msg);
+ bufferTail = sliceBuffer(bufferTail, msgLength);
+ }
+
+ var total = buffers.length;
+ buffers.forEach(function(buffer, i) {
+ callback(exports.decodePacket(buffer, binaryType, true), i, total);
+ });
+ };
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./keys":26,"after":27,"arraybuffer.slice":28,"base64-arraybuffer":29,"blob":30,"has-binary":31,"utf8":33}],26:[function(_dereq_,module,exports){
+
+ /**
+ * Gets the keys for an object.
+ *
+ * @return {Array} keys
+ * @api private
+ */
+
+ module.exports = Object.keys || function keys (obj){
+ var arr = [];
+ var has = Object.prototype.hasOwnProperty;
+
+ for (var i in obj) {
+ if (has.call(obj, i)) {
+ arr.push(i);
+ }
+ }
+ return arr;
+ };
+
+},{}],27:[function(_dereq_,module,exports){
+ module.exports = after
+
+ function after(count, callback, err_cb) {
+ var bail = false
+ err_cb = err_cb || noop
+ proxy.count = count
+
+ return (count === 0) ? callback() : proxy
+
+ function proxy(err, result) {
+ if (proxy.count <= 0) {
+ throw new Error('after called too many times')
+ }
+ --proxy.count
+
+ // after first error, rest are passed to err_cb
+ if (err) {
+ bail = true
+ callback(err)
+ // future error callbacks will go to error handler
+ callback = err_cb
+ } else if (proxy.count === 0 && !bail) {
+ callback(null, result)
+ }
+ }
+ }
+
+ function noop() {}
+
+},{}],28:[function(_dereq_,module,exports){
+ /**
+ * An abstraction for slicing an arraybuffer even when
+ * ArrayBuffer.prototype.slice is not supported
+ *
+ * @api public
+ */
+
+ module.exports = function(arraybuffer, start, end) {
+ var bytes = arraybuffer.byteLength;
+ start = start || 0;
+ end = end || bytes;
+
+ if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
+
+ if (start < 0) { start += bytes; }
+ if (end < 0) { end += bytes; }
+ if (end > bytes) { end = bytes; }
+
+ if (start >= bytes || start >= end || bytes === 0) {
+ return new ArrayBuffer(0);
+ }
+
+ var abv = new Uint8Array(arraybuffer);
+ var result = new Uint8Array(end - start);
+ for (var i = start, ii = 0; i < end; i++, ii++) {
+ result[ii] = abv[i];
+ }
+ return result.buffer;
+ };
+
+},{}],29:[function(_dereq_,module,exports){
+ /*
+ * base64-arraybuffer
+ * https://github.com/niklasvh/base64-arraybuffer
+ *
+ * Copyright (c) 2012 Niklas von Hertzen
+ * Licensed under the MIT license.
+ */
+ (function(chars){
+ "use strict";
+
+ exports.encode = function(arraybuffer) {
+ var bytes = new Uint8Array(arraybuffer),
+ i, len = bytes.length, base64 = "";
+
+ for (i = 0; i < len; i+=3) {
+ base64 += chars[bytes[i] >> 2];
+ base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
+ base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
+ base64 += chars[bytes[i + 2] & 63];
+ }
+
+ if ((len % 3) === 2) {
+ base64 = base64.substring(0, base64.length - 1) + "=";
+ } else if (len % 3 === 1) {
+ base64 = base64.substring(0, base64.length - 2) + "==";
+ }
+
+ return base64;
+ };
+
+ exports.decode = function(base64) {
+ var bufferLength = base64.length * 0.75,
+ len = base64.length, i, p = 0,
+ encoded1, encoded2, encoded3, encoded4;
+
+ if (base64[base64.length - 1] === "=") {
+ bufferLength--;
+ if (base64[base64.length - 2] === "=") {
+ bufferLength--;
+ }
+ }
+
+ var arraybuffer = new ArrayBuffer(bufferLength),
+ bytes = new Uint8Array(arraybuffer);
+
+ for (i = 0; i < len; i+=4) {
+ encoded1 = chars.indexOf(base64[i]);
+ encoded2 = chars.indexOf(base64[i+1]);
+ encoded3 = chars.indexOf(base64[i+2]);
+ encoded4 = chars.indexOf(base64[i+3]);
+
+ bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
+ bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
+ bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
+ }
+
+ return arraybuffer;
+ };
+ })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
+
+},{}],30:[function(_dereq_,module,exports){
+ (function (global){
+ /**
+ * Create a blob builder even when vendor prefixes exist
+ */
+
+ var BlobBuilder = global.BlobBuilder
+ || global.WebKitBlobBuilder
+ || global.MSBlobBuilder
+ || global.MozBlobBuilder;
+
+ /**
+ * Check if Blob constructor is supported
+ */
+
+ var blobSupported = (function() {
+ try {
+ var b = new Blob(['hi']);
+ return b.size == 2;
+ } catch(e) {
+ return false;
+ }
+ })();
+
+ /**
+ * Check if BlobBuilder is supported
+ */
+
+ var blobBuilderSupported = BlobBuilder
+ && BlobBuilder.prototype.append
+ && BlobBuilder.prototype.getBlob;
+
+ function BlobBuilderConstructor(ary, options) {
+ options = options || {};
+
+ var bb = new BlobBuilder();
+ for (var i = 0; i < ary.length; i++) {
+ bb.append(ary[i]);
+ }
+ return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
+ };
+
+ module.exports = (function() {
+ if (blobSupported) {
+ return global.Blob;
+ } else if (blobBuilderSupported) {
+ return BlobBuilderConstructor;
+ } else {
+ return undefined;
+ }
+ })();
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],31:[function(_dereq_,module,exports){
+ (function (global){
+
+ /*
+ * Module requirements.
+ */
+
+ var isArray = _dereq_('isarray');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = hasBinary;
+
+ /**
+ * Checks for binary data.
+ *
+ * Right now only Buffer and ArrayBuffer are supported..
+ *
+ * @param {Object} anything
+ * @api public
+ */
+
+ function hasBinary(data) {
+
+ function _hasBinary(obj) {
+ if (!obj) return false;
+
+ if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
+ (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
+ (global.Blob && obj instanceof Blob) ||
+ (global.File && obj instanceof File)
+ ) {
+ return true;
+ }
+
+ if (isArray(obj)) {
+ for (var i = 0; i < obj.length; i++) {
+ if (_hasBinary(obj[i])) {
+ return true;
+ }
+ }
+ } else if (obj && 'object' == typeof obj) {
+ if (obj.toJSON) {
+ obj = obj.toJSON();
+ }
+
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key) && _hasBinary(obj[key])) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ return _hasBinary(data);
+ }
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"isarray":32}],32:[function(_dereq_,module,exports){
+ module.exports = Array.isArray || function (arr) {
+ return Object.prototype.toString.call(arr) == '[object Array]';
+ };
+
+},{}],33:[function(_dereq_,module,exports){
+ (function (global){
+ /*! http://mths.be/utf8js v2.0.0 by @mathias */
+ ;(function(root) {
+
+ // Detect free variables `exports`
+ var freeExports = typeof exports == 'object' && exports;
+
+ // Detect free variable `module`
+ var freeModule = typeof module == 'object' && module &&
+ module.exports == freeExports && module;
+
+ // Detect free variable `global`, from Node.js or Browserified code,
+ // and use it as `root`
+ var freeGlobal = typeof global == 'object' && global;
+ if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
+ root = freeGlobal;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ var stringFromCharCode = String.fromCharCode;
+
+ // Taken from http://mths.be/punycode
+ function ucs2decode(string) {
+ var output = [];
+ var counter = 0;
+ var length = string.length;
+ var value;
+ var extra;
+ while (counter < length) {
+ value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // high surrogate, and there is a next character
+ extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // unmatched surrogate; only append this code unit, in case the next
+ // code unit is the high surrogate of a surrogate pair
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+ }
+
+ // Taken from http://mths.be/punycode
+ function ucs2encode(array) {
+ var length = array.length;
+ var index = -1;
+ var value;
+ var output = '';
+ while (++index < length) {
+ value = array[index];
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+ value = 0xDC00 | value & 0x3FF;
+ }
+ output += stringFromCharCode(value);
+ }
+ return output;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ function createByte(codePoint, shift) {
+ return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
+ }
+
+ function encodeCodePoint(codePoint) {
+ if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
+ return stringFromCharCode(codePoint);
+ }
+ var symbol = '';
+ if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
+ symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
+ }
+ else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
+ symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
+ symbol += createByte(codePoint, 6);
+ }
+ else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
+ symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
+ symbol += createByte(codePoint, 12);
+ symbol += createByte(codePoint, 6);
+ }
+ symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
+ return symbol;
+ }
+
+ function utf8encode(string) {
+ var codePoints = ucs2decode(string);
+
+ // console.log(JSON.stringify(codePoints.map(function(x) {
+ // return 'U+' + x.toString(16).toUpperCase();
+ // })));
+
+ var length = codePoints.length;
+ var index = -1;
+ var codePoint;
+ var byteString = '';
+ while (++index < length) {
+ codePoint = codePoints[index];
+ byteString += encodeCodePoint(codePoint);
+ }
+ return byteString;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ function readContinuationByte() {
+ if (byteIndex >= byteCount) {
+ throw Error('Invalid byte index');
+ }
+
+ var continuationByte = byteArray[byteIndex] & 0xFF;
+ byteIndex++;
+
+ if ((continuationByte & 0xC0) == 0x80) {
+ return continuationByte & 0x3F;
+ }
+
+ // If we end up here, it¡¯s not a continuation byte
+ throw Error('Invalid continuation byte');
+ }
+
+ function decodeSymbol() {
+ var byte1;
+ var byte2;
+ var byte3;
+ var byte4;
+ var codePoint;
+
+ if (byteIndex > byteCount) {
+ throw Error('Invalid byte index');
+ }
+
+ if (byteIndex == byteCount) {
+ return false;
+ }
+
+ // Read first byte
+ byte1 = byteArray[byteIndex] & 0xFF;
+ byteIndex++;
+
+ // 1-byte sequence (no continuation bytes)
+ if ((byte1 & 0x80) == 0) {
+ return byte1;
+ }
+
+ // 2-byte sequence
+ if ((byte1 & 0xE0) == 0xC0) {
+ var byte2 = readContinuationByte();
+ codePoint = ((byte1 & 0x1F) << 6) | byte2;
+ if (codePoint >= 0x80) {
+ return codePoint;
+ } else {
+ throw Error('Invalid continuation byte');
+ }
+ }
+
+ // 3-byte sequence (may include unpaired surrogates)
+ if ((byte1 & 0xF0) == 0xE0) {
+ byte2 = readContinuationByte();
+ byte3 = readContinuationByte();
+ codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
+ if (codePoint >= 0x0800) {
+ return codePoint;
+ } else {
+ throw Error('Invalid continuation byte');
+ }
+ }
+
+ // 4-byte sequence
+ if ((byte1 & 0xF8) == 0xF0) {
+ byte2 = readContinuationByte();
+ byte3 = readContinuationByte();
+ byte4 = readContinuationByte();
+ codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
+ (byte3 << 0x06) | byte4;
+ if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
+ return codePoint;
+ }
+ }
+
+ throw Error('Invalid UTF-8 detected');
+ }
+
+ var byteArray;
+ var byteCount;
+ var byteIndex;
+ function utf8decode(byteString) {
+ byteArray = ucs2decode(byteString);
+ byteCount = byteArray.length;
+ byteIndex = 0;
+ var codePoints = [];
+ var tmp;
+ while ((tmp = decodeSymbol()) !== false) {
+ codePoints.push(tmp);
+ }
+ return ucs2encode(codePoints);
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ var utf8 = {
+ 'version': '2.0.0',
+ 'encode': utf8encode,
+ 'decode': utf8decode
+ };
+
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ typeof define == 'function' &&
+ typeof define.amd == 'object' &&
+ define.amd
+ ) {
+ define(function() {
+ return utf8;
+ });
+ } else if (freeExports && !freeExports.nodeType) {
+ if (freeModule) { // in Node.js or RingoJS v0.8.0+
+ freeModule.exports = utf8;
+ } else { // in Narwhal or RingoJS v0.7.0-
+ var object = {};
+ var hasOwnProperty = object.hasOwnProperty;
+ for (var key in utf8) {
+ hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
+ }
+ }
+ } else { // in Rhino or a web browser
+ root.utf8 = utf8;
+ }
+
+ }(this));
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],34:[function(_dereq_,module,exports){
+ (function (global){
+ /**
+ * JSON parse.
+ *
+ * @see Based on jQuery#parseJSON (MIT) and JSON2
+ * @api private
+ */
+
+ var rvalidchars = /^[\],:{}\s]*$/;
+ var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
+ var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
+ var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
+ var rtrimLeft = /^\s+/;
+ var rtrimRight = /\s+$/;
+
+ module.exports = function parsejson(data) {
+ if ('string' != typeof data || !data) {
+ return null;
+ }
+
+ data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
+
+ // Attempt to parse using the native JSON parser first
+ if (global.JSON && JSON.parse) {
+ return JSON.parse(data);
+ }
+
+ if (rvalidchars.test(data.replace(rvalidescape, '@')
+ .replace(rvalidtokens, ']')
+ .replace(rvalidbraces, ''))) {
+ return (new Function('return ' + data))();
+ }
+ };
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],35:[function(_dereq_,module,exports){
+ /**
+ * Compiles a querystring
+ * Returns string representation of the object
+ *
+ * @param {Object}
+ * @api private
+ */
+
+ exports.encode = function (obj) {
+ var str = '';
+
+ for (var i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ if (str.length) str += '&';
+ str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
+ }
+ }
+
+ return str;
+ };
+
+ /**
+ * Parses a simple querystring into an object
+ *
+ * @param {String} qs
+ * @api private
+ */
+
+ exports.decode = function(qs){
+ var qry = {};
+ var pairs = qs.split('&');
+ for (var i = 0, l = pairs.length; i < l; i++) {
+ var pair = pairs[i].split('=');
+ qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
+ }
+ return qry;
+ };
+
+},{}],36:[function(_dereq_,module,exports){
+ /**
+ * Parses an URI
+ *
+ * @author Steven Levithan (MIT license)
+ * @api private
+ */
+
+ var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
+
+ var parts = [
+ 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
+ ];
+
+ module.exports = function parseuri(str) {
+ var src = str,
+ b = str.indexOf('['),
+ e = str.indexOf(']');
+
+ if (b != -1 && e != -1) {
+ str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
+ }
+
+ var m = re.exec(str || ''),
+ uri = {},
+ i = 14;
+
+ while (i--) {
+ uri[parts[i]] = m[i] || '';
+ }
+
+ if (b != -1 && e != -1) {
+ uri.source = src;
+ uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
+ uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
+ uri.ipv6uri = true;
+ }
+
+ return uri;
+ };
+
+},{}],37:[function(_dereq_,module,exports){
+
+ /**
+ * Module dependencies.
+ */
+
+ var global = (function() { return this; })();
+
+ /**
+ * WebSocket constructor.
+ */
+
+ var WebSocket = global.WebSocket || global.MozWebSocket;
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = WebSocket ? ws : null;
+
+ /**
+ * WebSocket constructor.
+ *
+ * The third `opts` options object gets ignored in web browsers, since it's
+ * non-standard, and throws a TypeError if passed to the constructor.
+ * See: https://github.com/einaros/ws/issues/227
+ *
+ * @param {String} uri
+ * @param {Array} protocols (optional)
+ * @param {Object) opts (optional)
+ * @api public
+ */
+
+ function ws(uri, protocols, opts) {
+ var instance;
+ if (protocols) {
+ instance = new WebSocket(uri, protocols);
+ } else {
+ instance = new WebSocket(uri);
+ }
+ return instance;
+ }
+
+ if (WebSocket) ws.prototype = WebSocket.prototype;
+
+},{}],38:[function(_dereq_,module,exports){
+ (function (global){
+
+ /*
+ * Module requirements.
+ */
+
+ var isArray = _dereq_('isarray');
+
+ /**
+ * Module exports.
+ */
+
+ module.exports = hasBinary;
+
+ /**
+ * Checks for binary data.
+ *
+ * Right now only Buffer and ArrayBuffer are supported..
+ *
+ * @param {Object} anything
+ * @api public
+ */
+
+ function hasBinary(data) {
+
+ function _hasBinary(obj) {
+ if (!obj) return false;
+
+ if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
+ (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
+ (global.Blob && obj instanceof Blob) ||
+ (global.File && obj instanceof File)
+ ) {
+ return true;
+ }
+
+ if (isArray(obj)) {
+ for (var i = 0; i < obj.length; i++) {
+ if (_hasBinary(obj[i])) {
+ return true;
+ }
+ }
+ } else if (obj && 'object' == typeof obj) {
+ if (obj.toJSON) {
+ obj = obj.toJSON();
+ }
+
+ for (var key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ return _hasBinary(data);
+ }
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"isarray":39}],39:[function(_dereq_,module,exports){
+ module.exports=_dereq_(32)
+},{}],40:[function(_dereq_,module,exports){
+
+ /**
+ * Module dependencies.
+ */
+
+ var global = _dereq_('global');
+
+ /**
+ * Module exports.
+ *
+ * Logic borrowed from Modernizr:
+ *
+ * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
+ */
+
+ try {
+ module.exports = 'XMLHttpRequest' in global &&
+ 'withCredentials' in new global.XMLHttpRequest();
+ } catch (err) {
+ // if XMLHttp support is disabled in IE then it will throw
+ // when trying to create
+ module.exports = false;
+ }
+
+},{"global":41}],41:[function(_dereq_,module,exports){
+
+ /**
+ * Returns `this`. Execute this without a "context" (i.e. without it being
+ * attached to an object of the left-hand side), and `this` points to the
+ * "global" scope of the current JS execution.
+ */
+
+ module.exports = (function () { return this; })();
+
+},{}],42:[function(_dereq_,module,exports){
+
+ var indexOf = [].indexOf;
+
+ module.exports = function(arr, obj){
+ if (indexOf) return arr.indexOf(obj);
+ for (var i = 0; i < arr.length; ++i) {
+ if (arr[i] === obj) return i;
+ }
+ return -1;
+ };
+},{}],43:[function(_dereq_,module,exports){
+
+ /**
+ * HOP ref.
+ */
+
+ var has = Object.prototype.hasOwnProperty;
+
+ /**
+ * Return own keys in `obj`.
+ *
+ * @param {Object} obj
+ * @return {Array}
+ * @api public
+ */
+
+ exports.keys = Object.keys || function(obj){
+ var keys = [];
+ for (var key in obj) {
+ if (has.call(obj, key)) {
+ keys.push(key);
+ }
+ }
+ return keys;
+ };
+
+ /**
+ * Return own values in `obj`.
+ *
+ * @param {Object} obj
+ * @return {Array}
+ * @api public
+ */
+
+ exports.values = function(obj){
+ var vals = [];
+ for (var key in obj) {
+ if (has.call(obj, key)) {
+ vals.push(obj[key]);
+ }
+ }
+ return vals;
+ };
+
+ /**
+ * Merge `b` into `a`.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Object} a
+ * @api public
+ */
+
+ exports.merge = function(a, b){
+ for (var key in b) {
+ if (has.call(b, key)) {
+ a[key] = b[key];
+ }
+ }
+ return a;
+ };
+
+ /**
+ * Return length of `obj`.
+ *
+ * @param {Object} obj
+ * @return {Number}
+ * @api public
+ */
+
+ exports.length = function(obj){
+ return exports.keys(obj).length;
+ };
+
+ /**
+ * Check if `obj` is empty.
+ *
+ * @param {Object} obj
+ * @return {Boolean}
+ * @api public
+ */
+
+ exports.isEmpty = function(obj){
+ return 0 == exports.length(obj);
+ };
+},{}],44:[function(_dereq_,module,exports){
+ /**
+ * Parses an URI
+ *
+ * @author Steven Levithan (MIT license)
+ * @api private
+ */
+
+ var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
+
+ var parts = [
+ 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host'
+ , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
+ ];
+
+ module.exports = function parseuri(str) {
+ var m = re.exec(str || '')
+ , uri = {}
+ , i = 14;
+
+ while (i--) {
+ uri[parts[i]] = m[i] || '';
+ }
+
+ return uri;
+ };
+
+},{}],45:[function(_dereq_,module,exports){
+ (function (global){
+ /*global Blob,File*/
+
+ /**
+ * Module requirements
+ */
+
+ var isArray = _dereq_('isarray');
+ var isBuf = _dereq_('./is-buffer');
+
+ /**
+ * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
+ * Anything with blobs or files should be fed through removeBlobs before coming
+ * here.
+ *
+ * @param {Object} packet - socket.io event packet
+ * @return {Object} with deconstructed packet and list of buffers
+ * @api public
+ */
+
+ exports.deconstructPacket = function(packet){
+ var buffers = [];
+ var packetData = packet.data;
+
+ function _deconstructPacket(data) {
+ if (!data) return data;
+
+ if (isBuf(data)) {
+ var placeholder = { _placeholder: true, num: buffers.length };
+ buffers.push(data);
+ return placeholder;
+ } else if (isArray(data)) {
+ var newData = new Array(data.length);
+ for (var i = 0; i < data.length; i++) {
+ newData[i] = _deconstructPacket(data[i]);
+ }
+ return newData;
+ } else if ('object' == typeof data && !(data instanceof Date)) {
+ var newData = {};
+ for (var key in data) {
+ newData[key] = _deconstructPacket(data[key]);
+ }
+ return newData;
+ }
+ return data;
+ }
+
+ var pack = packet;
+ pack.data = _deconstructPacket(packetData);
+ pack.attachments = buffers.length; // number of binary 'attachments'
+ return {packet: pack, buffers: buffers};
+ };
+
+ /**
+ * Reconstructs a binary packet from its placeholder packet and buffers
+ *
+ * @param {Object} packet - event packet with placeholders
+ * @param {Array} buffers - binary buffers to put in placeholder positions
+ * @return {Object} reconstructed packet
+ * @api public
+ */
+
+ exports.reconstructPacket = function(packet, buffers) {
+ var curPlaceHolder = 0;
+
+ function _reconstructPacket(data) {
+ if (data && data._placeholder) {
+ var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway)
+ return buf;
+ } else if (isArray(data)) {
+ for (var i = 0; i < data.length; i++) {
+ data[i] = _reconstructPacket(data[i]);
+ }
+ return data;
+ } else if (data && 'object' == typeof data) {
+ for (var key in data) {
+ data[key] = _reconstructPacket(data[key]);
+ }
+ return data;
+ }
+ return data;
+ }
+
+ packet.data = _reconstructPacket(packet.data);
+ packet.attachments = undefined; // no longer useful
+ return packet;
+ };
+
+ /**
+ * Asynchronously removes Blobs or Files from data via
+ * FileReader's readAsArrayBuffer method. Used before encoding
+ * data as msgpack. Calls callback with the blobless data.
+ *
+ * @param {Object} data
+ * @param {Function} callback
+ * @api private
+ */
+
+ exports.removeBlobs = function(data, callback) {
+ function _removeBlobs(obj, curKey, containingObject) {
+ if (!obj) return obj;
+
+ // convert any blob
+ if ((global.Blob && obj instanceof Blob) ||
+ (global.File && obj instanceof File)) {
+ pendingBlobs++;
+
+ // async filereader
+ var fileReader = new FileReader();
+ fileReader.onload = function() { // this.result == arraybuffer
+ if (containingObject) {
+ containingObject[curKey] = this.result;
+ }
+ else {
+ bloblessData = this.result;
+ }
+
+ // if nothing pending its callback time
+ if(! --pendingBlobs) {
+ callback(bloblessData);
+ }
+ };
+
+ fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
+ } else if (isArray(obj)) { // handle array
+ for (var i = 0; i < obj.length; i++) {
+ _removeBlobs(obj[i], i, obj);
+ }
+ } else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object
+ for (var key in obj) {
+ _removeBlobs(obj[key], key, obj);
+ }
+ }
+ }
+
+ var pendingBlobs = 0;
+ var bloblessData = data;
+ _removeBlobs(bloblessData);
+ if (!pendingBlobs) {
+ callback(bloblessData);
+ }
+ };
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"./is-buffer":47,"isarray":48}],46:[function(_dereq_,module,exports){
+
+ /**
+ * Module dependencies.
+ */
+
+ var debug = _dereq_('debug')('socket.io-parser');
+ var json = _dereq_('json3');
+ var isArray = _dereq_('isarray');
+ var Emitter = _dereq_('component-emitter');
+ var binary = _dereq_('./binary');
+ var isBuf = _dereq_('./is-buffer');
+
+ /**
+ * Protocol version.
+ *
+ * @api public
+ */
+
+ exports.protocol = 4;
+
+ /**
+ * Packet types.
+ *
+ * @api public
+ */
+
+ exports.types = [
+ 'CONNECT',
+ 'DISCONNECT',
+ 'EVENT',
+ 'BINARY_EVENT',
+ 'ACK',
+ 'BINARY_ACK',
+ 'ERROR'
+ ];
+
+ /**
+ * Packet type `connect`.
+ *
+ * @api public
+ */
+
+ exports.CONNECT = 0;
+
+ /**
+ * Packet type `disconnect`.
+ *
+ * @api public
+ */
+
+ exports.DISCONNECT = 1;
+
+ /**
+ * Packet type `event`.
+ *
+ * @api public
+ */
+
+ exports.EVENT = 2;
+
+ /**
+ * Packet type `ack`.
+ *
+ * @api public
+ */
+
+ exports.ACK = 3;
+
+ /**
+ * Packet type `error`.
+ *
+ * @api public
+ */
+
+ exports.ERROR = 4;
+
+ /**
+ * Packet type 'binary event'
+ *
+ * @api public
+ */
+
+ exports.BINARY_EVENT = 5;
+
+ /**
+ * Packet type `binary ack`. For acks with binary arguments.
+ *
+ * @api public
+ */
+
+ exports.BINARY_ACK = 6;
+
+ /**
+ * Encoder constructor.
+ *
+ * @api public
+ */
+
+ exports.Encoder = Encoder;
+
+ /**
+ * Decoder constructor.
+ *
+ * @api public
+ */
+
+ exports.Decoder = Decoder;
+
+ /**
+ * A socket.io Encoder instance
+ *
+ * @api public
+ */
+
+ function Encoder() {}
+
+ /**
+ * Encode a packet as a single string if non-binary, or as a
+ * buffer sequence, depending on packet type.
+ *
+ * @param {Object} obj - packet object
+ * @param {Function} callback - function to handle encodings (likely engine.write)
+ * @return Calls callback with Array of encodings
+ * @api public
+ */
+
+ Encoder.prototype.encode = function(obj, callback){
+ debug('encoding packet %j', obj);
+
+ if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
+ encodeAsBinary(obj, callback);
+ }
+ else {
+ var encoding = encodeAsString(obj);
+ callback([encoding]);
+ }
+ };
+
+ /**
+ * Encode packet as string.
+ *
+ * @param {Object} packet
+ * @return {String} encoded
+ * @api private
+ */
+
+ function encodeAsString(obj) {
+ var str = '';
+ var nsp = false;
+
+ // first is type
+ str += obj.type;
+
+ // attachments if we have them
+ if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
+ str += obj.attachments;
+ str += '-';
+ }
+
+ // if we have a namespace other than `/`
+ // we append it followed by a comma `,`
+ if (obj.nsp && '/' != obj.nsp) {
+ nsp = true;
+ str += obj.nsp;
+ }
+
+ // immediately followed by the id
+ if (null != obj.id) {
+ if (nsp) {
+ str += ',';
+ nsp = false;
+ }
+ str += obj.id;
+ }
+
+ // json data
+ if (null != obj.data) {
+ if (nsp) str += ',';
+ str += json.stringify(obj.data);
+ }
+
+ debug('encoded %j as %s', obj, str);
+ return str;
+ }
+
+ /**
+ * Encode packet as 'buffer sequence' by removing blobs, and
+ * deconstructing packet into object with placeholders and
+ * a list of buffers.
+ *
+ * @param {Object} packet
+ * @return {Buffer} encoded
+ * @api private
+ */
+
+ function encodeAsBinary(obj, callback) {
+
+ function writeEncoding(bloblessData) {
+ var deconstruction = binary.deconstructPacket(bloblessData);
+ var pack = encodeAsString(deconstruction.packet);
+ var buffers = deconstruction.buffers;
+
+ buffers.unshift(pack); // add packet info to beginning of data list
+ callback(buffers); // write all the buffers
+ }
+
+ binary.removeBlobs(obj, writeEncoding);
+ }
+
+ /**
+ * A socket.io Decoder instance
+ *
+ * @return {Object} decoder
+ * @api public
+ */
+
+ function Decoder() {
+ this.reconstructor = null;
+ }
+
+ /**
+ * Mix in `Emitter` with Decoder.
+ */
+
+ Emitter(Decoder.prototype);
+
+ /**
+ * Decodes an ecoded packet string into packet JSON.
+ *
+ * @param {String} obj - encoded packet
+ * @return {Object} packet
+ * @api public
+ */
+
+ Decoder.prototype.add = function(obj) {
+ var packet;
+ if ('string' == typeof obj) {
+ packet = decodeString(obj);
+ if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json
+ this.reconstructor = new BinaryReconstructor(packet);
+
+ // no attachments, labeled binary but no binary data to follow
+ if (this.reconstructor.reconPack.attachments === 0) {
+ this.emit('decoded', packet);
+ }
+ } else { // non-binary full packet
+ this.emit('decoded', packet);
+ }
+ }
+ else if (isBuf(obj) || obj.base64) { // raw binary data
+ if (!this.reconstructor) {
+ throw new Error('got binary data when not reconstructing a packet');
+ } else {
+ packet = this.reconstructor.takeBinaryData(obj);
+ if (packet) { // received final buffer
+ this.reconstructor = null;
+ this.emit('decoded', packet);
+ }
+ }
+ }
+ else {
+ throw new Error('Unknown type: ' + obj);
+ }
+ };
+
+ /**
+ * Decode a packet String (JSON data)
+ *
+ * @param {String} str
+ * @return {Object} packet
+ * @api private
+ */
+
+ function decodeString(str) {
+ var p = {};
+ var i = 0;
+
+ // look up type
+ p.type = Number(str.charAt(0));
+ if (null == exports.types[p.type]) return error();
+
+ // look up attachments if type binary
+ if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) {
+ var buf = '';
+ while (str.charAt(++i) != '-') {
+ buf += str.charAt(i);
+ if (i == str.length) break;
+ }
+ if (buf != Number(buf) || str.charAt(i) != '-') {
+ throw new Error('Illegal attachments');
+ }
+ p.attachments = Number(buf);
+ }
+
+ // look up namespace (if any)
+ if ('/' == str.charAt(i + 1)) {
+ p.nsp = '';
+ while (++i) {
+ var c = str.charAt(i);
+ if (',' == c) break;
+ p.nsp += c;
+ if (i == str.length) break;
+ }
+ } else {
+ p.nsp = '/';
+ }
+
+ // look up id
+ var next = str.charAt(i + 1);
+ if ('' !== next && Number(next) == next) {
+ p.id = '';
+ while (++i) {
+ var c = str.charAt(i);
+ if (null == c || Number(c) != c) {
+ --i;
+ break;
+ }
+ p.id += str.charAt(i);
+ if (i == str.length) break;
+ }
+ p.id = Number(p.id);
+ }
+
+ // look up json data
+ if (str.charAt(++i)) {
+ try {
+ p.data = json.parse(str.substr(i));
+ } catch(e){
+ return error();
+ }
+ }
+
+ debug('decoded %s as %j', str, p);
+ return p;
+ }
+
+ /**
+ * Deallocates a parser's resources
+ *
+ * @api public
+ */
+
+ Decoder.prototype.destroy = function() {
+ if (this.reconstructor) {
+ this.reconstructor.finishedReconstruction();
+ }
+ };
+
+ /**
+ * A manager of a binary event's 'buffer sequence'. Should
+ * be constructed whenever a packet of type BINARY_EVENT is
+ * decoded.
+ *
+ * @param {Object} packet
+ * @return {BinaryReconstructor} initialized reconstructor
+ * @api private
+ */
+
+ function BinaryReconstructor(packet) {
+ this.reconPack = packet;
+ this.buffers = [];
+ }
+
+ /**
+ * Method to be called when binary data received from connection
+ * after a BINARY_EVENT packet.
+ *
+ * @param {Buffer | ArrayBuffer} binData - the raw binary data received
+ * @return {null | Object} returns null if more binary data is expected or
+ * a reconstructed packet object if all buffers have been received.
+ * @api private
+ */
+
+ BinaryReconstructor.prototype.takeBinaryData = function(binData) {
+ this.buffers.push(binData);
+ if (this.buffers.length == this.reconPack.attachments) { // done with buffer list
+ var packet = binary.reconstructPacket(this.reconPack, this.buffers);
+ this.finishedReconstruction();
+ return packet;
+ }
+ return null;
+ };
+
+ /**
+ * Cleans up binary packet reconstruction variables.
+ *
+ * @api private
+ */
+
+ BinaryReconstructor.prototype.finishedReconstruction = function() {
+ this.reconPack = null;
+ this.buffers = [];
+ };
+
+ function error(data){
+ return {
+ type: exports.ERROR,
+ data: 'parser error'
+ };
+ }
+
+},{"./binary":45,"./is-buffer":47,"component-emitter":9,"debug":10,"isarray":48,"json3":49}],47:[function(_dereq_,module,exports){
+ (function (global){
+
+ module.exports = isBuf;
+
+ /**
+ * Returns true if obj is a buffer or an arraybuffer.
+ *
+ * @api private
+ */
+
+ function isBuf(obj) {
+ return (global.Buffer && global.Buffer.isBuffer(obj)) ||
+ (global.ArrayBuffer && obj instanceof ArrayBuffer);
+ }
+
+ }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],48:[function(_dereq_,module,exports){
+ module.exports=_dereq_(32)
+},{}],49:[function(_dereq_,module,exports){
+ /*! JSON v3.2.6 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */
+ ;(function (window) {
+ // Convenience aliases.
+ var getClass = {}.toString, isProperty, forEach, undef;
+
+ // Detect the `define` function exposed by asynchronous module loaders. The
+ // strict `define` check is necessary for compatibility with `r.js`.
+ var isLoader = typeof define === "function" && define.amd;
+
+ // Detect native implementations.
+ var nativeJSON = typeof JSON == "object" && JSON;
+
+ // Set up the JSON 3 namespace, preferring the CommonJS `exports` object if
+ // available.
+ var JSON3 = typeof exports == "object" && exports && !exports.nodeType && exports;
+
+ if (JSON3 && nativeJSON) {
+ // Explicitly delegate to the native `stringify` and `parse`
+ // implementations in CommonJS environments.
+ JSON3.stringify = nativeJSON.stringify;
+ JSON3.parse = nativeJSON.parse;
+ } else {
+ // Export for web browsers, JavaScript engines, and asynchronous module
+ // loaders, using the global `JSON` object if available.
+ JSON3 = window.JSON = nativeJSON || {};
+ }
+
+ // Test the `Date#getUTC*` methods. Based on work by @Yaffle.
+ var isExtended = new Date(-3509827334573292);
+ try {
+ // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
+ // results for certain dates in Opera >= 10.53.
+ isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
+ // Safari < 2.0.2 stores the internal millisecond time value correctly,
+ // but clips the values returned by the date methods to the range of
+ // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
+ isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
+ } catch (exception) {}
+
+ // Internal: Determines whether the native `JSON.stringify` and `parse`
+ // implementations are spec-compliant. Based on work by Ken Snyder.
+ function has(name) {
+ if (has[name] !== undef) {
+ // Return cached feature test result.
+ return has[name];
+ }
+
+ var isSupported;
+ if (name == "bug-string-char-index") {
+ // IE <= 7 doesn't support accessing string characters using square
+ // bracket notation. IE 8 only supports this for primitives.
+ isSupported = "a"[0] != "a";
+ } else if (name == "json") {
+ // Indicates whether both `JSON.stringify` and `JSON.parse` are
+ // supported.
+ isSupported = has("json-stringify") && has("json-parse");
+ } else {
+ var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';
+ // Test `JSON.stringify`.
+ if (name == "json-stringify") {
+ var stringify = JSON3.stringify, stringifySupported = typeof stringify == "function" && isExtended;
+ if (stringifySupported) {
+ // A test function object with a custom `toJSON` method.
+ (value = function () {
+ return 1;
+ }).toJSON = value;
+ try {
+ stringifySupported =
+ // Firefox 3.1b1 and b2 serialize string, number, and boolean
+ // primitives as object literals.
+ stringify(0) === "0" &&
+ // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
+ // literals.
+ stringify(new Number()) === "0" &&
+ stringify(new String()) == '""' &&
+ // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
+ // does not define a canonical JSON representation (this applies to
+ // objects with `toJSON` properties as well, *unless* they are nested
+ // within an object or array).
+ stringify(getClass) === undef &&
+ // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
+ // FF 3.1b3 pass this test.
+ stringify(undef) === undef &&
+ // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
+ // respectively, if the value is omitted entirely.
+ stringify() === undef &&
+ // FF 3.1b1, 2 throw an error if the given value is not a number,
+ // string, array, object, Boolean, or `null` literal. This applies to
+ // objects with custom `toJSON` methods as well, unless they are nested
+ // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
+ // methods entirely.
+ stringify(value) === "1" &&
+ stringify([value]) == "[1]" &&
+ // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
+ // `"[null]"`.
+ stringify([undef]) == "[null]" &&
+ // YUI 3.0.0b1 fails to serialize `null` literals.
+ stringify(null) == "null" &&
+ // FF 3.1b1, 2 halts serialization if an array contains a function:
+ // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
+ // elides non-JSON values from objects and arrays, unless they
+ // define custom `toJSON` methods.
+ stringify([undef, getClass, null]) == "[null,null,null]" &&
+ // Simple serialization test. FF 3.1b1 uses Unicode escape sequences
+ // where character escape codes are expected (e.g., `\b` => `\u0008`).
+ stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
+ // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
+ stringify(null, value) === "1" &&
+ stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
+ // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
+ // serialize extended years.
+ stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
+ // The milliseconds are optional in ES 5, but required in 5.1.
+ stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
+ // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
+ // four-digit years instead of six-digit years. Credits: @Yaffle.
+ stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
+ // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
+ // values less than 1000. Credits: @Yaffle.
+ stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
+ } catch (exception) {
+ stringifySupported = false;
+ }
+ }
+ isSupported = stringifySupported;
+ }
+ // Test `JSON.parse`.
+ if (name == "json-parse") {
+ var parse = JSON3.parse;
+ if (typeof parse == "function") {
+ try {
+ // FF 3.1b1, b2 will throw an exception if a bare literal is provided.
+ // Conforming implementations should also coerce the initial argument to
+ // a string prior to parsing.
+ if (parse("0") === 0 && !parse(false)) {
+ // Simple parsing test.
+ value = parse(serialized);
+ var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
+ if (parseSupported) {
+ try {
+ // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
+ parseSupported = !parse('"\t"');
+ } catch (exception) {}
+ if (parseSupported) {
+ try {
+ // FF 4.0 and 4.0.1 allow leading `+` signs and leading
+ // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
+ // certain octal literals.
+ parseSupported = parse("01") !== 1;
+ } catch (exception) {}
+ }
+ if (parseSupported) {
+ try {
+ // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
+ // points. These environments, along with FF 3.1b1 and 2,
+ // also allow trailing commas in JSON objects and arrays.
+ parseSupported = parse("1.") !== 1;
+ } catch (exception) {}
+ }
+ }
+ }
+ } catch (exception) {
+ parseSupported = false;
+ }
+ }
+ isSupported = parseSupported;
+ }
+ }
+ return has[name] = !!isSupported;
+ }
+
+ if (!has("json")) {
+ // Common `[[Class]]` name aliases.
+ var functionClass = "[object Function]";
+ var dateClass = "[object Date]";
+ var numberClass = "[object Number]";
+ var stringClass = "[object String]";
+ var arrayClass = "[object Array]";
+ var booleanClass = "[object Boolean]";
+
+ // Detect incomplete support for accessing string characters by index.
+ var charIndexBuggy = has("bug-string-char-index");
+
+ // Define additional utility methods if the `Date` methods are buggy.
+ if (!isExtended) {
+ var floor = Math.floor;
+ // A mapping between the months of the year and the number of days between
+ // January 1st and the first of the respective month.
+ var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
+ // Internal: Calculates the number of days between the Unix epoch and the
+ // first day of the given month.
+ var getDay = function (year, month) {
+ return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
+ };
+ }
+
+ // Internal: Determines if a property is a direct property of the given
+ // object. Delegates to the native `Object#hasOwnProperty` method.
+ if (!(isProperty = {}.hasOwnProperty)) {
+ isProperty = function (property) {
+ var members = {}, constructor;
+ if ((members.__proto__ = null, members.__proto__ = {
+ // The *proto* property cannot be set multiple times in recent
+ // versions of Firefox and SeaMonkey.
+ "toString": 1
+ }, members).toString != getClass) {
+ // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
+ // supports the mutable *proto* property.
+ isProperty = function (property) {
+ // Capture and break the object's prototype chain (see section 8.6.2
+ // of the ES 5.1 spec). The parenthesized expression prevents an
+ // unsafe transformation by the Closure Compiler.
+ var original = this.__proto__, result = property in (this.__proto__ = null, this);
+ // Restore the original prototype chain.
+ this.__proto__ = original;
+ return result;
+ };
+ } else {
+ // Capture a reference to the top-level `Object` constructor.
+ constructor = members.constructor;
+ // Use the `constructor` property to simulate `Object#hasOwnProperty` in
+ // other environments.
+ isProperty = function (property) {
+ var parent = (this.constructor || constructor).prototype;
+ return property in this && !(property in parent && this[property] === parent[property]);
+ };
+ }
+ members = null;
+ return isProperty.call(this, property);
+ };
+ }
+
+ // Internal: A set of primitive types used by `isHostType`.
+ var PrimitiveTypes = {
+ 'boolean': 1,
+ 'number': 1,
+ 'string': 1,
+ 'undefined': 1
+ };
+
+ // Internal: Determines if the given object `property` value is a
+ // non-primitive.
+ var isHostType = function (object, property) {
+ var type = typeof object[property];
+ return type == 'object' ? !!object[property] : !PrimitiveTypes[type];
+ };
+
+ // Internal: Normalizes the `for...in` iteration algorithm across
+ // environments. Each enumerated key is yielded to a `callback` function.
+ forEach = function (object, callback) {
+ var size = 0, Properties, members, property;
+
+ // Tests for bugs in the current environment's `for...in` algorithm. The
+ // `valueOf` property inherits the non-enumerable flag from
+ // `Object.prototype` in older versions of IE, Netscape, and Mozilla.
+ (Properties = function () {
+ this.valueOf = 0;
+ }).prototype.valueOf = 0;
+
+ // Iterate over a new instance of the `Properties` class.
+ members = new Properties();
+ for (property in members) {
+ // Ignore all properties inherited from `Object.prototype`.
+ if (isProperty.call(members, property)) {
+ size++;
+ }
+ }
+ Properties = members = null;
+
+ // Normalize the iteration algorithm.
+ if (!size) {
+ // A list of non-enumerable properties inherited from `Object.prototype`.
+ members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
+ // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
+ // properties.
+ forEach = function (object, callback) {
+ var isFunction = getClass.call(object) == functionClass, property, length;
+ var hasProperty = !isFunction && typeof object.constructor != 'function' && isHostType(object, 'hasOwnProperty') ? object.hasOwnProperty : isProperty;
+ for (property in object) {
+ // Gecko <= 1.0 enumerates the `prototype` property of functions under
+ // certain conditions; IE does not.
+ if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
+ callback(property);
+ }
+ }
+ // Manually invoke the callback for each non-enumerable property.
+ for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
+ };
+ } else if (size == 2) {
+ // Safari <= 2.0.4 enumerates shadowed properties twice.
+ forEach = function (object, callback) {
+ // Create a set of iterated properties.
+ var members = {}, isFunction = getClass.call(object) == functionClass, property;
+ for (property in object) {
+ // Store each property name to prevent double enumeration. The
+ // `prototype` property of functions is not enumerated due to cross-
+ // environment inconsistencies.
+ if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
+ callback(property);
+ }
+ }
+ };
+ } else {
+ // No bugs detected; use the standard `for...in` algorithm.
+ forEach = function (object, callback) {
+ var isFunction = getClass.call(object) == functionClass, property, isConstructor;
+ for (property in object) {
+ if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
+ callback(property);
+ }
+ }
+ // Manually invoke the callback for the `constructor` property due to
+ // cross-environment inconsistencies.
+ if (isConstructor || isProperty.call(object, (property = "constructor"))) {
+ callback(property);
+ }
+ };
+ }
+ return forEach(object, callback);
+ };
+
+ // Public: Serializes a JavaScript `value` as a JSON string. The optional
+ // `filter` argument may specify either a function that alters how object and
+ // array members are serialized, or an array of strings and numbers that
+ // indicates which properties should be serialized. The optional `width`
+ // argument may be either a string or number that specifies the indentation
+ // level of the output.
+ if (!has("json-stringify")) {
+ // Internal: A map of control characters and their escaped equivalents.
+ var Escapes = {
+ 92: "\\\\",
+ 34: '\\"',
+ 8: "\\b",
+ 12: "\\f",
+ 10: "\\n",
+ 13: "\\r",
+ 9: "\\t"
+ };
+
+ // Internal: Converts `value` into a zero-padded string such that its
+ // length is at least equal to `width`. The `width` must be <= 6.
+ var leadingZeroes = "000000";
+ var toPaddedString = function (width, value) {
+ // The `|| 0` expression is necessary to work around a bug in
+ // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
+ return (leadingZeroes + (value || 0)).slice(-width);
+ };
+
+ // Internal: Double-quotes a string `value`, replacing all ASCII control
+ // characters (characters with code unit values between 0 and 31) with
+ // their escaped equivalents. This is an implementation of the
+ // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
+ var unicodePrefix = "\\u00";
+ var quote = function (value) {
+ var result = '"', index = 0, length = value.length, isLarge = length > 10 && charIndexBuggy, symbols;
+ if (isLarge) {
+ symbols = value.split("");
+ }
+ for (; index < length; index++) {
+ var charCode = value.charCodeAt(index);
+ // If the character is a control character, append its Unicode or
+ // shorthand escape sequence; otherwise, append the character as-is.
+ switch (charCode) {
+ case 8: case 9: case 10: case 12: case 13: case 34: case 92:
+ result += Escapes[charCode];
+ break;
+ default:
+ if (charCode < 32) {
+ result += unicodePrefix + toPaddedString(2, charCode.toString(16));
+ break;
+ }
+ result += isLarge ? symbols[index] : charIndexBuggy ? value.charAt(index) : value[index];
+ }
+ }
+ return result + '"';
+ };
+
+ // Internal: Recursively serializes an object. Implements the
+ // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
+ var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
+ var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
+ try {
+ // Necessary for host object support.
+ value = object[property];
+ } catch (exception) {}
+ if (typeof value == "object" && value) {
+ className = getClass.call(value);
+ if (className == dateClass && !isProperty.call(value, "toJSON")) {
+ if (value > -1 / 0 && value < 1 / 0) {
+ // Dates are serialized according to the `Date#toJSON` method
+ // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
+ // for the ISO 8601 date time string format.
+ if (getDay) {
+ // Manually compute the year, month, date, hours, minutes,
+ // seconds, and milliseconds if the `getUTC*` methods are
+ // buggy. Adapted from @Yaffle's `date-shim` project.
+ date = floor(value / 864e5);
+ for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
+ for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
+ date = 1 + date - getDay(year, month);
+ // The `time` value specifies the time within the day (see ES
+ // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
+ // to compute `A modulo B`, as the `%` operator does not
+ // correspond to the `modulo` operation for negative numbers.
+ time = (value % 864e5 + 864e5) % 864e5;
+ // The hours, minutes, seconds, and milliseconds are obtained by
+ // decomposing the time within the day. See section 15.9.1.10.
+ hours = floor(time / 36e5) % 24;
+ minutes = floor(time / 6e4) % 60;
+ seconds = floor(time / 1e3) % 60;
+ milliseconds = time % 1e3;
+ } else {
+ year = value.getUTCFullYear();
+ month = value.getUTCMonth();
+ date = value.getUTCDate();
+ hours = value.getUTCHours();
+ minutes = value.getUTCMinutes();
+ seconds = value.getUTCSeconds();
+ milliseconds = value.getUTCMilliseconds();
+ }
+ // Serialize extended years correctly.
+ value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
+ "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
+ // Months, dates, hours, minutes, and seconds should have two
+ // digits; milliseconds should have three.
+ "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
+ // Milliseconds are optional in ES 5.0, but required in 5.1.
+ "." + toPaddedString(3, milliseconds) + "Z";
+ } else {
+ value = null;
+ }
+ } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
+ // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
+ // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
+ // ignores all `toJSON` methods on these objects unless they are
+ // defined directly on an instance.
+ value = value.toJSON(property);
+ }
+ }
+ if (callback) {
+ // If a replacement function was provided, call it to obtain the value
+ // for serialization.
+ value = callback.call(object, property, value);
+ }
+ if (value === null) {
+ return "null";
+ }
+ className = getClass.call(value);
+ if (className == booleanClass) {
+ // Booleans are represented literally.
+ return "" + value;
+ } else if (className == numberClass) {
+ // JSON numbers must be finite. `Infinity` and `NaN` are serialized as
+ // `"null"`.
+ return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
+ } else if (className == stringClass) {
+ // Strings are double-quoted and escaped.
+ return quote("" + value);
+ }
+ // Recursively serialize objects and arrays.
+ if (typeof value == "object") {
+ // Check for cyclic structures. This is a linear search; performance
+ // is inversely proportional to the number of unique nested objects.
+ for (length = stack.length; length--;) {
+ if (stack[length] === value) {
+ // Cyclic structures cannot be serialized by `JSON.stringify`.
+ throw TypeError();
+ }
+ }
+ // Add the object to the stack of traversed objects.
+ stack.push(value);
+ results = [];
+ // Save the current indentation level and indent one additional level.
+ prefix = indentation;
+ indentation += whitespace;
+ if (className == arrayClass) {
+ // Recursively serialize array elements.
+ for (index = 0, length = value.length; index < length; index++) {
+ element = serialize(index, value, callback, properties, whitespace, indentation, stack);
+ results.push(element === undef ? "null" : element);
+ }
+ result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
+ } else {
+ // Recursively serialize object members. Members are selected from
+ // either a user-specified list of property names, or the object
+ // itself.
+ forEach(properties || value, function (property) {
+ var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
+ if (element !== undef) {
+ // According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
+ // is not the empty string, let `member` {quote(property) + ":"}
+ // be the concatenation of `member` and the `space` character."
+ // The "`space` character" refers to the literal space
+ // character, not the `space` {width} argument provided to
+ // `JSON.stringify`.
+ results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
+ }
+ });
+ result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
+ }
+ // Remove the object from the traversed object stack.
+ stack.pop();
+ return result;
+ }
+ };
+
+ // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
+ JSON3.stringify = function (source, filter, width) {
+ var whitespace, callback, properties, className;
+ if (typeof filter == "function" || typeof filter == "object" && filter) {
+ if ((className = getClass.call(filter)) == functionClass) {
+ callback = filter;
+ } else if (className == arrayClass) {
+ // Convert the property names array into a makeshift set.
+ properties = {};
+ for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
+ }
+ }
+ if (width) {
+ if ((className = getClass.call(width)) == numberClass) {
+ // Convert the `width` to an integer and create a string containing
+ // `width` number of space characters.
+ if ((width -= width % 1) > 0) {
+ for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
+ }
+ } else if (className == stringClass) {
+ whitespace = width.length <= 10 ? width : width.slice(0, 10);
+ }
+ }
+ // Opera <= 7.54u2 discards the values associated with empty string keys
+ // (`""`) only if they are used directly within an object member list
+ // (e.g., `!("" in { "": 1})`).
+ return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
+ };
+ }
+
+ // Public: Parses a JSON source string.
+ if (!has("json-parse")) {
+ var fromCharCode = String.fromCharCode;
+
+ // Internal: A map of escaped control characters and their unescaped
+ // equivalents.
+ var Unescapes = {
+ 92: "\\",
+ 34: '"',
+ 47: "/",
+ 98: "\b",
+ 116: "\t",
+ 110: "\n",
+ 102: "\f",
+ 114: "\r"
+ };
+
+ // Internal: Stores the parser state.
+ var Index, Source;
+
+ // Internal: Resets the parser state and throws a `SyntaxError`.
+ var abort = function() {
+ Index = Source = null;
+ throw SyntaxError();
+ };
+
+ // Internal: Returns the next token, or `"$"` if the parser has reached
+ // the end of the source string. A token may be a string, number, `null`
+ // literal, or Boolean literal.
+ var lex = function () {
+ var source = Source, length = source.length, value, begin, position, isSigned, charCode;
+ while (Index < length) {
+ charCode = source.charCodeAt(Index);
+ switch (charCode) {
+ case 9: case 10: case 13: case 32:
+ // Skip whitespace tokens, including tabs, carriage returns, line
+ // feeds, and space characters.
+ Index++;
+ break;
+ case 123: case 125: case 91: case 93: case 58: case 44:
+ // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
+ // the current position.
+ value = charIndexBuggy ? source.charAt(Index) : source[Index];
+ Index++;
+ return value;
+ case 34:
+ // `"` delimits a JSON string; advance to the next character and
+ // begin parsing the string. String tokens are prefixed with the
+ // sentinel `@` character to distinguish them from punctuators and
+ // end-of-string tokens.
+ for (value = "@", Index++; Index < length;) {
+ charCode = source.charCodeAt(Index);
+ if (charCode < 32) {
+ // Unescaped ASCII control characters (those with a code unit
+ // less than the space character) are not permitted.
+ abort();
+ } else if (charCode == 92) {
+ // A reverse solidus (`\`) marks the beginning of an escaped
+ // control character (including `"`, `\`, and `/`) or Unicode
+ // escape sequence.
+ charCode = source.charCodeAt(++Index);
+ switch (charCode) {
+ case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
+ // Revive escaped control characters.
+ value += Unescapes[charCode];
+ Index++;
+ break;
+ case 117:
+ // `\u` marks the beginning of a Unicode escape sequence.
+ // Advance to the first character and validate the
+ // four-digit code point.
+ begin = ++Index;
+ for (position = Index + 4; Index < position; Index++) {
+ charCode = source.charCodeAt(Index);
+ // A valid sequence comprises four hexdigits (case-
+ // insensitive) that form a single hexadecimal value.
+ if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
+ // Invalid Unicode escape sequence.
+ abort();
+ }
+ }
+ // Revive the escaped character.
+ value += fromCharCode("0x" + source.slice(begin, Index));
+ break;
+ default:
+ // Invalid escape sequence.
+ abort();
+ }
+ } else {
+ if (charCode == 34) {
+ // An unescaped double-quote character marks the end of the
+ // string.
+ break;
+ }
+ charCode = source.charCodeAt(Index);
+ begin = Index;
+ // Optimize for the common case where a string is valid.
+ while (charCode >= 32 && charCode != 92 && charCode != 34) {
+ charCode = source.charCodeAt(++Index);
+ }
+ // Append the string as-is.
+ value += source.slice(begin, Index);
+ }
+ }
+ if (source.charCodeAt(Index) == 34) {
+ // Advance to the next character and return the revived string.
+ Index++;
+ return value;
+ }
+ // Unterminated string.
+ abort();
+ default:
+ // Parse numbers and literals.
+ begin = Index;
+ // Advance past the negative sign, if one is specified.
+ if (charCode == 45) {
+ isSigned = true;
+ charCode = source.charCodeAt(++Index);
+ }
+ // Parse an integer or floating-point value.
+ if (charCode >= 48 && charCode <= 57) {
+ // Leading zeroes are interpreted as octal literals.
+ if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
+ // Illegal octal literal.
+ abort();
+ }
+ isSigned = false;
+ // Parse the integer component.
+ for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
+ // Floats cannot contain a leading decimal point; however, this
+ // case is already accounted for by the parser.
+ if (source.charCodeAt(Index) == 46) {
+ position = ++Index;
+ // Parse the decimal component.
+ for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
+ if (position == Index) {
+ // Illegal trailing decimal.
+ abort();
+ }
+ Index = position;
+ }
+ // Parse exponents. The `e` denoting the exponent is
+ // case-insensitive.
+ charCode = source.charCodeAt(Index);
+ if (charCode == 101 || charCode == 69) {
+ charCode = source.charCodeAt(++Index);
+ // Skip past the sign following the exponent, if one is
+ // specified.
+ if (charCode == 43 || charCode == 45) {
+ Index++;
+ }
+ // Parse the exponential component.
+ for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
+ if (position == Index) {
+ // Illegal empty exponent.
+ abort();
+ }
+ Index = position;
+ }
+ // Coerce the parsed value to a JavaScript number.
+ return +source.slice(begin, Index);
+ }
+ // A negative sign may only precede numbers.
+ if (isSigned) {
+ abort();
+ }
+ // `true`, `false`, and `null` literals.
+ if (source.slice(Index, Index + 4) == "true") {
+ Index += 4;
+ return true;
+ } else if (source.slice(Index, Index + 5) == "false") {
+ Index += 5;
+ return false;
+ } else if (source.slice(Index, Index + 4) == "null") {
+ Index += 4;
+ return null;
+ }
+ // Unrecognized token.
+ abort();
+ }
+ }
+ // Return the sentinel `$` character if the parser has reached the end
+ // of the source string.
+ return "$";
+ };
+
+ // Internal: Parses a JSON `value` token.
+ var get = function (value) {
+ var results, hasMembers;
+ if (value == "$") {
+ // Unexpected end of input.
+ abort();
+ }
+ if (typeof value == "string") {
+ if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
+ // Remove the sentinel `@` character.
+ return value.slice(1);
+ }
+ // Parse object and array literals.
+ if (value == "[") {
+ // Parses a JSON array, returning a new JavaScript array.
+ results = [];
+ for (;; hasMembers || (hasMembers = true)) {
+ value = lex();
+ // A closing square bracket marks the end of the array literal.
+ if (value == "]") {
+ break;
+ }
+ // If the array literal contains elements, the current token
+ // should be a comma separating the previous element from the
+ // next.
+ if (hasMembers) {
+ if (value == ",") {
+ value = lex();
+ if (value == "]") {
+ // Unexpected trailing `,` in array literal.
+ abort();
+ }
+ } else {
+ // A `,` must separate each array element.
+ abort();
+ }
+ }
+ // Elisions and leading commas are not permitted.
+ if (value == ",") {
+ abort();
+ }
+ results.push(get(value));
+ }
+ return results;
+ } else if (value == "{") {
+ // Parses a JSON object, returning a new JavaScript object.
+ results = {};
+ for (;; hasMembers || (hasMembers = true)) {
+ value = lex();
+ // A closing curly brace marks the end of the object literal.
+ if (value == "}") {
+ break;
+ }
+ // If the object literal contains members, the current token
+ // should be a comma separator.
+ if (hasMembers) {
+ if (value == ",") {
+ value = lex();
+ if (value == "}") {
+ // Unexpected trailing `,` in object literal.
+ abort();
+ }
+ } else {
+ // A `,` must separate each object member.
+ abort();
+ }
+ }
+ // Leading commas are not permitted, object property names must be
+ // double-quoted strings, and a `:` must separate each property
+ // name and value.
+ if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
+ abort();
+ }
+ results[value.slice(1)] = get(lex());
+ }
+ return results;
+ }
+ // Unexpected token encountered.
+ abort();
+ }
+ return value;
+ };
+
+ // Internal: Updates a traversed object member.
+ var update = function(source, property, callback) {
+ var element = walk(source, property, callback);
+ if (element === undef) {
+ delete source[property];
+ } else {
+ source[property] = element;
+ }
+ };
+
+ // Internal: Recursively traverses a parsed JSON object, invoking the
+ // `callback` function for each value. This is an implementation of the
+ // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
+ var walk = function (source, property, callback) {
+ var value = source[property], length;
+ if (typeof value == "object" && value) {
+ // `forEach` can't be used to traverse an array in Opera <= 8.54
+ // because its `Object#hasOwnProperty` implementation returns `false`
+ // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
+ if (getClass.call(value) == arrayClass) {
+ for (length = value.length; length--;) {
+ update(value, length, callback);
+ }
+ } else {
+ forEach(value, function (property) {
+ update(value, property, callback);
+ });
+ }
+ }
+ return callback.call(source, property, value);
+ };
+
+ // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
+ JSON3.parse = function (source, callback) {
+ var result, value;
+ Index = 0;
+ Source = "" + source;
+ result = get(lex());
+ // If a JSON string contains multiple tokens, it is invalid.
+ if (lex() != "$") {
+ abort();
+ }
+ // Reset the parser state.
+ Index = Source = null;
+ return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
+ };
+ }
+ }
+
+ // Export for asynchronous module loaders.
+ if (isLoader) {
+ define(function () {
+ return JSON3;
+ });
+ }
+ }(this));
+
+},{}],50:[function(_dereq_,module,exports){
+ module.exports = toArray
+
+ function toArray(list, index) {
+ var array = []
+
+ index = index || 0
+
+ for (var i = index || 0; i < list.length; i++) {
+ array[i - index] = list[i]
+ }
+
+ return array
+ }
+
+},{}]},{},[1])
+(1)
+});
diff --git a/external/socketio/socket.io.min.js b/external/socketio/socket.io.min.js
new file mode 100644
index 0000000000..28e8fee2bb
--- /dev/null
+++ b/external/socketio/socket.io.min.js
@@ -0,0 +1,3 @@
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0&&!this.encoding){var pack=this.packetBuffer.shift();this.packet(pack)}};Manager.prototype.cleanup=function(){var sub;while(sub=this.subs.shift())sub.destroy();this.packetBuffer=[];this.encoding=false;this.decoder.destroy()};Manager.prototype.close=Manager.prototype.disconnect=function(){this.skipReconnect=true;this.backoff.reset();this.readyState="closed";this.engine&&this.engine.close()};Manager.prototype.onclose=function(reason){debug("close");this.cleanup();this.backoff.reset();this.readyState="closed";this.emit("close",reason);if(this._reconnection&&!this.skipReconnect){this.reconnect()}};Manager.prototype.reconnect=function(){if(this.reconnecting||this.skipReconnect)return this;var self=this;if(this.backoff.attempts>=this._reconnectionAttempts){debug("reconnect failed");this.backoff.reset();this.emitAll("reconnect_failed");this.reconnecting=false}else{var delay=this.backoff.duration();debug("will wait %dms before reconnect attempt",delay);this.reconnecting=true;var timer=setTimeout(function(){if(self.skipReconnect)return;debug("attempting reconnect");self.emitAll("reconnect_attempt",self.backoff.attempts);self.emitAll("reconnecting",self.backoff.attempts);if(self.skipReconnect)return;self.open(function(err){if(err){debug("reconnect attempt error");self.reconnecting=false;self.reconnect();self.emitAll("reconnect_error",err.data)}else{debug("reconnect success");self.onreconnect()}})},delay);this.subs.push({destroy:function(){clearTimeout(timer)}})}};Manager.prototype.onreconnect=function(){var attempt=this.backoff.attempts;this.reconnecting=false;this.backoff.reset();this.updateSocketIds();this.emitAll("reconnect",attempt)}},{"./on":4,"./socket":5,"./url":6,backo2:7,"component-bind":8,"component-emitter":9,debug:10,"engine.io-client":11,indexof:42,"object-component":43,"socket.io-parser":46}],4:[function(_dereq_,module,exports){module.exports=on;function on(obj,ev,fn){obj.on(ev,fn);return{destroy:function(){obj.removeListener(ev,fn)}}}},{}],5:[function(_dereq_,module,exports){var parser=_dereq_("socket.io-parser");var Emitter=_dereq_("component-emitter");var toArray=_dereq_("to-array");var on=_dereq_("./on");var bind=_dereq_("component-bind");var debug=_dereq_("debug")("socket.io-client:socket");var hasBin=_dereq_("has-binary");module.exports=exports=Socket;var events={connect:1,connect_error:1,connect_timeout:1,disconnect:1,error:1,reconnect:1,reconnect_attempt:1,reconnect_failed:1,reconnect_error:1,reconnecting:1};var emit=Emitter.prototype.emit;function Socket(io,nsp){this.io=io;this.nsp=nsp;this.json=this;this.ids=0;this.acks={};if(this.io.autoConnect)this.open();this.receiveBuffer=[];this.sendBuffer=[];this.connected=false;this.disconnected=true}Emitter(Socket.prototype);Socket.prototype.subEvents=function(){if(this.subs)return;var io=this.io;this.subs=[on(io,"open",bind(this,"onopen")),on(io,"packet",bind(this,"onpacket")),on(io,"close",bind(this,"onclose"))]};Socket.prototype.open=Socket.prototype.connect=function(){if(this.connected)return this;this.subEvents();this.io.open();if("open"==this.io.readyState)this.onopen();return this};Socket.prototype.send=function(){var args=toArray(arguments);args.unshift("message");this.emit.apply(this,args);return this};Socket.prototype.emit=function(ev){if(events.hasOwnProperty(ev)){emit.apply(this,arguments);return this}var args=toArray(arguments);var parserType=parser.EVENT;if(hasBin(args)){parserType=parser.BINARY_EVENT}var packet={type:parserType,data:args};if("function"==typeof args[args.length-1]){debug("emitting packet with ack id %d",this.ids);this.acks[this.ids]=args.pop();packet.id=this.ids++}if(this.connected){this.packet(packet)}else{this.sendBuffer.push(packet)}return this};Socket.prototype.packet=function(packet){packet.nsp=this.nsp;this.io.packet(packet)};Socket.prototype.onopen=function(){debug("transport is open - connecting");if("/"!=this.nsp){this.packet({type:parser.CONNECT})}};Socket.prototype.onclose=function(reason){debug("close (%s)",reason);this.connected=false;this.disconnected=true;delete this.id;this.emit("disconnect",reason)};Socket.prototype.onpacket=function(packet){if(packet.nsp!=this.nsp)return;switch(packet.type){case parser.CONNECT:this.onconnect();break;case parser.EVENT:this.onevent(packet);break;case parser.BINARY_EVENT:this.onevent(packet);break;case parser.ACK:this.onack(packet);break;case parser.BINARY_ACK:this.onack(packet);break;case parser.DISCONNECT:this.ondisconnect();break;case parser.ERROR:this.emit("error",packet.data);break}};Socket.prototype.onevent=function(packet){var args=packet.data||[];debug("emitting event %j",args);if(null!=packet.id){debug("attaching ack callback to event");args.push(this.ack(packet.id))}if(this.connected){emit.apply(this,args)}else{this.receiveBuffer.push(args)}};Socket.prototype.ack=function(id){var self=this;var sent=false;return function(){if(sent)return;sent=true;var args=toArray(arguments);debug("sending ack %j",args);var type=hasBin(args)?parser.BINARY_ACK:parser.ACK;self.packet({type:type,id:id,data:args})}};Socket.prototype.onack=function(packet){debug("calling ack %s with %j",packet.id,packet.data);var fn=this.acks[packet.id];fn.apply(this,packet.data);delete this.acks[packet.id]};Socket.prototype.onconnect=function(){this.connected=true;this.disconnected=false;this.emit("connect");this.emitBuffered()};Socket.prototype.emitBuffered=function(){var i;for(i=0;i0&&opts.jitter<=1?opts.jitter:0;this.attempts=0}Backoff.prototype.duration=function(){var ms=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var rand=Math.random();var deviation=Math.floor(rand*this.jitter*ms);ms=(Math.floor(rand*10)&1)==0?ms-deviation:ms+deviation}return Math.min(ms,this.max)|0};Backoff.prototype.reset=function(){this.attempts=0};Backoff.prototype.setMin=function(min){this.ms=min};Backoff.prototype.setMax=function(max){this.max=max};Backoff.prototype.setJitter=function(jitter){this.jitter=jitter}},{}],8:[function(_dereq_,module,exports){var slice=[].slice;module.exports=function(obj,fn){if("string"==typeof fn)fn=obj[fn];if("function"!=typeof fn)throw new Error("bind() requires a function");var args=slice.call(arguments,2);return function(){return fn.apply(obj,args.concat(slice.call(arguments)))}}},{}],9:[function(_dereq_,module,exports){module.exports=Emitter;function Emitter(obj){if(obj)return mixin(obj)}function mixin(obj){for(var key in Emitter.prototype){obj[key]=Emitter.prototype[key]}return obj}Emitter.prototype.on=Emitter.prototype.addEventListener=function(event,fn){this._callbacks=this._callbacks||{};(this._callbacks[event]=this._callbacks[event]||[]).push(fn);return this};Emitter.prototype.once=function(event,fn){var self=this;this._callbacks=this._callbacks||{};function on(){self.off(event,on);fn.apply(this,arguments)}on.fn=fn;this.on(event,on);return this};Emitter.prototype.off=Emitter.prototype.removeListener=Emitter.prototype.removeAllListeners=Emitter.prototype.removeEventListener=function(event,fn){this._callbacks=this._callbacks||{};if(0==arguments.length){this._callbacks={};return this}var callbacks=this._callbacks[event];if(!callbacks)return this;if(1==arguments.length){delete this._callbacks[event];return this}var cb;for(var i=0;i=hour)return(ms/hour).toFixed(1)+"h";if(ms>=min)return(ms/min).toFixed(1)+"m";if(ms>=sec)return(ms/sec|0)+"s";return ms+"ms"};debug.enabled=function(name){for(var i=0,len=debug.skips.length;i';iframe=document.createElement(html)}catch(e){iframe=document.createElement("iframe");iframe.name=self.iframeId;iframe.src="javascript:0"}iframe.id=self.iframeId;self.form.appendChild(iframe);self.iframe=iframe}initIframe();data=data.replace(rEscapedNewline,"\\\n");this.area.value=data.replace(rNewline,"\\n");try{this.form.submit()}catch(e){}if(this.iframe.attachEvent){this.iframe.onreadystatechange=function(){if(self.iframe.readyState=="complete"){complete()}}}else{this.iframe.onload=complete}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_("xmlhttprequest");var Polling=_dereq_("./polling");var Emitter=_dereq_("component-emitter");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:polling-xhr");module.exports=XHR;module.exports.Request=Request;function empty(){}function XHR(opts){Polling.call(this,opts);if(global.location){var isSSL="https:"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}this.xd=opts.hostname!=global.location.hostname||port!=opts.port;this.xs=opts.secure!=isSSL}}inherit(XHR,Polling);XHR.prototype.supportsBinary=true;XHR.prototype.request=function(opts){opts=opts||{};opts.uri=this.uri();opts.xd=this.xd;opts.xs=this.xs;opts.agent=this.agent||false;opts.supportsBinary=this.supportsBinary;opts.enablesXDR=this.enablesXDR;opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;return new Request(opts)};XHR.prototype.doWrite=function(data,fn){var isBinary=typeof data!=="string"&&data!==undefined;var req=this.request({method:"POST",data:data,isBinary:isBinary});var self=this;req.on("success",fn);req.on("error",function(err){self.onError("xhr post error",err)});this.sendXhr=req};XHR.prototype.doPoll=function(){debug("xhr poll");var req=this.request();var self=this;req.on("data",function(data){self.onData(data)});req.on("error",function(err){self.onError("xhr poll error",err)});this.pollXhr=req};function Request(opts){this.method=opts.method||"GET";this.uri=opts.uri;this.xd=!!opts.xd;this.xs=!!opts.xs;this.async=false!==opts.async;this.data=undefined!=opts.data?opts.data:null;this.agent=opts.agent;this.isBinary=opts.isBinary;this.supportsBinary=opts.supportsBinary;this.enablesXDR=opts.enablesXDR;this.pfx=opts.pfx;this.key=opts.key;this.passphrase=opts.passphrase;this.cert=opts.cert;this.ca=opts.ca;this.ciphers=opts.ciphers;this.rejectUnauthorized=opts.rejectUnauthorized;this.create()}Emitter(Request.prototype);Request.prototype.create=function(){var opts={agent:this.agent,xdomain:this.xd,xscheme:this.xs,enablesXDR:this.enablesXDR};opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;var xhr=this.xhr=new XMLHttpRequest(opts);var self=this;try{debug("xhr open %s: %s",this.method,this.uri);xhr.open(this.method,this.uri,this.async);if(this.supportsBinary){xhr.responseType="arraybuffer"}if("POST"==this.method){try{if(this.isBinary){xhr.setRequestHeader("Content-type","application/octet-stream")}else{xhr.setRequestHeader("Content-type","text/plain;charset=UTF-8")}}catch(e){}}if("withCredentials"in xhr){xhr.withCredentials=true}if(this.hasXDR()){xhr.onload=function(){self.onLoad()};xhr.onerror=function(){self.onError(xhr.responseText)}}else{xhr.onreadystatechange=function(){if(4!=xhr.readyState)return;if(200==xhr.status||1223==xhr.status){self.onLoad()}else{setTimeout(function(){self.onError(xhr.status)},0)}}}debug("xhr data %s",this.data);xhr.send(this.data)}catch(e){setTimeout(function(){self.onError(e)},0);return}if(global.document){this.index=Request.requestsCount++;Request.requests[this.index]=this}};Request.prototype.onSuccess=function(){this.emit("success");this.cleanup()};Request.prototype.onData=function(data){this.emit("data",data);this.onSuccess()};Request.prototype.onError=function(err){this.emit("error",err);this.cleanup(true)};Request.prototype.cleanup=function(fromError){if("undefined"==typeof this.xhr||null===this.xhr){return}if(this.hasXDR()){this.xhr.onload=this.xhr.onerror=empty}else{this.xhr.onreadystatechange=empty}if(fromError){try{this.xhr.abort()}catch(e){}}if(global.document){delete Request.requests[this.index]}this.xhr=null};Request.prototype.onLoad=function(){var data;try{var contentType;try{contentType=this.xhr.getResponseHeader("Content-Type").split(";")[0]}catch(e){}if(contentType==="application/octet-stream"){data=this.xhr.response}else{if(!this.supportsBinary){data=this.xhr.responseText}else{data="ok"}}}catch(e){this.onError(e)}if(null!=data){this.onData(data)}};Request.prototype.hasXDR=function(){return"undefined"!==typeof global.XDomainRequest&&!this.xs&&this.enablesXDR};Request.prototype.abort=function(){this.cleanup()};if(global.document){Request.requestsCount=0;Request.requests={};if(global.attachEvent){global.attachEvent("onunload",unloadHandler)}else if(global.addEventListener){global.addEventListener("beforeunload",unloadHandler,false)}}function unloadHandler(){for(var i in Request.requests){if(Request.requests.hasOwnProperty(i)){Request.requests[i].abort()}}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling":18,"component-emitter":9,"component-inherit":21,debug:22,xmlhttprequest:20}],18:[function(_dereq_,module,exports){var Transport=_dereq_("../transport");var parseqs=_dereq_("parseqs");var parser=_dereq_("engine.io-parser");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:polling");module.exports=Polling;var hasXHR2=function(){var XMLHttpRequest=_dereq_("xmlhttprequest");var xhr=new XMLHttpRequest({xdomain:false});return null!=xhr.responseType}();function Polling(opts){var forceBase64=opts&&opts.forceBase64;if(!hasXHR2||forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(Polling,Transport);Polling.prototype.name="polling";Polling.prototype.doOpen=function(){this.poll()};Polling.prototype.pause=function(onPause){var pending=0;var self=this;this.readyState="pausing";function pause(){debug("paused");self.readyState="paused";onPause()}if(this.polling||!this.writable){var total=0;if(this.polling){debug("we are currently polling - waiting to pause");total++;this.once("pollComplete",function(){debug("pre-pause polling complete");--total||pause()})}if(!this.writable){debug("we are currently writing - waiting to pause");total++;this.once("drain",function(){debug("pre-pause writing complete");--total||pause()})}}else{pause()}};Polling.prototype.poll=function(){debug("polling");this.polling=true;this.doPoll();this.emit("poll")};Polling.prototype.onData=function(data){var self=this;debug("polling got data %s",data);var callback=function(packet,index,total){if("opening"==self.readyState){self.onOpen()}if("close"==packet.type){self.onClose();return false}self.onPacket(packet)};parser.decodePayload(data,this.socket.binaryType,callback);if("closed"!=this.readyState){this.polling=false;this.emit("pollComplete");if("open"==this.readyState){this.poll()}else{debug('ignoring poll - transport state "%s"',this.readyState)}}};Polling.prototype.doClose=function(){var self=this;function close(){debug("writing close packet");self.write([{type:"close"}])}if("open"==this.readyState){debug("transport open - closing");close()}else{debug("transport not open - deferring close");this.once("open",close)}};Polling.prototype.write=function(packets){var self=this;this.writable=false;var callbackfn=function(){self.writable=true;self.emit("drain")};var self=this;parser.encodePayload(packets,this.supportsBinary,function(data){self.doWrite(data,callbackfn)})};Polling.prototype.uri=function(){var query=this.query||{};var schema=this.secure?"https":"http";var port="";if(false!==this.timestampRequests){query[this.timestampParam]=+new Date+"-"+Transport.timestamps++}if(!this.supportsBinary&&!query.sid){query.b64=1}query=parseqs.encode(query);if(this.port&&("https"==schema&&this.port!=443||"http"==schema&&this.port!=80)){port=":"+this.port}if(query.length){query="?"+query}return schema+"://"+this.hostname+port+this.path+query}},{"../transport":14,"component-inherit":21,debug:22,"engine.io-parser":25,parseqs:35,xmlhttprequest:20}],19:[function(_dereq_,module,exports){var Transport=_dereq_("../transport");var parser=_dereq_("engine.io-parser");var parseqs=_dereq_("parseqs");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:websocket");var WebSocket=_dereq_("ws");module.exports=WS;function WS(opts){var forceBase64=opts&&opts.forceBase64;if(forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(WS,Transport);WS.prototype.name="websocket";WS.prototype.supportsBinary=true;WS.prototype.doOpen=function(){if(!this.check()){return}var self=this;var uri=this.uri();var protocols=void 0;var opts={agent:this.agent};opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;this.ws=new WebSocket(uri,protocols,opts);if(this.ws.binaryType===undefined){this.supportsBinary=false}this.ws.binaryType="arraybuffer";this.addEventListeners()};WS.prototype.addEventListeners=function(){var self=this;this.ws.onopen=function(){self.onOpen()};this.ws.onclose=function(){self.onClose()};this.ws.onmessage=function(ev){self.onData(ev.data)};this.ws.onerror=function(e){self.onError("websocket error",e)}};if("undefined"!=typeof navigator&&/iPad|iPhone|iPod/i.test(navigator.userAgent)){WS.prototype.onData=function(data){var self=this;setTimeout(function(){Transport.prototype.onData.call(self,data)},0)}}WS.prototype.write=function(packets){var self=this;this.writable=false;for(var i=0,l=packets.length;i=31}exports.formatters.j=function(v){return JSON.stringify(v)};function formatArgs(){var args=arguments;var useColors=this.useColors;args[0]=(useColors?"%c":"")+this.namespace+(useColors?" %c":" ")+args[0]+(useColors?"%c ":" ")+"+"+exports.humanize(this.diff);if(!useColors)return args;var c="color: "+this.color;args=[args[0],c,"color: inherit"].concat(Array.prototype.slice.call(args,1));var index=0;var lastC=0;args[0].replace(/%[a-z%]/g,function(match){if("%"===match)return;index++;if("%c"===match){lastC=index}});args.splice(lastC,0,c);return args}function log(){return"object"==typeof console&&"function"==typeof console.log&&Function.prototype.apply.call(console.log,console,arguments)}function save(namespaces){try{if(null==namespaces){localStorage.removeItem("debug")}else{localStorage.debug=namespaces}}catch(e){}}function load(){var r;try{r=localStorage.debug}catch(e){}return r}exports.enable(load())},{"./debug":23}],23:[function(_dereq_,module,exports){exports=module.exports=debug;exports.coerce=coerce;exports.disable=disable;exports.enable=enable;exports.enabled=enabled;exports.humanize=_dereq_("ms");exports.names=[];exports.skips=[];exports.formatters={};var prevColor=0;var prevTime;function selectColor(){return exports.colors[prevColor++%exports.colors.length]}function debug(namespace){function disabled(){}disabled.enabled=false;function enabled(){var self=enabled;var curr=+new Date;var ms=curr-(prevTime||curr);self.diff=ms;self.prev=prevTime;self.curr=curr;prevTime=curr;if(null==self.useColors)self.useColors=exports.useColors();if(null==self.color&&self.useColors)self.color=selectColor();var args=Array.prototype.slice.call(arguments);args[0]=exports.coerce(args[0]);if("string"!==typeof args[0]){args=["%o"].concat(args)}var index=0;args[0]=args[0].replace(/%([a-z%])/g,function(match,format){if(match==="%")return match;index++;var formatter=exports.formatters[format];if("function"===typeof formatter){var val=args[index];match=formatter.call(self,val);args.splice(index,1);index--}return match});if("function"===typeof exports.formatArgs){args=exports.formatArgs.apply(self,args)}var logFn=enabled.log||exports.log||console.log.bind(console);logFn.apply(self,args)}enabled.enabled=true;var fn=exports.enabled(namespace)?enabled:disabled;fn.namespace=namespace;return fn}function enable(namespaces){exports.save(namespaces);var split=(namespaces||"").split(/[\s,]+/);var len=split.length;for(var i=0;i=d)return Math.round(ms/d)+"d";if(ms>=h)return Math.round(ms/h)+"h";if(ms>=m)return Math.round(ms/m)+"m";if(ms>=s)return Math.round(ms/s)+"s";return ms+"ms"}function long(ms){return plural(ms,d,"day")||plural(ms,h,"hour")||plural(ms,m,"minute")||plural(ms,s,"second")||ms+" ms"}function plural(ms,n,name){if(ms1){return{type:packetslist[type],data:data.substring(1)}}else{return{type:packetslist[type]}}}var asArray=new Uint8Array(data);var type=asArray[0];var rest=sliceBuffer(data,1);if(Blob&&binaryType==="blob"){rest=new Blob([rest])}return{type:packetslist[type],data:rest}};exports.decodeBase64Packet=function(msg,binaryType){var type=packetslist[msg.charAt(0)];if(!global.ArrayBuffer){return{type:type,data:{base64:true,data:msg.substr(1)}}}var data=base64encoder.decode(msg.substr(1));if(binaryType==="blob"&&Blob){data=new Blob([data])}return{type:type,data:data}};exports.encodePayload=function(packets,supportsBinary,callback){if(typeof supportsBinary=="function"){callback=supportsBinary;supportsBinary=null}var isBinary=hasBinary(packets);if(supportsBinary&&isBinary){if(Blob&&!dontSendBlobs){return exports.encodePayloadAsBlob(packets,callback)}return exports.encodePayloadAsArrayBuffer(packets,callback)}if(!packets.length){return callback("0:")}function setLengthHeader(message){return message.length+":"+message}function encodeOne(packet,doneCallback){exports.encodePacket(packet,!isBinary?false:supportsBinary,true,function(message){doneCallback(null,setLengthHeader(message))})}map(packets,encodeOne,function(err,results){return callback(results.join(""))})};function map(ary,each,done){var result=new Array(ary.length);var next=after(ary.length,done);var eachWithIndex=function(i,el,cb){each(el,function(error,msg){result[i]=msg;cb(error,result)})};for(var i=0;i0){var tailArray=new Uint8Array(bufferTail);var isString=tailArray[0]===0;var msgLength="";for(var i=1;;i++){if(tailArray[i]==255)break;if(msgLength.length>310){numberTooLong=true;break}msgLength+=tailArray[i]}if(numberTooLong)return callback(err,0,1);bufferTail=sliceBuffer(bufferTail,2+msgLength.length);msgLength=parseInt(msgLength);var msg=sliceBuffer(bufferTail,0,msgLength);if(isString){try{msg=String.fromCharCode.apply(null,new Uint8Array(msg))}catch(e){var typed=new Uint8Array(msg);msg="";for(var i=0;ibytes){end=bytes}if(start>=bytes||start>=end||bytes===0){return new ArrayBuffer(0)}var abv=new Uint8Array(arraybuffer);var result=new Uint8Array(end-start);for(var i=start,ii=0;i>2];base64+=chars[(bytes[i]&3)<<4|bytes[i+1]>>4];base64+=chars[(bytes[i+1]&15)<<2|bytes[i+2]>>6];base64+=chars[bytes[i+2]&63]}if(len%3===2){base64=base64.substring(0,base64.length-1)+"="}else if(len%3===1){base64=base64.substring(0,base64.length-2)+"=="}return base64};exports.decode=function(base64){var bufferLength=base64.length*.75,len=base64.length,i,p=0,encoded1,encoded2,encoded3,encoded4;if(base64[base64.length-1]==="="){bufferLength--;if(base64[base64.length-2]==="="){bufferLength--}}var arraybuffer=new ArrayBuffer(bufferLength),bytes=new Uint8Array(arraybuffer);for(i=0;i>4;bytes[p++]=(encoded2&15)<<4|encoded3>>2;bytes[p++]=(encoded3&3)<<6|encoded4&63}return arraybuffer}})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")},{}],30:[function(_dereq_,module,exports){(function(global){var BlobBuilder=global.BlobBuilder||global.WebKitBlobBuilder||global.MSBlobBuilder||global.MozBlobBuilder;var blobSupported=function(){try{var b=new Blob(["hi"]);return b.size==2}catch(e){return false}}();var blobBuilderSupported=BlobBuilder&&BlobBuilder.prototype.append&&BlobBuilder.prototype.getBlob;function BlobBuilderConstructor(ary,options){options=options||{};var bb=new BlobBuilder;for(var i=0;i=55296&&value<=56319&&counter65535){value-=65536;
+ output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value)}return output}function createByte(codePoint,shift){return stringFromCharCode(codePoint>>shift&63|128)}function encodeCodePoint(codePoint){if((codePoint&4294967168)==0){return stringFromCharCode(codePoint)}var symbol="";if((codePoint&4294965248)==0){symbol=stringFromCharCode(codePoint>>6&31|192)}else if((codePoint&4294901760)==0){symbol=stringFromCharCode(codePoint>>12&15|224);symbol+=createByte(codePoint,6)}else if((codePoint&4292870144)==0){symbol=stringFromCharCode(codePoint>>18&7|240);symbol+=createByte(codePoint,12);symbol+=createByte(codePoint,6)}symbol+=stringFromCharCode(codePoint&63|128);return symbol}function utf8encode(string){var codePoints=ucs2decode(string);var length=codePoints.length;var index=-1;var codePoint;var byteString="";while(++index=byteCount){throw Error("Invalid byte index")}var continuationByte=byteArray[byteIndex]&255;byteIndex++;if((continuationByte&192)==128){return continuationByte&63}throw Error("Invalid continuation byte")}function decodeSymbol(){var byte1;var byte2;var byte3;var byte4;var codePoint;if(byteIndex>byteCount){throw Error("Invalid byte index")}if(byteIndex==byteCount){return false}byte1=byteArray[byteIndex]&255;byteIndex++;if((byte1&128)==0){return byte1}if((byte1&224)==192){var byte2=readContinuationByte();codePoint=(byte1&31)<<6|byte2;if(codePoint>=128){return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&240)==224){byte2=readContinuationByte();byte3=readContinuationByte();codePoint=(byte1&15)<<12|byte2<<6|byte3;if(codePoint>=2048){return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&248)==240){byte2=readContinuationByte();byte3=readContinuationByte();byte4=readContinuationByte();codePoint=(byte1&15)<<18|byte2<<12|byte3<<6|byte4;if(codePoint>=65536&&codePoint<=1114111){return codePoint}}throw Error("Invalid UTF-8 detected")}var byteArray;var byteCount;var byteIndex;function utf8decode(byteString){byteArray=ucs2decode(byteString);byteCount=byteArray.length;byteIndex=0;var codePoints=[];var tmp;while((tmp=decodeSymbol())!==false){codePoints.push(tmp)}return ucs2encode(codePoints)}var utf8={version:"2.0.0",encode:utf8encode,decode:utf8decode};if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){define(function(){return utf8})}else if(freeExports&&!freeExports.nodeType){if(freeModule){freeModule.exports=utf8}else{var object={};var hasOwnProperty=object.hasOwnProperty;for(var key in utf8){hasOwnProperty.call(utf8,key)&&(freeExports[key]=utf8[key])}}}else{root.utf8=utf8}})(this)}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],34:[function(_dereq_,module,exports){(function(global){var rvalidchars=/^[\],:{}\s]*$/;var rvalidescape=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;var rvalidtokens=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;var rvalidbraces=/(?:^|:|,)(?:\s*\[)+/g;var rtrimLeft=/^\s+/;var rtrimRight=/\s+$/;module.exports=function parsejson(data){if("string"!=typeof data||!data){return null}data=data.replace(rtrimLeft,"").replace(rtrimRight,"");if(global.JSON&&JSON.parse){return JSON.parse(data)}if(rvalidchars.test(data.replace(rvalidescape,"@").replace(rvalidtokens,"]").replace(rvalidbraces,""))){return new Function("return "+data)()}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],35:[function(_dereq_,module,exports){exports.encode=function(obj){var str="";for(var i in obj){if(obj.hasOwnProperty(i)){if(str.length)str+="&";str+=encodeURIComponent(i)+"="+encodeURIComponent(obj[i])}}return str};exports.decode=function(qs){var qry={};var pairs=qs.split("&");for(var i=0,l=pairs.length;i1)))/4)-floor((year-1901+month)/100)+floor((year-1601+month)/400)}}if(!(isProperty={}.hasOwnProperty)){isProperty=function(property){var members={},constructor;if((members.__proto__=null,members.__proto__={toString:1},members).toString!=getClass){isProperty=function(property){var original=this.__proto__,result=property in(this.__proto__=null,this);this.__proto__=original;return result}}else{constructor=members.constructor;isProperty=function(property){var parent=(this.constructor||constructor).prototype;return property in this&&!(property in parent&&this[property]===parent[property])}}members=null;return isProperty.call(this,property)}}var PrimitiveTypes={"boolean":1,number:1,string:1,undefined:1};var isHostType=function(object,property){var type=typeof object[property];return type=="object"?!!object[property]:!PrimitiveTypes[type]};forEach=function(object,callback){var size=0,Properties,members,property;(Properties=function(){this.valueOf=0}).prototype.valueOf=0;members=new Properties;for(property in members){if(isProperty.call(members,property)){size++}}Properties=members=null;if(!size){members=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"];forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,length;var hasProperty=!isFunction&&typeof object.constructor!="function"&&isHostType(object,"hasOwnProperty")?object.hasOwnProperty:isProperty;for(property in object){if(!(isFunction&&property=="prototype")&&hasProperty.call(object,property)){callback(property)}}for(length=members.length;property=members[--length];hasProperty.call(object,property)&&callback(property));}}else if(size==2){forEach=function(object,callback){var members={},isFunction=getClass.call(object)==functionClass,property;for(property in object){if(!(isFunction&&property=="prototype")&&!isProperty.call(members,property)&&(members[property]=1)&&isProperty.call(object,property)){callback(property)}}}}else{forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,isConstructor;for(property in object){if(!(isFunction&&property=="prototype")&&isProperty.call(object,property)&&!(isConstructor=property==="constructor")){callback(property)}}if(isConstructor||isProperty.call(object,property="constructor")){callback(property)}}}return forEach(object,callback)};if(!has("json-stringify")){var Escapes={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"};var leadingZeroes="000000";var toPaddedString=function(width,value){return(leadingZeroes+(value||0)).slice(-width)};var unicodePrefix="\\u00";var quote=function(value){var result='"',index=0,length=value.length,isLarge=length>10&&charIndexBuggy,symbols;if(isLarge){symbols=value.split("")}for(;index-1/0&&value<1/0){if(getDay){date=floor(value/864e5);for(year=floor(date/365.2425)+1970-1;getDay(year+1,0)<=date;year++);for(month=floor((date-getDay(year,0))/30.42);getDay(year,month+1)<=date;month++);date=1+date-getDay(year,month);time=(value%864e5+864e5)%864e5;hours=floor(time/36e5)%24;minutes=floor(time/6e4)%60;seconds=floor(time/1e3)%60;milliseconds=time%1e3}else{year=value.getUTCFullYear();month=value.getUTCMonth();date=value.getUTCDate();hours=value.getUTCHours();minutes=value.getUTCMinutes();seconds=value.getUTCSeconds();milliseconds=value.getUTCMilliseconds()}value=(year<=0||year>=1e4?(year<0?"-":"+")+toPaddedString(6,year<0?-year:year):toPaddedString(4,year))+"-"+toPaddedString(2,month+1)+"-"+toPaddedString(2,date)+"T"+toPaddedString(2,hours)+":"+toPaddedString(2,minutes)+":"+toPaddedString(2,seconds)+"."+toPaddedString(3,milliseconds)+"Z"}else{value=null}}else if(typeof value.toJSON=="function"&&(className!=numberClass&&className!=stringClass&&className!=arrayClass||isProperty.call(value,"toJSON"))){value=value.toJSON(property)}}if(callback){value=callback.call(object,property,value)}if(value===null){return"null"}className=getClass.call(value);if(className==booleanClass){return""+value}else if(className==numberClass){return value>-1/0&&value<1/0?""+value:"null"}else if(className==stringClass){return quote(""+value)}if(typeof value=="object"){for(length=stack.length;length--;){if(stack[length]===value){throw TypeError()}}stack.push(value);results=[];prefix=indentation;indentation+=whitespace;if(className==arrayClass){for(index=0,length=value.length;index0){for(whitespace="",width>10&&(width=10);whitespace.length=48&&charCode<=57||charCode>=97&&charCode<=102||charCode>=65&&charCode<=70)){abort()}}value+=fromCharCode("0x"+source.slice(begin,Index));break;default:abort()}}else{if(charCode==34){break}charCode=source.charCodeAt(Index);begin=Index;while(charCode>=32&&charCode!=92&&charCode!=34){charCode=source.charCodeAt(++Index)}value+=source.slice(begin,Index)}}if(source.charCodeAt(Index)==34){Index++;return value}abort();default:begin=Index;if(charCode==45){isSigned=true;charCode=source.charCodeAt(++Index)}if(charCode>=48&&charCode<=57){if(charCode==48&&(charCode=source.charCodeAt(Index+1),charCode>=48&&charCode<=57)){abort()}isSigned=false;for(;Index=48&&charCode<=57);Index++);if(source.charCodeAt(Index)==46){position=++Index;for(;position=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}charCode=source.charCodeAt(Index);if(charCode==101||charCode==69){charCode=source.charCodeAt(++Index);if(charCode==43||charCode==45){Index++}for(position=Index;position=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}return+source.slice(begin,Index)}if(isSigned){abort()}if(source.slice(Index,Index+4)=="true"){Index+=4;return true}else if(source.slice(Index,Index+5)=="false"){Index+=5;return false}else if(source.slice(Index,Index+4)=="null"){Index+=4;return null}abort()}}return"$"};var get=function(value){var results,hasMembers;if(value=="$"){abort()}if(typeof value=="string"){if((charIndexBuggy?value.charAt(0):value[0])=="@"){return value.slice(1)}if(value=="["){results=[];for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="]"){break}if(hasMembers){if(value==","){value=lex();if(value=="]"){abort()}}else{abort()}}if(value==","){abort()}results.push(get(value))}return results}else if(value=="{"){results={};for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="}"){break}if(hasMembers){if(value==","){value=lex();if(value=="}"){abort()}}else{abort()}}if(value==","||typeof value!="string"||(charIndexBuggy?value.charAt(0):value[0])!="@"||lex()!=":"){abort()}results[value.slice(1)]=get(lex())}return results}abort()}return value};var update=function(source,property,callback){var element=walk(source,property,callback);if(element===undef){delete source[property]}else{source[property]=element}};var walk=function(source,property,callback){var value=source[property],length;if(typeof value=="object"&&value){if(getClass.call(value)==arrayClass){for(length=value.length;length--;){update(value,length,callback)}}else{forEach(value,function(property){update(value,property,callback)})}}return callback.call(source,property,value)};JSON3.parse=function(source,callback){var result,value;Index=0;Source=""+source;result=get(lex());if(lex()!="$"){abort()}Index=Source=null;return callback&&getClass.call(callback)==functionClass?walk((value={},value[""]=result,value),"",callback):result}}}if(isLoader){define(function(){return JSON3})}})(this)},{}],50:[function(_dereq_,module,exports){module.exports=toArray;function toArray(list,index){var array=[];index=index||0;for(var i=index||0;i
-
-
- Cocos2d-HTML5
-
-
-
-
-
-
-
-
-
-
- Hello World
- Test cases
- Template
- MoonWarriors
- Fruit Attack
- Watermelon with Me
- CocosDragon
- Crystal Craze
-
-
-Note
-
-
-
While games written with Cocos2d-html5 should work offline, but some browsers won't allow this to happen.
- Browsers that deny access to certain functions such as XMLHttpRequest that fails for "file:// " protocol, but
- Cocos2d-html5 engine depend on this to read many files such as a .plist file.
-
-
Some versions of Firefox, Safari and Opera are notable exceptions.
-
-
If you wish to use other browsers, you need a webserver. It doesn't mean a seperate computer, you can download a
- free webserver program to your computer. Here is some popular webserver program:
-
- XAMPP : for windows, Mac, Linux
- WAMP : for windows
- MAMP : for Mac
-
- Once you install a webserver, go to your installation directory, there should be a directory called "htdocs" or
- "www", place Cocos2d-html5 files in there. Then point your browser to http://localhost/.
-
-
Cocos2d-html5 should now work without any errors
-
-
-
diff --git a/jsb_apis.js b/jsb_apis.js
new file mode 100644
index 0000000000..19680d178f
--- /dev/null
+++ b/jsb_apis.js
@@ -0,0 +1,618 @@
+/****************************************************************************
+ Copyright (c) 2014 Chukong Technologies Inc.
+
+ http://www.cocos2d-x.org
+
+ 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.
+ ****************************************************************************/
+
+/**
+ * The namespace for jsb exclusive APIs, all APIs in this namespace should never be used in Web engine.
+ * So please check whether the running environment is native or not before any usage.
+ * @namespace
+ * @name jsb
+ * @example
+ *
+ * if(cc.sys.isNative) {
+ * cc.log(cc.fileUtils.fullPathForFilename("test.js"));
+ * }
+ */
+var jsb = jsb || {};
+
+/**
+ * ATTENTION: USE jsb.fileUtils INSTEAD OF jsb.FileUtils.
+ * jsb.fileUtils is the native file utils' singleton object,
+ * please refer to Cocos2d-x's API to know how to use it.
+ * Only available in JSB
+ * @class
+ * @name jsb.fileUtils
+ * @extend cc.Class
+ */
+jsb.fileUtils = /** @lends jsb.fileUtils# */{
+
+ /**
+ * @function fullPathForFilename
+ * @param {String} arg0
+ * @return {String}
+ */
+ fullPathForFilename : function (str)
+ {
+ return ;
+ },
+
+ /**
+ * @function getStringFromFile
+ * @param {String} arg0
+ * @return {String}
+ */
+ getStringFromFile : function (str)
+ {
+ return ;
+ },
+
+ /**
+ * @function removeFile
+ * @param {String} arg0
+ * @return {bool}
+ */
+ removeFile : function (str)
+ {
+ return false;
+ },
+
+ /**
+ * @function isAbsolutePath
+ * @param {String} arg0
+ * @return {bool}
+ */
+ isAbsolutePath : function (str)
+ {
+ return false;
+ },
+
+ /**
+ * @function renameFile
+ * @param {String} arg0
+ * @param {String} arg1
+ * @param {String} arg2
+ * @return {bool}
+ */
+ renameFile : function (arg0,arg1,arg2)
+ {
+ return false;
+ },
+
+ /**
+ * @function loadFilenameLookupDictionaryFromFile
+ * @param {String} arg0
+ */
+ loadFilenameLookupDictionaryFromFile : function (str)
+ {
+ },
+
+ /**
+ * @function isPopupNotify
+ * @return {bool}
+ */
+ isPopupNotify : function ()
+ {
+ return false;
+ },
+
+ /**
+ * @function getValueVectorFromFile
+ * @param {String} arg0
+ * @return {Array}
+ */
+ getValueVectorFromFile : function (str)
+ {
+ return new Array();
+ },
+
+ /**
+ * @function getSearchPaths
+ * @return {Array}
+ */
+ getSearchPaths : function ()
+ {
+ return new Array();
+ },
+
+ /**
+ * @function writeToFile
+ * @param {map_object} arg0
+ * @param {String} arg1
+ * @return {bool}
+ */
+ writeToFile : function (map, str)
+ {
+ return false;
+ },
+
+ /**
+ * @function getValueMapFromFile
+ * @param {String} arg0
+ * @return {map_object}
+ */
+ getValueMapFromFile : function (str)
+ {
+ return map_object;
+ },
+
+ /**
+ * @function getFileSize
+ * @param {String} arg0
+ * @return {long}
+ */
+ getFileSize : function (str)
+ {
+ return 0;
+ },
+
+ /**
+ * @function removeDirectory
+ * @param {String} arg0
+ * @return {bool}
+ */
+ removeDirectory : function (str)
+ {
+ return false;
+ },
+
+ /**
+ * @function setSearchPaths
+ * @param {Array} arg0
+ */
+ setSearchPaths : function (array)
+ {
+ },
+
+ /**
+ * @function writeStringToFile
+ * @param {String} arg0
+ * @param {String} arg1
+ * @return {bool}
+ */
+ writeStringToFile : function (arg0,arg1)
+ {
+ return false;
+ },
+
+ /**
+ * @function setSearchResolutionsOrder
+ * @param {Array} arg0
+ */
+ setSearchResolutionsOrder : function (array)
+ {
+ },
+
+ /**
+ * @function addSearchResolutionsOrder
+ * @param {String} arg0
+ */
+ addSearchResolutionsOrder : function (str)
+ {
+ },
+
+ /**
+ * @function addSearchPath
+ * @param {String} arg0
+ */
+ addSearchPath : function (str)
+ {
+ },
+
+ /**
+ * @function isFileExist
+ * @param {String} arg0
+ * @return {bool}
+ */
+ isFileExist : function (str)
+ {
+ return false;
+ },
+
+ /**
+ * @function purgeCachedEntries
+ */
+ purgeCachedEntries : function ()
+ {
+ },
+
+ /**
+ * @function fullPathFromRelativeFile
+ * @param {String} arg0
+ * @param {String} arg1
+ * @return {String}
+ */
+ fullPathFromRelativeFile : function (arg0,arg1)
+ {
+ return ;
+ },
+
+ /**
+ * @function isDirectoryExist
+ * @param {String} arg0
+ * @return {bool}
+ */
+ isDirectoryExist : function (str)
+ {
+ return false;
+ },
+
+ /**
+ * @function getSearchResolutionsOrder
+ * @return {Array}
+ */
+ getSearchResolutionsOrder : function ()
+ {
+ return new Array();
+ },
+
+ /**
+ * @function createDirectory
+ * @param {String} arg0
+ * @return {bool}
+ */
+ createDirectory : function (str)
+ {
+ return false;
+ },
+
+ /**
+ * @function createDirectories
+ * @param {String} arg0
+ * @return {bool}
+ */
+ createDirectories : function (str)
+ {
+ return false;
+ },
+
+ /**
+ * @function getWritablePath
+ * @return {String}
+ */
+ getWritablePath : function ()
+ {
+ return ;
+ }
+
+};
+
+/**
+ * @class
+ */
+jsb.EventAssetsManager = cc.Class.extend(/** @lends jsb.EventAssetsManager# */{
+
+ /**
+ * @function getAssetsManager
+ * @return {cc.AssetsManager}
+ */
+ getAssetsManager : function (
+ )
+ {
+ return cc.AssetsManager;
+ },
+
+ /**
+ * @function getAssetId
+ * @return {String}
+ */
+ getAssetId : function (
+ )
+ {
+ return ;
+ },
+
+ /**
+ * @function getCURLECode
+ * @return {int}
+ */
+ getCURLECode : function (
+ )
+ {
+ return 0;
+ },
+
+ /**
+ * @function getMessage
+ * @return {String}
+ */
+ getMessage : function (
+ )
+ {
+ return ;
+ },
+
+ /**
+ * @function getCURLMCode
+ * @return {int}
+ */
+ getCURLMCode : function (
+ )
+ {
+ return 0;
+ },
+
+ /**
+ * @function getPercentByFile
+ * @return {float}
+ */
+ getPercentByFile : function (
+ )
+ {
+ return 0;
+ },
+
+ /**
+ * @function getEventCode
+ * @return {number} cc.EventAssetsManager.EventCode
+ */
+ getEventCode : function (
+ )
+ {
+ return 0;
+ },
+
+ /**
+ * @function getPercent
+ * @return {float}
+ */
+ getPercent : function (
+ )
+ {
+ return 0;
+ },
+
+ /**
+ * @function EventAssetsManager
+ * @constructor
+ * @param {String} arg0
+ * @param {cc.AssetsManager} arg1
+ * @param {number} arg2 cc.EventAssetsManager::EventCode
+ * @param {float} arg3
+ * @param {float} arg4
+ * @param {String} arg5
+ * @param {String} arg6
+ * @param {int} arg7
+ * @param {int} arg8
+ */
+ EventAssetsManager : function (
+ arg0,
+ assetsmanager,
+ eventcode,
+ arg3,
+ arg4,
+ arg5,
+ arg6,
+ arg7,
+ arg8
+ )
+ {
+ }
+});
+
+
+/**
+ * @class
+ */
+jsb.EventListenerAssetsManager = cc.Class.extend(/** @lends jsb.EventListenerAssetsManager# */{
+
+ /**
+ * @function init
+ * @param {cc.AssetsManager} arg0
+ * @param {function} arg1
+ * @return {bool}
+ */
+ init : function (
+ assetsmanager,
+ func
+ )
+ {
+ return false;
+ },
+
+ /**
+ * @function create
+ * @param {cc.AssetsManager} arg0
+ * @param {function} arg1
+ * @return {cc.EventListenerAssetsManager}
+ */
+ create : function (
+ assetsmanager,
+ func
+ )
+ {
+ return cc.EventListenerAssetsManager;
+ },
+
+ /**
+ * @function EventListenerAssetsManager
+ * @constructor
+ */
+ EventListenerAssetsManager : function (
+ )
+ {
+ }
+
+});
+
+/**
+ * @class
+ * jsb.AssetsManager is the native AssetsManager for your game resources or scripts.
+ * please refer to this document to know how to use it: http://www.cocos2d-x.org/docs/manual/framework/html5/v3/assets-manager/en
+ * Only available in JSB
+ */
+jsb.AssetsManager = cc.Class.extend(/** @lends jsb.AssetsManager# */{
+
+ /**
+ * @function getState
+ * @return {number} jsb.AssetsManager::State
+ */
+ getState : function ()
+ {
+ return 0;
+ },
+
+ /**
+ * @function checkUpdate
+ */
+ checkUpdate : function ()
+ {
+ },
+
+ /**
+ * @function getStoragePath
+ * @return {String}
+ */
+ getStoragePath : function ()
+ {
+ return ;
+ },
+
+ /**
+ * @function update
+ */
+ update : function ()
+ {
+ },
+
+ /**
+ * @function getLocalManifest
+ * @return {object} jsb.Manifest
+ */
+ getLocalManifest : function ()
+ {
+ return cc.Manifest;
+ },
+
+ /**
+ * @function getRemoteManifest
+ * @return {jsb.Manifest}
+ */
+ getRemoteManifest : function ()
+ {
+ return cc.Manifest;
+ },
+
+ /**
+ * @function downloadFailedAssets
+ */
+ downloadFailedAssets : function ()
+ {
+ },
+
+ /**
+ * @function create
+ * @param {String} arg0
+ * @param {String} arg1
+ * @return {jsb.AssetsManager}
+ */
+ create : function (arg0,arg1)
+ {
+ return cc.AssetsManager;
+ },
+
+ /**
+ * @function AssetsManager
+ * @constructor
+ * @param {String} arg0
+ * @param {String} arg1
+ */
+ ctor : function (arg0,arg1)
+ {
+ }
+
+});
+
+/**
+ * @class
+ */
+jsb.Manifest = cc.Class.extend(/** @lends jsb.Manifest# */{
+
+ /**
+ * @function getManifestFileUrl
+ * @return {String}
+ */
+ getManifestFileUrl : function ()
+ {
+ return ;
+ },
+
+ /**
+ * @function isVersionLoaded
+ * @return {bool}
+ */
+ isVersionLoaded : function ()
+ {
+ return false;
+ },
+
+ /**
+ * @function isLoaded
+ * @return {bool}
+ */
+ isLoaded : function ()
+ {
+ return false;
+ },
+
+ /**
+ * @function getPackageUrl
+ * @return {String}
+ */
+ getPackageUrl : function ()
+ {
+ return ;
+ },
+
+ /**
+ * @function getVersion
+ * @return {String}
+ */
+ getVersion : function ()
+ {
+ return ;
+ },
+
+ /**
+ * @function getVersionFileUrl
+ * @return {String}
+ */
+ getVersionFileUrl : function ()
+ {
+ return ;
+ }
+});
+
+/**
+ * jsb.reflection is a bridge to let you invoke Java static functions.
+ * please refer to this document to know how to use it: http://www.cocos2d-x.org/docs/manual/framework/html5/v3/reflection/en
+ * Only available on iOS/Mac/Android platform
+ * @class
+ * @name jsb.reflection
+ */
+jsb.reflection = /** @lends jsb.reflection# */{
+ /**
+ * @function
+ */
+ callStaticMethod : function(){
+ }
+};
diff --git a/moduleConfig.json b/moduleConfig.json
new file mode 100644
index 0000000000..55a9e81c60
--- /dev/null
+++ b/moduleConfig.json
@@ -0,0 +1,494 @@
+{
+ "module" : {
+ "actions" : [
+ "core",
+
+ "cocos2d/actions/CCAction.js",
+ "cocos2d/actions/CCActionInterval.js",
+ "cocos2d/actions/CCActionInstant.js",
+ "cocos2d/actions/CCActionEase.js",
+ "cocos2d/actions/CCActionCatmullRom.js",
+ "cocos2d/actions/CCActionTween.js"
+ ],
+ "actions3d" : [
+ "core", "kazmath", "shaders", "actions", "effects", "render-texture",
+
+ "cocos2d/actions3d/CCActionGrid.js",
+ "cocos2d/actions3d/CCActionGrid3D.js",
+ "cocos2d/actions3d/CCActionTiledGrid.js",
+ "cocos2d/actions3d/CCActionPageTurn3D.js"
+ ],
+ "audio" : [
+ "core",
+
+ "cocos2d/audio/CCAudio.js"
+ ],
+ "clipping-nodes" : [
+ "core", "shape-nodes",
+
+ "cocos2d/clipping-nodes/CCClippingNode.js",
+ "cocos2d/clipping-nodes/CCClippingNodeCanvasRenderCmd.js",
+ "cocos2d/clipping-nodes/CCClippingNodeWebGLRenderCmd.js"
+ ],
+ "compression" : [
+ "core",
+
+ "cocos2d/compression/ZipUtils.js",
+ "cocos2d/compression/base64.js"
+ ],
+ "core" : [
+ "cocos2d/core/event-manager/CCEventHelper.js",
+ "CCDebugger.js",
+ "cocos2d/core/utils/BinaryLoader.js",
+ "Base64Images.js",
+ "cocos2d/core/platform/CCClass.js",
+ "cocos2d/core/platform/CCCommon.js",
+ "cocos2d/core/cocoa/CCGeometry.js",
+ "cocos2d/core/platform/CCSAXParser.js",
+ "cocos2d/core/platform/CCLoaders.js",
+ "cocos2d/core/platform/CCConfig.js",
+ "cocos2d/core/platform/miniFramework.js",
+ "cocos2d/core/platform/CCMacro.js",
+ "cocos2d/core/platform/CCTypes.js",
+ "cocos2d/core/platform/CCEGLView.js",
+ "cocos2d/core/platform/CCScreen.js",
+ "cocos2d/core/platform/CCVisibleRect.js",
+
+ "cocos2d/core/platform/CCInputManager.js",
+ "cocos2d/core/platform/CCInputExtension.js",
+
+ "cocos2d/core/cocoa/CCAffineTransform.js",
+ "cocos2d/core/support/CCPointExtension.js",
+ "cocos2d/core/support/CCVertex.js",
+ "cocos2d/core/support/TransformUtils.js",
+ "cocos2d/core/event-manager/CCTouch.js",
+
+ "cocos2d/core/event-manager/CCEvent.js",
+ "cocos2d/core/event-manager/CCEventListener.js",
+ "cocos2d/core/event-manager/CCEventManager.js",
+ "cocos2d/core/event-manager/CCEventExtension.js",
+
+ "cocos2d/core/renderer/GlobalVertexBuffer.js",
+ "cocos2d/core/renderer/RendererCanvas.js",
+ "cocos2d/core/renderer/RendererWebGL.js",
+ "cocos2d/core/renderer/DirtyRegion.js",
+ "cocos2d/core/base-nodes/BaseNodesPropertyDefine.js",
+ "cocos2d/core/base-nodes/CCNode.js",
+ "cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js",
+ "cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js",
+ "cocos2d/core/base-nodes/CCAtlasNode.js",
+ "cocos2d/core/base-nodes/CCAtlasNodeCanvasRenderCmd.js",
+ "cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js",
+
+ "cocos2d/core/textures/TexturesWebGL.js",
+ "cocos2d/core/textures/TexturesPropertyDefine.js",
+ "cocos2d/core/textures/CCTexture2D.js",
+ "cocos2d/core/textures/CCTextureCache.js",
+ "cocos2d/core/textures/CCTextureAtlas.js",
+
+ "cocos2d/core/scenes/CCScene.js",
+ "cocos2d/core/scenes/CCLoaderScene.js",
+
+ "cocos2d/core/layers/CCLayer.js",
+ "cocos2d/core/layers/CCLayerCanvasRenderCmd.js",
+ "cocos2d/core/layers/CCLayerWebGLRenderCmd.js",
+
+ "cocos2d/core/sprites/SpritesPropertyDefine.js",
+ "cocos2d/core/sprites/CCSprite.js",
+ "cocos2d/core/sprites/CCSpriteCanvasRenderCmd.js",
+ "cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js",
+ "cocos2d/core/sprites/CCSpriteBatchNode.js",
+ "cocos2d/core/sprites/CCBakeSprite.js",
+ "cocos2d/core/sprites/CCAnimation.js",
+ "cocos2d/core/sprites/CCAnimationCache.js",
+ "cocos2d/core/sprites/CCSpriteFrame.js",
+ "cocos2d/core/sprites/CCSpriteFrameCache.js",
+ "cocos2d/core/CCConfiguration.js",
+
+ "cocos2d/core/CCDirector.js",
+ "cocos2d/core/CCDirectorCanvas.js",
+ "cocos2d/core/CCDirectorWebGL.js",
+
+ "cocos2d/core/CCScheduler.js",
+ "cocos2d/core/CCDrawingPrimitivesCanvas.js",
+ "cocos2d/core/CCDrawingPrimitivesWebGL.js",
+
+ "cocos2d/core/labelttf/LabelTTFPropertyDefine.js",
+ "cocos2d/core/labelttf/CCLabelTTF.js",
+ "cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js",
+ "cocos2d/core/labelttf/CCLabelTTFWebGLRenderCmd.js",
+
+ "cocos2d/core/CCActionManager.js",
+
+ "cocos2d/core/utils/CCProfiler.js"
+ ],
+ "effects" : [
+ "core",
+
+ "cocos2d/effects/CCGrid.js",
+ "cocos2d/effects/CCGrabber.js"
+ ],
+ "kazmath" : [
+ "core",
+
+ "cocos2d/kazmath/utility.js",
+ "cocos2d/kazmath/vec2.js",
+ "cocos2d/kazmath/vec3.js",
+ "cocos2d/kazmath/vec4.js",
+ "cocos2d/kazmath/ray2.js",
+ "cocos2d/kazmath/mat3.js",
+ "cocos2d/kazmath/mat4.js",
+ "cocos2d/kazmath/plane.js",
+ "cocos2d/kazmath/quaternion.js",
+ "cocos2d/kazmath/aabb.js",
+ "cocos2d/kazmath/gl/mat4stack.js",
+ "cocos2d/kazmath/gl/matrix.js"
+ ],
+ "kazmathSIMD" : [
+ "kazmath",
+
+ "cocos2d/kazmath/vec3SIMD.js",
+ "cocos2d/kazmath/mat4SIMD.js",
+ "cocos2d/kazmath/SIMDPolyfill.js"
+ ],
+ "labels" : [
+ "core",
+ "cocos2d/labels/CCLabelBMFont.js",
+ "cocos2d/labels/CCLabelBMFontCanvasRenderCmd.js",
+ "cocos2d/labels/CCLabelBMFontWebGLRenderCmd.js",
+ "cocos2d/labels/CCLabelAtlas.js",
+ "cocos2d/labels/CCLabelAtlasCanvasRenderCmd.js",
+ "cocos2d/labels/CCLabelAtlasWebGLRenderCmd.js"
+ ],
+ "menus" : [
+ "core", "actions",
+
+ "cocos2d/menus/CCMenuItem.js",
+ "cocos2d/menus/CCMenu.js"
+ ],
+ "motion-streak" : [
+ "core", "shaders", "kazmath", "labels",
+
+ "cocos2d/motion-streak/CCMotionStreak.js",
+ "cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js"
+ ],
+ "node-grid" : [
+ "core",
+
+ "cocos2d/node-grid/CCNodeGrid.js",
+ "cocos2d/node-grid/CCNodeGridWebGLRenderCmd.js"
+ ],
+ "parallax" : [
+ "core",
+
+ "cocos2d/parallax/CCParallaxNode.js",
+ "cocos2d/parallax/CCParallaxNodeRenderCmd.js"
+ ],
+ "particle" : [
+ "core", "compression",
+
+ "cocos2d/particle/CCPNGReader.js",
+ "cocos2d/particle/CCTIFFReader.js",
+ "cocos2d/particle/CCParticleSystem.js",
+ "cocos2d/particle/CCParticleSystemCanvasRenderCmd.js",
+ "cocos2d/particle/CCParticleSystemWebGLRenderCmd.js",
+ "cocos2d/particle/CCParticleExamples.js",
+ "cocos2d/particle/CCParticleBatchNode.js",
+ "cocos2d/particle/CCParticleBatchNodeCanvasRenderCmd.js",
+ "cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js"
+ ],
+ "physics" : [
+ "core", "shape-nodes",
+
+ "cocos2d/physics/CCPhysicsSprite.js",
+ "cocos2d/physics/CCPhysicsDebugNode.js",
+ "cocos2d/physics/CCPhysicsDebugNodeCanvasRenderCmd.js",
+ "cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js",
+ "cocos2d/physics/CCPhysicsSpriteCanvasRenderCmd.js",
+ "cocos2d/physics/CCPhysicsSpriteWebGLRenderCmd.js"
+ ],
+ "progress-timer" : [
+ "core", "actions",
+
+ "cocos2d/progress-timer/CCProgressTimer.js",
+ "cocos2d/progress-timer/CCActionProgressTimer.js",
+ "cocos2d/progress-timer/CCProgressTimerCanvasRenderCmd.js",
+ "cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js"
+ ],
+ "render-texture" : [
+ "core",
+
+ "cocos2d/render-texture/CCRenderTexture.js",
+ "cocos2d/render-texture/CCRenderTextureCanvasRenderCmd.js",
+ "cocos2d/render-texture/CCRenderTextureWebGLRenderCmd.js"
+ ],
+ "shaders" : [
+ "core", "kazmath",
+
+ "cocos2d/shaders/CCShaders.js",
+ "cocos2d/shaders/CCShaderCache.js",
+ "cocos2d/shaders/CCGLProgram.js",
+ "cocos2d/shaders/CCGLProgramState.js",
+ "cocos2d/shaders/CCGLStateCache.js"
+ ],
+ "shape-nodes" : [
+ "core",
+
+ "cocos2d/shape-nodes/CCDrawNode.js",
+ "cocos2d/shape-nodes/CCDrawNodeCanvasRenderCmd.js",
+ "cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js"
+ ],
+ "text-input" : [
+ "core",
+
+ "cocos2d/text-input/CCIMEDispatcher.js",
+ "cocos2d/text-input/CCTextFieldTTF.js"
+ ],
+ "tilemap" : [
+ "core", "compression",
+
+ "cocos2d/compression/gzip.js",
+ "cocos2d/compression/zlib.min.js",
+
+ "cocos2d/tilemap/CCTGAlib.js",
+ "cocos2d/tilemap/CCTMXTiledMap.js",
+ "cocos2d/tilemap/CCTMXXMLParser.js",
+ "cocos2d/tilemap/CCTMXObjectGroup.js",
+ "cocos2d/tilemap/CCTMXLayer.js",
+ "cocos2d/tilemap/CCTMXLayerCanvasRenderCmd.js",
+ "cocos2d/tilemap/CCTMXLayerWebGLRenderCmd.js"
+ ],
+ "transitions" : [
+ "core", "actions", "render-texture", "progress-timer",
+
+ "cocos2d/transitions/CCTransition.js",
+ "cocos2d/transitions/CCTransitionProgress.js",
+ "cocos2d/transitions/CCTransitionPageTurn.js"
+ ],
+
+ "base4webgl" : ["core", "kazmath", "shaders"],
+ "cocos2d" : [
+ "core", "kazmath", "shaders", "render-texture", "motion-streak", "node-grid",
+ "clipping-nodes", "effects", "shape-nodes", "actions", "actions3d",
+ "progress-timer", "transitions", "labels", "compression", "particle",
+ "text-input", "menus", "tilemap", "parallax", "audio"
+ ],
+
+ "ccbreader" : [
+ "core", "audio", "gui", "menus", "particle", "actions", "labels",
+
+ "extensions/ccb-reader/CCNodeLoader.js",
+ "extensions/ccb-reader/CCBReaderUtil.js",
+ "extensions/ccb-reader/CCControlLoader.js",
+ "extensions/ccb-reader/CCSpriteLoader.js",
+ "extensions/ccb-reader/CCNodeLoaderLibrary.js",
+ "extensions/ccb-reader/CCBReader.js",
+ "extensions/ccb-reader/CCBValue.js",
+ "extensions/ccb-reader/CCBKeyframe.js",
+ "extensions/ccb-reader/CCBSequence.js",
+ "extensions/ccb-reader/CCBRelativePositioning.js",
+ "extensions/ccb-reader/CCBAnimationManager.js"
+ ],
+ "editbox" : [
+ "core", "gui",
+
+ "extensions/editbox/CCEditBox.js"
+ ],
+ "ccpool" : [
+ "core",
+
+ "extensions/ccpool/CCPool.js"
+ ],
+ "ccui" : [
+ "core", "actions", "labels", "text-input","clipping-nodes",
+ "extensions/ccui/base-classes/CCProtectedNode.js",
+ "extensions/ccui/base-classes/CCProtectedNodeCanvasRenderCmd.js",
+ "extensions/ccui/base-classes/CCProtectedNodeWebGLRenderCmd.js",
+ "extensions/ccui/system/CocosGUI.js",
+ "extensions/ccui/base-classes/UIWidget.js",
+ "extensions/ccui/base-classes/UIWidgetRenderCmd.js",
+ "extensions/ccui/base-classes/UIScale9Sprite.js",
+ "extensions/ccui/base-classes/UIScale9SpriteCanvasRenderCmd.js",
+ "extensions/ccui/base-classes/UIScale9SpriteWebGLRenderCmd.js",
+ "extensions/ccui/layouts/UILayout.js",
+ "extensions/ccui/layouts/UILayoutCanvasRenderCmd.js",
+ "extensions/ccui/layouts/UILayoutWebGLRenderCmd.js",
+ "extensions/ccui/layouts/UILayoutParameter.js",
+ "extensions/ccui/layouts/UILayoutManager.js",
+ "extensions/ccui/layouts/UIHBox.js",
+ "extensions/ccui/layouts/UIRelativeBox.js",
+ "extensions/ccui/layouts/UIVBox.js",
+ "extensions/ccui/system/UIHelper.js",
+ "extensions/ccui/uiwidgets/UIButton.js",
+ "extensions/ccui/uiwidgets/UICheckBox.js",
+ "extensions/ccui/uiwidgets/UIImageView.js",
+ "extensions/ccui/uiwidgets/UILoadingBar.js",
+ "extensions/ccui/uiwidgets/UISlider.js",
+ "extensions/ccui/uiwidgets/UIText.js",
+ "extensions/ccui/uiwidgets/UITextAtlas.js",
+ "extensions/ccui/uiwidgets/UITextBMFont.js",
+ "extensions/ccui/uiwidgets/UITextField.js",
+ "extensions/ccui/uiwidgets/UIVideoPlayer.js",
+ "extensions/ccui/uiwidgets/UIRichText.js",
+ "extensions/ccui/uiwidgets/UIWebView.js",
+ "extensions/ccui/uiwidgets/scroll-widget/UIScrollViewBar.js",
+ "extensions/ccui/uiwidgets/scroll-widget/UIScrollView.js",
+ "extensions/ccui/uiwidgets/scroll-widget/UIListView.js",
+ "extensions/ccui/uiwidgets/scroll-widget/UIPageView.js",
+ "extensions/ccui/uiwidgets/scroll-widget/UIPageViewIndicator.js",
+ "extensions/ccui/uiwidgets/scroll-widget/UIScrollViewCanvasRenderCmd.js",
+ "extensions/ccui/uiwidgets/scroll-widget/UIScrollViewWebGLRenderCmd.js"
+ ],
+ "cocostudio" : [
+ "core", "tilemap", "particle", "shape-nodes", "ccui",
+
+ "extensions/cocostudio/components/CCComponent.js",
+ "extensions/cocostudio/components/CCComponentContainer.js",
+ "extensions/ccui/layouts/UILayoutComponent.js",
+ "extensions/cocostudio/CocoStudio.js",
+
+ "extensions/cocostudio/armature/utils/CCArmatureDefine.js",
+ "extensions/cocostudio/armature/utils/CCDataReaderHelper.js",
+ "extensions/cocostudio/armature/utils/CCSpriteFrameCacheHelper.js",
+ "extensions/cocostudio/armature/utils/CCTransformHelp.js",
+ "extensions/cocostudio/armature/utils/CCTweenFunction.js",
+ "extensions/cocostudio/armature/utils/CCUtilMath.js",
+ "extensions/cocostudio/armature/utils/CCArmatureDataManager.js",
+ "extensions/cocostudio/armature/datas/CCDatas.js",
+ "extensions/cocostudio/armature/display/CCDecorativeDisplay.js",
+ "extensions/cocostudio/armature/display/CCDisplayFactory.js",
+ "extensions/cocostudio/armature/display/CCDisplayManager.js",
+ "extensions/cocostudio/armature/display/CCSkin.js",
+ "extensions/cocostudio/armature/display/CCSkinRenderCmd.js",
+ "extensions/cocostudio/armature/animation/CCProcessBase.js",
+ "extensions/cocostudio/armature/animation/CCArmatureAnimation.js",
+ "extensions/cocostudio/armature/animation/CCTween.js",
+ "extensions/cocostudio/armature/physics/CCColliderDetector.js",
+ "extensions/cocostudio/armature/CCArmature.js",
+ "extensions/cocostudio/armature/CCArmatureCanvasRenderCmd.js",
+ "extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js",
+ "extensions/cocostudio/armature/CCBone.js",
+
+ "extensions/cocostudio/action/CCActionFrame.js",
+ "extensions/cocostudio/action/CCActionManager.js",
+ "extensions/cocostudio/action/CCActionNode.js",
+ "extensions/cocostudio/action/CCActionObject.js",
+
+ "extensions/cocostudio/components/CCComAttribute.js",
+ "extensions/cocostudio/components/CCComAudio.js",
+ "extensions/cocostudio/components/CCComController.js",
+ "extensions/cocostudio/components/CCComRender.js",
+
+ "extensions/cocostudio/trigger/ObjectFactory.js",
+ "extensions/cocostudio/trigger/TriggerBase.js",
+ "extensions/cocostudio/trigger/TriggerMng.js",
+ "extensions/cocostudio/trigger/TriggerObj.js",
+
+ "extensions/cocostudio/timeline/ActionTimeline.js",
+ "extensions/cocostudio/timeline/Frame.js",
+ "extensions/cocostudio/timeline/Timeline.js",
+
+ "extensions/cocostudio/timeline/CCSkinNode.js",
+ "extensions/cocostudio/timeline/CCBoneNode.js",
+ "extensions/cocostudio/timeline/CCSkeletonNode.js",
+
+ "extensions/cocostudio/loader/load.js",
+ "extensions/cocostudio/loader/parsers/scene-1.x.js",
+ "extensions/cocostudio/loader/parsers/uiParser-1.x.js",
+ "extensions/cocostudio/loader/parsers/action-1.x.js",
+ "extensions/cocostudio/loader/parsers/action-2.x.js",
+ "extensions/cocostudio/loader/parsers/timelineParser-1.x.js",
+ "extensions/cocostudio/loader/parsers/timelineParser-2.x.js",
+ "extensions/cocostudio/loader/parsers/compatible.js"
+
+
+ ],
+ "gui" : [
+ "core", "clipping-nodes", "render-texture", "actions", "progress-timer",
+
+ "extensions/gui/control-extension/CCControl.js",
+ "extensions/gui/control-extension/CCControlButton.js",
+ "extensions/gui/control-extension/CCControlUtils.js",
+ "extensions/gui/control-extension/CCInvocation.js",
+ "extensions/gui/control-extension/CCMenuPassive.js",
+ "extensions/gui/control-extension/CCControlSaturationBrightnessPicker.js",
+ "extensions/gui/control-extension/CCControlHuePicker.js",
+ "extensions/gui/control-extension/CCControlColourPicker.js",
+ "extensions/gui/control-extension/CCControlSlider.js",
+ "extensions/gui/control-extension/CCControlSwitch.js",
+ "extensions/gui/control-extension/CCControlStepper.js",
+ "extensions/gui/control-extension/CCControlPotentiometer.js",
+ "extensions/gui/scrollview/CCScrollView.js",
+ "extensions/gui/scrollview/CCScrollViewCanvasRenderCmd.js",
+ "extensions/gui/scrollview/CCScrollViewWebGLRenderCmd.js",
+ "extensions/gui/scrollview/CCSorting.js",
+ "extensions/gui/scrollview/CCTableView.js"
+ ],
+
+ "pluginx" : [
+ "core",
+
+ "external/pluginx/Plugin.js"
+ ],
+ "plugin-facebook" : [
+ "external/pluginx/platform/facebook_sdk.js",
+ "external/pluginx/platform/facebook.js"
+ ],
+
+ "spine":[
+ "core",
+
+ "extensions/spine/Spine.js",
+ "extensions/spine/CCSkeleton.js",
+ "extensions/spine/CCSkeletonAnimation.js",
+ "extensions/spine/CCSkeletonTexture.js",
+ "extensions/spine/CCSkeletonCanvasRenderCmd.js",
+ "extensions/spine/CCSkeletonWebGLRenderCmd.js"
+ ],
+ "gaf":[
+ "core",
+
+ "external/gaf/GAFMacros.js",
+ "external/gaf/GAFBoot.js",
+ "external/gaf/Library/GAFAssetPreload.js",
+ "external/gaf/Library/GAFAsset.js",
+ "external/gaf/Library/GAFObject.js",
+ "external/gaf/Library/GAFTimeLine.js",
+ "external/gaf/Library/GAFTextField.js",
+ "external/gaf/Library/GAFSprite.js",
+ "external/gaf/Library/GAFMask.js",
+ "external/gaf/Library/GAFSpriteCanvasRenderCmd.js",
+ "external/gaf/Library/GAFSpriteWebGLRenderCmd.js",
+ "external/gaf/Library/GAFTimeLineProto.js",
+ "external/gaf/Library/GAFSpriteProto.js",
+ "external/gaf/Library/GAFMaskProto.js",
+ "external/gaf/Library/GAFTags.js",
+ "external/gaf/Library/GAFLoader.js",
+ "external/gaf/Library/GAFDataReader.js",
+ "external/gaf/Library/GAFShaders.js",
+ "external/gaf/Library/GAFShaderManager.js",
+ "external/gaf/Library/GAFAtlasLoader.js"
+ ],
+ "extensions" : ["gui", "ccbreader", "editbox", "cocostudio", "spine", "ccpool"],
+
+ "box2d" : [
+ "core", "physics",
+
+ "external/box2d/box2d.js"
+ ],
+ "chipmunk" : [
+ "core", "physics",
+
+ "external/chipmunk/chipmunk.js"
+ ],
+ "runtime":[
+ "core",
+ "extensions/runtime/CCLoaderLayer.js"
+ ],
+ "socketio" : [
+ "external/socketio/socket.io.min.js"
+ ],
+ "external" : ["box2d", "chipmunk", "socketio", "pluginx", "gaf"]
+ },
+ "bootFile" : "CCBoot.js"
+}
diff --git a/samples b/samples
deleted file mode 160000
index ab33b257d2..0000000000
--- a/samples
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ab33b257d2f3f1093c8e42abbdf41a8643a77c23
diff --git a/template/build.xml b/template/build.xml
deleted file mode 100644
index e8394e89be..0000000000
--- a/template/build.xml
+++ /dev/null
@@ -1,187 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/template/cocos2d-jsb.js b/template/cocos2d-jsb.js
deleted file mode 100755
index 879b2486cf..0000000000
--- a/template/cocos2d-jsb.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
-
- http://www.cocos2d-x.org
-
-
- 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.
- ****************************************************************************/
-
-// boot code needed for cocos2d + JS bindings.
-// Not needed by cocos2d-html5
-
-require("jsb.js");
-
-var appFiles = [
- 'src/resource.js',
- 'src/myApp.js'
-];
-
-cc.dumpConfig();
-
-for (var i = 0; i < appFiles.length; i++) {
- require(appFiles[i]);
-}
-
-var director = cc.Director.getInstance();
-
-//var screenSize = cc.EGLView.getInstance().getFrameSize();
-var screenSize = cc.size(320,480)
-var resourceSize = cc.size(800, 450);
-var designSize = cc.size(800, 450);
-
-var searchPaths = [];
-var resDirOrders = [];
-
-searchPaths.push("res");
-cc.FileUtils.getInstance().setSearchPaths(searchPaths);
-
-var platform = cc.Application.getInstance().getTargetPlatform();
-if (platform == cc.TARGET_PLATFORM.MOBILE_BROWSER) {
- if (screenSize.height > 450) {
- resDirOrders.push("HD");
- }
- else {
- resourceSize = cc.size(400, 225);
- designSize = cc.size(400, 225);
- resDirOrders.push("Normal");
- }
-}
-else if (platform == cc.TARGET_PLATFORM.PC_BROWSER) {
- resDirOrders.push("HD");
-}
-else if (platform == cc.TARGET_PLATFORM.IPHONE) {
- resDirOrders.push("Normal");
-}
-else if (platform == cc.TARGET_PLATFORM.IPAD) {
- resDirOrders.push("HD");
-}
-
-cc.FileUtils.getInstance().setSearchResolutionsOrder(resDirOrders);
-
-director.setContentScaleFactor(resourceSize.width / designSize.width);
-
-//cc.EGLView.getInstance().setDesignResolutionSize(designSize.width, designSize.height, cc.RESOLUTION_POLICY.SHOW_ALL);
-
-
-director.setDisplayStats(true);
-director.setAnimationInterval(1.0 / 60);
-var mainScene = new MyScene();
-director.runWithScene(mainScene);
-
diff --git a/template/cocos2d.js b/template/cocos2d.js
deleted file mode 100644
index c21c5a771e..0000000000
--- a/template/cocos2d.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2008-2010 Ricardo Quesada
- Copyright (c) 2011 Zynga Inc.
-
- http://www.cocos2d-x.org
-
-
- 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.
- ****************************************************************************/
-(function () {
- var d = document;
- var c = {
- COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
- box2d:false,
- chipmunk:false,
- showFPS:true,
- loadExtension:false,
- frameRate:60,
- renderMode:0, //Choose of RenderMode: 0(default), 1(Canvas only), 2(WebGL only)
- tag:'gameCanvas', //the dom element to run cocos2d on
- engineDir:'../cocos2d/',
- //SingleEngineFile:'',
- appFiles:[
- 'src/resource.js',
- 'src/myApp.js'//add your own files in order here
- ]
- };
-
- if(!d.createElement('canvas').getContext){
- var s = d.createElement('div');
- s.innerHTML = 'Your browser does not support HTML5 canvas! ' +
- 'Google Chrome is a browser that combines a minimal design with sophisticated technology to make the web faster, safer, and easier.Click the logo to download.
' +
- ' ';
- var p = d.getElementById(c.tag).parentNode;
- p.style.background = 'none';
- p.style.border = 'none';
- p.insertBefore(s,d.getElementById(c.tag));
-
- d.body.style.background = '#ffffff';
- return;
- }
-
-
- window.addEventListener('DOMContentLoaded', function () {
- this.removeEventListener('DOMContentLoaded', arguments.callee, false);
- //first load engine file if specified
- var s = d.createElement('script');
- /*********Delete this section if you have packed all files into one*******/
- if (c.SingleEngineFile && !c.engineDir) {
- s.src = c.SingleEngineFile;
-
- var loadJsImg = document.createElement('img');
- loadJsImg.src = "data:image/gif;base64,R0lGODlhEAAQALMNAD8/P7+/vyoqKlVVVX9/fxUVFUBAQGBgYMDAwC8vL5CQkP///wAAAP///wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAANACwAAAAAEAAQAAAEO5DJSau9OOvNex0IMnDIsiCkiW6g6BmKYlBFkhSUEgQKlQCARG6nEBwOgl+QApMdCIRD7YZ5RjlGpCUCACH5BAUAAA0ALAAAAgAOAA4AAAQ6kLGB0JA4M7QW0hrngRllkYyhKAYqKUGguAws0ypLS8JxCLQDgXAIDg+FRKIA6v0SAECCBpXSkstMBAAh+QQFAAANACwAAAAACgAQAAAEOJDJORAac6K1kDSKYmydpASBUl0mqmRfaGTCcQgwcxDEke+9XO2WkxQSiUIuAQAkls0n7JgsWq8RACH5BAUAAA0ALAAAAAAOAA4AAAQ6kMlplDIzTxWC0oxwHALnDQgySAdBHNWFLAvCukc215JIZihVIZEogDIJACBxnCSXTcmwGK1ar1hrBAAh+QQFAAANACwAAAAAEAAKAAAEN5DJKc4RM+tDyNFTkSQF5xmKYmQJACTVpQSBwrpJNteZSGYoFWjIGCAQA2IGsVgglBOmEyoxIiMAIfkEBQAADQAsAgAAAA4ADgAABDmQSVZSKjPPBEDSGucJxyGA1XUQxAFma/tOpDlnhqIYN6MEAUXvF+zldrMBAjHoIRYLhBMqvSmZkggAIfkEBQAADQAsBgAAAAoAEAAABDeQyUmrnSWlYhMASfeFVbZdjHAcgnUQxOHCcqWylKEohqUEAYVkgEAMfkEJYrFA6HhKJsJCNFoiACH5BAUAAA0ALAIAAgAOAA4AAAQ3kMlJq704611SKloCAEk4lln3DQgyUMJxCBKyLAh1EMRR3wiDQmHY9SQslyIQUMRmlmVTIyRaIgA7";
-
- var canvasNode = document.getElementById(c.tag);
- canvasNode.style.backgroundColor = "black";
- canvasNode.parentNode.appendChild(loadJsImg);
-
- var canvasStyle = getComputedStyle?getComputedStyle(canvasNode):canvasNode.currentStyle;
- loadJsImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - loadJsImg.width)/2 + "px";
- loadJsImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - loadJsImg.height)/2 + "px";
- loadJsImg.style.position = "absolute";
- loadJsImg.id = "cocos2d_loadJsImg";
- }
- else if (c.engineDir && !c.SingleEngineFile) {
- s.src = c.engineDir + 'platform/jsloader.js';
- }
- else {
- alert('You must specify either the single engine file OR the engine directory in "cocos2d.js"');
- }
- /*********Delete this section if you have packed all files into one*******/
-
- //s.src = 'myTemplate.js'; //IMPORTANT: Un-comment this line if you have packed all files into one
-
- d.body.appendChild(s);
- document.ccConfig = c;
- s.id = 'cocos2d-html5';
- //else if single file specified, load singlefile
- });
-})();
diff --git a/template/index.html b/template/index.html
index f0db646cfc..e0f577b927 100644
--- a/template/index.html
+++ b/template/index.html
@@ -4,7 +4,7 @@
Cocos2d-html5 Hello World test
-
+
@@ -19,9 +19,11 @@
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
+
+
-
-
+
+